From bc4a19c69bcc3dbad7106b868fb2b4fad05b3d20 Mon Sep 17 00:00:00 2001 From: hyzboy Date: Mon, 17 Jun 2019 10:37:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0CreateRenderableSphere?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/Vulkan/SceneTree.cpp | 11 +- inc/hgl/graph/InlineGeometry.h | 13 +- inc/hgl/graph/VertexBuffer.h | 4 - src/SceneGraph/InlineGeometry.cpp | 189 +++++++++++++++++++++++++++--- 4 files changed, 181 insertions(+), 36 deletions(-) diff --git a/example/Vulkan/SceneTree.cpp b/example/Vulkan/SceneTree.cpp index 34eaf4bf..a3321770 100644 --- a/example/Vulkan/SceneTree.cpp +++ b/example/Vulkan/SceneTree.cpp @@ -27,7 +27,7 @@ private: vulkan::Material * material =nullptr; vulkan::DescriptorSets * descriptor_sets =nullptr; - vulkan::Renderable * ro_cube =nullptr; + vulkan::Renderable * renderable_object =nullptr; vulkan::Pipeline * pipeline_line =nullptr; @@ -58,9 +58,10 @@ private: void CreateRenderObject() { - struct CubeCreateInfo cci; + //struct CubeCreateInfo cci; - ro_cube=CreateCube(db,material,&cci); + //renderable_object=CreateCube(db,material,&cci); + renderable_object=CreateRenderableSphere(db,material,16); } bool InitUBO() @@ -74,8 +75,6 @@ private: bool InitPipeline() { - constexpr os_char PIPELINE_FILENAME[]=OS_TEXT("2DSolid.pipeline"); - { vulkan::PipelineCreater *pipeline_creater=new vulkan::PipelineCreater(device,material,device->GetRenderPass(),device->GetExtent()); pipeline_creater->SetDepthTest(true); @@ -103,7 +102,7 @@ private: uint count; float size; - RenderableInstance *ri=db->CreateRenderableInstance(pipeline_line,descriptor_sets,ro_cube); + RenderableInstance *ri=db->CreateRenderableInstance(pipeline_line,descriptor_sets,renderable_object); for(uint i=0;i<360;i++) { diff --git a/inc/hgl/graph/InlineGeometry.h b/inc/hgl/graph/InlineGeometry.h index 54fa623f..8eb4de72 100644 --- a/inc/hgl/graph/InlineGeometry.h +++ b/inc/hgl/graph/InlineGeometry.h @@ -76,18 +76,11 @@ namespace hgl * 创建一个中心坐标为0,0,0,长宽高为1的立方体 */ vulkan::Renderable *CreateCube(SceneDB *db,vulkan::Material *mtl,const CubeCreateInfo *cci); - - struct BoundingBoxCreateInfo - { - AABB bounding_box; - };// - + /** - * 创建一个空心立方体,使用绑定盒的真实坐标 + * 创建一个球心坐标为0,0,0,半径为1的球体 */ - vulkan::Renderable *CreateBoundingBox(SceneDB *db,vulkan::Material *mtl,const BoundingBoxCreateInfo *bbci); - - //vulkan::Renderable *CreateSphere(SceneDB *db,vulkan::Material *mtl,const uint ); + vulkan::Renderable *CreateRenderableSphere(SceneDB *db,vulkan::Material *mtl,const uint numberSlices); }//namespace graph };//namespace hgl #endif//HGL_GRAPH_INLINE_GEOMETRY_INCLUDE diff --git a/inc/hgl/graph/VertexBuffer.h b/inc/hgl/graph/VertexBuffer.h index 22a9d9ed..9edbb5aa 100644 --- a/inc/hgl/graph/VertexBuffer.h +++ b/inc/hgl/graph/VertexBuffer.h @@ -79,10 +79,6 @@ namespace hgl */ void End() { - //ChangeVertexBuffer( ((char *)start )-((char *)mem_type), - // ((char *)access)-((char *)start), - // start); - access=nullptr; start=nullptr; } diff --git a/src/SceneGraph/InlineGeometry.cpp b/src/SceneGraph/InlineGeometry.cpp index 84adfa7f..f080f52b 100644 --- a/src/SceneGraph/InlineGeometry.cpp +++ b/src/SceneGraph/InlineGeometry.cpp @@ -372,35 +372,192 @@ namespace hgl db->Add(render_obj); return(render_obj); } - - vulkan::Renderable *CreateBoundingBox(SceneDB *db,vulkan::Material *mtl,const BoundingBoxCreateInfo *bbci) + + template vulkan::IndexBuffer *CreateSphereIndices(vulkan::IndexBuffer *ibo,uint numberParallels,const uint numberSlices) { - vec side[24]; + T *tp=(T *)ibo->Map(); - bbci->bounding_box.ToEdgeList(side); + for (uint i = 0; i < numberParallels; i++) + { + for (uint j = 0; j < numberSlices; j++) + { + *tp= i * (numberSlices + 1) + j; ++tp; + *tp=(i + 1) * (numberSlices + 1) + j; ++tp; + *tp=(i + 1) * (numberSlices + 1) + (j + 1); ++tp; + *tp= i * (numberSlices + 1) + j; ++tp; + *tp=(i + 1) * (numberSlices + 1) + (j + 1); ++tp; + *tp= i * (numberSlices + 1) + (j + 1); ++tp; + } + } + + ibo->Unmap(); + return ibo; + } + + namespace + { + void glusQuaternionRotateRyf(float quaternion[4], const float angle) + { + float halfAngleRadian = hgl_ang2rad(angle) * 0.5f; + + quaternion[0] = 0.0f; + quaternion[1] = sinf(halfAngleRadian); + quaternion[2] = 0.0f; + quaternion[3] = cosf(halfAngleRadian); + } + + void glusQuaternionGetMatrix4x4f(float matrix[16], const float quaternion[4]) + { + float x = quaternion[0]; + float y = quaternion[1]; + float z = quaternion[2]; + float w = quaternion[3]; + + matrix[0] = 1.0f - 2.0f * y * y - 2.0f * z * z; + matrix[1] = 2.0f * x * y + 2.0f * w * z; + matrix[2] = 2.0f * x * z - 2.0f * w * y; + matrix[3] = 0.0f; + + matrix[4] = 2.0f * x * y - 2.0f * w * z; + matrix[5] = 1.0f - 2.0f * x * x - 2.0f * z * z; + matrix[6] = 2.0f * y * z + 2.0f * w * x; + matrix[7] = 0.0f; + + matrix[8] = 2.0f * x * z + 2.0f * w * y; + matrix[9] = 2.0f * y * z - 2.0f * w * x; + matrix[10] = 1.0f - 2.0f * x * x - 2.0f * y * y; + matrix[11] = 0.0f; + + matrix[12] = 0.0f; + matrix[13] = 0.0f; + matrix[14] = 0.0f; + matrix[15] = 1.0f; + } + + void glusMatrix4x4MultiplyVector3f(float result[3], const float matrix[16], const float vector[3]) + { + int i; + + float temp[3]; + + for (i = 0; i < 3; i++) + { + temp[i] = matrix[i] * vector[0] + matrix[4 + i] * vector[1] + matrix[8 + i] * vector[2]; + } + + for (i = 0; i < 3; i++) + { + result[i] = temp[i]; + } + } + } + + /** + * 创建一个球体的可渲染数据,球心为0,0,0,半径为1 + * @param numberSlices 切片数 + * @return 可渲染数据 + */ + vulkan::Renderable *CreateRenderableSphere(SceneDB *db,vulkan::Material *mtl,const uint numberSlices) + { const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); vulkan::Renderable *render_obj=nullptr; + + const int vertex_binding=vsm->GetStageInputBinding("Vertex"); + + if(vertex_binding==-1) + return(nullptr); + + uint numberParallels = (numberSlices+1) / 2; + uint numberVertices = (numberParallels + 1) * (numberSlices + 1); + uint numberIndices = numberParallels * numberSlices * 6; + + const double angleStep = double(2.0f * HGL_PI) / ((double) numberSlices); + + // used later to help us calculating tangents vectors + float helpVector[3] = { 1.0f, 0.0f, 0.0f }; + float helpQuaternion[4]; + float helpMatrix[16]; + float tex_x; + + VB3f *vertex =new VB3f(numberVertices); + VB3f *normal =nullptr; + VB3f *tangent =nullptr; + VB2f *tex_coord =nullptr; + + render_obj=mtl->CreateRenderable(vertex->GetCount()); + + const int normal_binding=vsm->GetStageInputBinding("Normal"); + const int tangent_binding=vsm->GetStageInputBinding("Tangent"); + const int texcoord_binding=vsm->GetStageInputBinding("TexCoord"); + + float *vp=(float *)vertex->Begin(); + float *np=nullptr; + float *tp=nullptr; + float *tc=nullptr; + + if(normal_binding !=-1){normal =new VB3f(numberVertices);np=(float *)normal->Begin();} + if(tangent_binding !=-1){tangent =new VB3f(numberVertices);tp=(float *)tangent->Begin();} + if(texcoord_binding !=-1){tex_coord =new VB2f(numberVertices);tc=(float *)tex_coord->Begin();} + + for (uint i = 0; i < numberParallels + 1; i++) { - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); + for (uint j = 0; j < numberSlices + 1; j++) + { + float x=sin(angleStep * (double) i) * sin(angleStep * (double) j); + float y=cos(angleStep * (double) i); + float z=sin(angleStep * (double) i) * cos(angleStep * (double) j); - if(vertex_binding==-1) - return(nullptr); + *vp=x;++vp; + *vp=y;++vp; + *vp=z;++vp; - VB3f *vertex=new VB3f(24); + if(normal) + { + *np=x;++np; + *np=y;++np; + *np=z;++np; + } - vertex->Begin(); - vertex->Write(side,24); - vertex->End(); + if(tex_coord) + { + tex_x=(float) j / (float) numberSlices; - render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - delete vertex; + *tc=tex_x;++tc; + *tc=1.0f - (float) i / (float) numberParallels;++tc; + + if(tangent) + { + // use quaternion to get the tangent vector + glusQuaternionRotateRyf(helpQuaternion, 360.0f * tex_x); + glusQuaternionGetMatrix4x4f(helpMatrix, helpQuaternion); + + glusMatrix4x4MultiplyVector3f(tp, helpMatrix, helpVector); + tp+=3; + } + } + } + } + + if(tex_coord){tex_coord ->End();render_obj->Set(texcoord_binding, db->CreateVBO(tex_coord ));delete tex_coord;} + if(tangent ){tangent ->End();render_obj->Set(tangent_binding, db->CreateVBO(tangent ));delete tangent; } + if(normal ){normal ->End();render_obj->Set(normal_binding, db->CreateVBO(normal ));delete normal; } + + vertex->End(); + render_obj->Set(vertex_binding,db->CreateVBO(vertex)); + render_obj->SetBoundingBox(vertex->GetAABB()); + delete vertex; + + { + uint indices_number=numberParallels * numberSlices * 6; + + if(numberVertices<=0xffff) + render_obj->Set(CreateSphereIndices(db->CreateIBO16(indices_number),numberParallels,numberSlices)); + else + render_obj->Set(CreateSphereIndices(db->CreateIBO32(indices_number),numberParallels,numberSlices)); } - db->Add(render_obj); return render_obj; }