From c84b522703fa8ace5907c41bb0cc66ad6a412ff5 Mon Sep 17 00:00:00 2001 From: hyzboy Date: Mon, 17 Jun 2019 20:25:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=A4=9A=E7=A7=8D=E5=86=85?= =?UTF-8?q?=E5=B5=8C=E5=87=A0=E4=BD=95=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/Vulkan/InlineGeometryScene.cpp | 66 +- inc/hgl/graph/InlineGeometry.h | 44 + inc/hgl/graph/VertexBuffer.h | 7 + src/SceneGraph/InlineGeometry.cpp | 1072 ++++++++++++++++++------ 4 files changed, 944 insertions(+), 245 deletions(-) diff --git a/example/Vulkan/InlineGeometryScene.cpp b/example/Vulkan/InlineGeometryScene.cpp index 9821c5cd..154bddfd 100644 --- a/example/Vulkan/InlineGeometryScene.cpp +++ b/example/Vulkan/InlineGeometryScene.cpp @@ -26,10 +26,15 @@ private: vulkan::Renderable *ro_plane_grid, *ro_cube, - *ro_sphere; + *ro_sphere, + *ro_dome, + *ro_torus, + *ro_cylinder, + *ro_cone; - vulkan::Pipeline *pipeline_line =nullptr, - *pipeline_solid =nullptr; + vulkan::Pipeline *pipeline_line =nullptr, + *pipeline_solid =nullptr, + *pipeline_twoside =nullptr; private: @@ -77,6 +82,48 @@ private: { ro_sphere=CreateRenderableSphere(db,material,16); } + + { + DomeCreateInfo dci; + + dci.radius=100; + dci.numberSlices=16; + + ro_dome=CreateRenderableDome(db,material,&dci); + } + + { + TorusCreateInfo tci; + + tci.innerRadius=50; + tci.outerRadius=70; + + tci.numberSlices=32; + tci.numberStacks=16; + + ro_torus=CreateRenderableTorus(db,material,&tci); + } + + { + CylinderCreateInfo cci; + + cci.halfExtend=10; + cci.radius=10; + cci.numberSlices=16; + + ro_cylinder=CreateRenderableCylinder(db,material,&cci); + } + + { + ConeCreateInfo cci; + + cci.halfExtend=10; + cci.radius=10; + cci.numberSlices=16; + cci.numberStacks=1; + + ro_cone=CreateRenderableCone(db,material,&cci); + } } bool InitUBO() @@ -99,9 +146,14 @@ private: db->Add(pipeline_line); pipeline_creater->Set(PRIM_TRIANGLES); + pipeline_creater->SetPolygonMode(VK_POLYGON_MODE_LINE); pipeline_solid=pipeline_creater->Create(); db->Add(pipeline_solid); + pipeline_creater->SetCullMode(VK_CULL_MODE_NONE); + pipeline_twoside=pipeline_creater->Create(); + db->Add(pipeline_twoside); + delete pipeline_creater; if(!pipeline_line) @@ -116,8 +168,12 @@ private: bool InitScene() { render_root.Add(db->CreateRenderableInstance(pipeline_line,descriptor_sets,ro_plane_grid)); - render_root.Add(db->CreateRenderableInstance(pipeline_line,descriptor_sets,ro_cube ),translate(-10,0,0)*scale(10,10,10)); - render_root.Add(db->CreateRenderableInstance(pipeline_line,descriptor_sets,ro_sphere ),translate( 10,0,0)*scale(10,10,10)); + render_root.Add(db->CreateRenderableInstance(pipeline_twoside,descriptor_sets,ro_dome)); + render_root.Add(db->CreateRenderableInstance(pipeline_twoside,descriptor_sets,ro_torus)); + render_root.Add(db->CreateRenderableInstance(pipeline_solid,descriptor_sets,ro_cube ),translate(-10, 0,10)*scale(10,10,10)); + render_root.Add(db->CreateRenderableInstance(pipeline_solid,descriptor_sets,ro_sphere ),translate( 10, 0,10)*scale(10,10,10)); + render_root.Add(db->CreateRenderableInstance(pipeline_solid,descriptor_sets,ro_cylinder ),translate( 0, 16, 0)); + render_root.Add(db->CreateRenderableInstance(pipeline_solid,descriptor_sets,ro_cone ),translate( 0,-16, 0)); render_root.RefreshMatrix(); render_root.ExpendToList(&render_list); diff --git a/inc/hgl/graph/InlineGeometry.h b/inc/hgl/graph/InlineGeometry.h index 8eb4de72..5d540196 100644 --- a/inc/hgl/graph/InlineGeometry.h +++ b/inc/hgl/graph/InlineGeometry.h @@ -81,6 +81,50 @@ namespace hgl * 创建一个球心坐标为0,0,0,半径为1的球体 */ vulkan::Renderable *CreateRenderableSphere(SceneDB *db,vulkan::Material *mtl,const uint numberSlices); + + struct DomeCreateInfo + { + float radius; + uint numberSlices; + };//struct DomeCreateInfo + + /** + * 创建一个穹顶 + */ + vulkan::Renderable *CreateRenderableDome(SceneDB *db,vulkan::Material *mtl, const DomeCreateInfo *); + + struct TorusCreateInfo + { + float innerRadius, + outerRadius; + + uint numberSlices, + numberStacks; + };//struct TorusCreateInfo + + /** + * 创建一个圆环 + */ + vulkan::Renderable *CreateRenderableTorus(SceneDB *db,vulkan::Material *mtl,TorusCreateInfo *tci); + + struct CylinderCreateInfo + { + float halfExtend, //高度 + radius; //半径 + uint numberSlices; + };//struct CylinderCreateInfo + + vulkan::Renderable *CreateRenderableCylinder(SceneDB *db,vulkan::Material *mtl,CylinderCreateInfo *cci); + + struct ConeCreateInfo + { + float halfExtend, //高度 + radius; //半径 + uint numberSlices, //圆切分精度 + numberStacks; //柱高层数 + };//struct ConeCreateInfo + + vulkan::Renderable *CreateRenderableCone(SceneDB *db,vulkan::Material *mtl,ConeCreateInfo *cci); }//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 9edbb5aa..4aed8518 100644 --- a/inc/hgl/graph/VertexBuffer.h +++ b/inc/hgl/graph/VertexBuffer.h @@ -37,6 +37,13 @@ namespace hgl virtual ~VertexBufferBase()=default; + void BufferData(const T *ptr) + { + if(!ptr)return; + + memcpy(mem_type,ptr,total_bytes); + } + /** * 取得数据区地址 * @param offset 从第几个数据开始访问 diff --git a/src/SceneGraph/InlineGeometry.cpp b/src/SceneGraph/InlineGeometry.cpp index f080f52b..9fa54d64 100644 --- a/src/SceneGraph/InlineGeometry.cpp +++ b/src/SceneGraph/InlineGeometry.cpp @@ -7,49 +7,166 @@ namespace hgl { namespace graph { + namespace + { + template + struct GeometryCreater + { + SceneDB *db; + vulkan::Material *mtl; + + const vulkan::VertexShaderModule *vsm=nullptr; + + vulkan::Renderable *render_obj=nullptr; + + int vertex_binding =-1; + int color_binding =-1; + int normal_binding =-1; + int tangent_binding =-1; + int texcoord_binding=-1; + + VERTEX_VB_FORMAT *vertex =nullptr; + VB4f *color =nullptr; + VB3f *normal =nullptr; + VB3f *tangent =nullptr; + VB2f *tex_coord =nullptr; + + vulkan::IndexBuffer *ibo=nullptr; + + public: + + GeometryCreater(SceneDB *sdb,vulkan::Material *m):db(sdb),mtl(m) + { + vsm=mtl->GetVertexShaderModule(); + + vertex_binding =vsm->GetStageInputBinding("Vertex"); + color_binding =vsm->GetStageInputBinding("Color"); + normal_binding =vsm->GetStageInputBinding("Normal"); + tangent_binding =vsm->GetStageInputBinding("Tangent"); + texcoord_binding=vsm->GetStageInputBinding("TexCoord"); + } + + ~GeometryCreater() + { + if(render_obj) + delete render_obj; + } + + bool Init(uint vertices_number) + { + if(vertex_binding==-1)return(false); + if(!vertices_number)return(false); + + render_obj=mtl->CreateRenderable(vertices_number); + + vertex =new VERTEX_VB_FORMAT(vertices_number); + if(color_binding !=-1)color =new VB4f(vertices_number); + if(normal_binding !=-1)normal =new VB3f(vertices_number); + if(tangent_binding !=-1)tangent =new VB3f(vertices_number); + if(texcoord_binding !=-1)tex_coord =new VB2f(vertices_number); + + return(true); + } + + void WriteVertex (const float *v){if(vertex )vertex ->BufferData(v);} + void WriteColor (const float *v){if(color )color ->BufferData(v);} + void WriteNormal (const float *v){if(normal )normal ->BufferData(v);} + void WriteTangent (const float *v){if(tangent )tangent ->BufferData(v);} + void WriteTexCoord (const float *v){if(tex_coord )tex_coord ->BufferData(v);} + + VERTEX_VB_FORMAT *GetVertex (){if(vertex )vertex ->Begin();return vertex;} + VB4f *GetColor (){if(color )color ->Begin();return color;} + VB3f *GetNormal (){if(normal )normal ->Begin();return normal;} + VB3f *GetTangent (){if(tangent )tangent ->Begin();return tangent;} + VB2f *GetTexCoord (){if(tex_coord )tex_coord ->Begin();return tex_coord;} + + float *GetVertexPointer (){return vertex ?(float *)vertex ->Begin():nullptr;} + float *GetColorPointer (){return color ?(float *)color ->Begin():nullptr;} + float *GetNormalPointer (){return normal ?(float *)normal ->Begin():nullptr;} + float *GetTangentPointer (){return tangent ?(float *)tangent ->Begin():nullptr;} + float *GetTexCoordPointer (){return tex_coord ?(float *)tex_coord ->Begin():nullptr;} + + uint16 *CreateIBO16(uint count,const uint16 *data=nullptr) + { + ibo=db->CreateIBO16(count,data); + return (uint16 *)ibo->Map(); + } + + uint32 *CreateIBO32(uint count,const uint32 *data=nullptr) + { + ibo=db->CreateIBO32(count,data); + return (uint32 *)ibo->Map(); + } + + private: + + void Finish(int binding,VertexBufferCreater *vb) + { + render_obj->Set(binding,db->CreateVBO(vb)); + delete vb; + } + + public: + + vulkan::Renderable *Finish() + { + if(vertex) + { + render_obj->SetBoundingBox(vertex->GetAABB()); + Finish(vertex_binding,vertex); + } + + if(color)Finish(color_binding,color); + if(normal)Finish(normal_binding,normal); + if(tangent)Finish(tangent_binding,tangent); + if(tex_coord)Finish(texcoord_binding,tex_coord); + + if(ibo) + { + ibo->Unmap(); + render_obj->Set(ibo); + } + + vulkan::Renderable *result=render_obj; + + db->Add(render_obj); + render_obj=nullptr; + return result; + } + };//struct GeometryCreater + + using GeometryCreater3D=GeometryCreater; + using GeometryCreater2D=GeometryCreater; + }//namespace + vulkan::Renderable *CreateRectangle(SceneDB *db,vulkan::Material *mtl,const RectangleCreateInfo *rci) { - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + GeometryCreater2D gc(db,mtl); - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); - - if(vertex_binding==-1) + if(!gc.Init(4)) return(nullptr); - VB2f *vertex=new VB2f(4); + VB2f *vertex=gc.GetVertex(); - vertex->Begin(); vertex->WriteRectFan(rci->scope); - vertex->End(); - vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - - delete vertex; - db->Add(render_obj); - return render_obj; + return gc.Finish(); } vulkan::Renderable *CreateRoundRectangle(SceneDB *db,vulkan::Material *mtl,const RoundRectangleCreateInfo *rci) { - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + GeometryCreater2D gc(db,mtl); - vulkan::Renderable *render_obj=nullptr; - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); - - if(vertex_binding==-1) - return(nullptr); - - VB2f *vertex=nullptr; + if(rci->radius==0||rci->round_per<=1) //这是要画矩形 if(rci->radius==0||rci->round_per<=1) //这是要画矩形 { - vertex=new VB2f(4); + if(!gc.Init(4)) + return(nullptr); + + VB2f *vertex=gc.GetVertex(); - vertex->Begin(); vertex->WriteRectFan(rci->scope); - vertex->End(); } else { @@ -58,9 +175,10 @@ namespace hgl if(radius>rci->scope.GetWidth()/2.0f)radius=rci->scope.GetWidth()/2.0f; if(radius>rci->scope.GetHeight()/2.0f)radius=rci->scope.GetHeight()/2.0f; - vertex=new VB2f(rci->round_per*4); - - vertex->Begin(); + if(!gc.Init(rci->round_per*4)) + return(nullptr); + + VB2f *vertex=gc.GetVertex(); vec2 *coord=new vec2[rci->round_per]; @@ -106,31 +224,19 @@ namespace hgl } delete[] coord; - - vertex->End(); } - - render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - - delete vertex; - db->Add(render_obj); - return render_obj; + + return gc.Finish(); } vulkan::Renderable *CreateCircle(SceneDB *db,vulkan::Material *mtl,const CircleCreateInfo *cci) - { - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + { + GeometryCreater2D gc(db,mtl); - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); - - if(vertex_binding==-1) + if(!gc.Init(cci->field_count+2)) return(nullptr); - VB2f *vertex=new VB2f(cci->field_count+2); - - vertex->Begin(); + VB2f *vertex=gc.GetVertex(); vertex->Write(cci->center.x,cci->center.y); @@ -144,29 +250,17 @@ namespace hgl vertex->Write(x,y); } - vertex->End(); - - vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - - delete vertex; - db->Add(render_obj); - return render_obj; + return gc.Finish(); } vulkan::Renderable *CreatePlaneGrid(SceneDB *db,vulkan::Material *mtl,const PlaneGridCreateInfo *pgci) { - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + GeometryCreater3D gc(db,mtl); - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); - - if(vertex_binding==-1) + if(!gc.Init(((pgci->step.u+1)+(pgci->step.v+1))*2)) return(nullptr); - VB3f *vertex=new VB3f(((pgci->step.u+1)+(pgci->step.v+1))*2); - - vertex->Begin(); + VB3f *vertex=gc.GetVertex(); for(uint row=0;row<=pgci->step.u;row++) { float pos=float(row)/float(pgci->step.u); @@ -182,41 +276,28 @@ namespace hgl vertex->WriteLine(to(pgci->coord[1],pgci->coord[2],pos), to(pgci->coord[0],pgci->coord[3],pos)); } - vertex->End(); - vulkan::Renderable *render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - - const int color_binding=vsm->GetStageInputBinding("Color"); - if(color_binding!=-1) + VB4f *color=gc.GetColor(); + if(color) { - VB4f *color=new VB4f(((pgci->step.u+1)+(pgci->step.v+1))*2); + for(uint row=0;row<=pgci->step.u;row++) + { + if((row%pgci->side_step.u)==0) + color->Fill(pgci->side_color,2); + else + color->Fill(pgci->color,2); + } - color->Begin(); - for(uint row=0;row<=pgci->step.u;row++) - { - if((row%pgci->side_step.u)==0) - color->Fill(pgci->side_color,2); - else - color->Fill(pgci->color,2); - } - - for(uint col=0;col<=pgci->step.v;col++) - { - if((col%pgci->side_step.v)==0) - color->Fill(pgci->side_color,2); - else - color->Fill(pgci->color,2); - } - color->End(); - - render_obj->Set(color_binding,db->CreateVBO(color)); + for(uint col=0;col<=pgci->step.v;col++) + { + if((col%pgci->side_step.v)==0) + color->Fill(pgci->side_color,2); + else + color->Fill(pgci->color,2); + } } - delete vertex; - db->Add(render_obj); - return render_obj; + return gc.Finish(); } vulkan::Renderable *CreatePlane(SceneDB *db,vulkan::Material *mtl,const PlaneCreateInfo *pci) @@ -226,69 +307,38 @@ namespace hgl const Vector3f xy_normal(0.0f,0.0f,1.0f); const Vector3f xy_tangent(1.0f,0.0f,0.0f); - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + GeometryCreater3D gc(db,mtl); + + if(!gc.Init(4)) + return(nullptr); + + gc.WriteVertex(xy_vertices); - vulkan::Renderable *render_obj=nullptr; { - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); + VB3f *normal=gc.GetNormal(); - if(vertex_binding==-1) - return(nullptr); - - VB3f *vertex=new VB3f(4,xy_vertices); - - render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - delete vertex; + if(normal)normal->Fill(xy_normal,4); } - if(render_obj) { - const int normal_binding=vsm->GetStageInputBinding("Normal"); + VB3f *tangent=gc.GetTangent(); - if(normal_binding!=-1) - { - VB3f *normal=new VB3f(4); + tangent->Fill(xy_tangent,4); + } - normal->Begin(); - normal->Fill(xy_normal,4); - normal->End(); + { + VB2f *tex_coord=gc.GetTexCoord(); - render_obj->Set(normal_binding,db->CreateVBO(normal)); - delete normal; - } - - const int tagent_binding=vsm->GetStageInputBinding("Tangent"); - - if(tagent_binding!=-1) - { - VB3f *tangent=new VB3f(4); - - tangent->Begin(); - tangent->Fill(xy_tangent,4); - tangent->End(); - - render_obj->Set(tagent_binding,db->CreateVBO(tangent)); - delete tangent; - } - - const int texcoord_binding=vsm->GetStageInputBinding("TexCoord"); - - if(texcoord_binding!=-1) + if(tex_coord) { xy_tex_coord[2]=xy_tex_coord[6]=pci->tile.x; xy_tex_coord[5]=xy_tex_coord[7]=pci->tile.y; - VB2f *tex_coord=new VB2f(4,xy_tex_coord); - - render_obj->Set(texcoord_binding,db->CreateVBO(tex_coord)); - delete tex_coord; + tex_coord->BufferData(xy_tex_coord); } } - db->Add(render_obj); - return render_obj; + return gc.Finish(); } vulkan::Renderable *CreateCube(SceneDB *db,vulkan::Material *mtl,const CubeCreateInfo *cci) @@ -314,46 +364,17 @@ namespace hgl 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f }; - const vulkan::VertexShaderModule *vsm=mtl->GetVertexShaderModule(); + GeometryCreater3D gc(db,mtl); - vulkan::Renderable *render_obj=nullptr; - { - const int vertex_binding=vsm->GetStageInputBinding("Vertex"); + if(!gc.Init(24)) + return(nullptr); - if(vertex_binding==-1) - return(nullptr); + gc.WriteVertex(points); + gc.WriteNormal(normals); + gc.WriteTangent(tangents); - VB3f *vertex=new VB3f(24,points); - - render_obj=mtl->CreateRenderable(vertex->GetCount()); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - delete vertex; - } - - const int normal_binding=vsm->GetStageInputBinding("Normal"); - - if(normal_binding!=-1) - { - VB3f *normal=new VB3f(24,normals); - - render_obj->Set(normal_binding,db->CreateVBO(normal)); - delete normal; - } - - const int tagent_binding=vsm->GetStageInputBinding("Tangent"); - - if(tagent_binding!=-1) - { - VB3f *tangent=new VB3f(24,tangents); - - render_obj->Set(tagent_binding,db->CreateVBO(tangent)); - delete tangent; - } - - const int texcoord_binding=vsm->GetStageInputBinding("TexCoord"); - - if(texcoord_binding!=-1) + VB2f *tc_vb=gc.GetTexCoord(); + if(tc_vb) { float *tc=tex_coords; for(uint i=0;i<24;i++) @@ -362,21 +383,15 @@ namespace hgl (*tc)*=cci->tile.y;++tc; } - VB2f *tex_coord=new VB2f(24,tex_coords); - - render_obj->Set(texcoord_binding,db->CreateVBO(tex_coord)); - delete tex_coord; + tc_vb->BufferData(tex_coords); } - render_obj->Set(db->CreateIBO16(6*2*3,indices)); - db->Add(render_obj); - return(render_obj); + gc.CreateIBO16(6*2*3,indices); + return gc.Finish(); } - template vulkan::IndexBuffer *CreateSphereIndices(vulkan::IndexBuffer *ibo,uint numberParallels,const uint numberSlices) + template void CreateSphereIndices(T *tp,uint numberParallels,const uint numberSlices) { - T *tp=(T *)ibo->Map(); - for (uint i = 0; i < numberParallels; i++) { for (uint j = 0; j < numberSlices; j++) @@ -390,13 +405,15 @@ namespace hgl *tp= i * (numberSlices + 1) + (j + 1); ++tp; } } - - ibo->Unmap(); - return ibo; } namespace - { + { + constexpr uint GLUS_VERTICES_FACTOR =4; + constexpr uint GLUS_VERTICES_DIVISOR=4; + constexpr uint GLUS_MAX_VERTICES =1048576; + constexpr uint GLUS_MAX_INDICES =GLUS_MAX_VERTICES*GLUS_VERTICES_FACTOR; + void glusQuaternionRotateRyf(float quaternion[4], const float angle) { float halfAngleRadian = hgl_ang2rad(angle) * 0.5f; @@ -406,6 +423,16 @@ namespace hgl quaternion[2] = 0.0f; quaternion[3] = cosf(halfAngleRadian); } + + void glusQuaternionRotateRzf(float quaternion[4], const float angle) + { + float halfAngleRadian = hgl_ang2rad(angle) * 0.5f; + + quaternion[0] = 0.0f; + quaternion[1] = 0.0f; + quaternion[2] = sinf(halfAngleRadian); + quaternion[3] = cosf(halfAngleRadian); + } void glusQuaternionGetMatrix4x4f(float matrix[16], const float quaternion[4]) { @@ -451,7 +478,7 @@ namespace hgl result[i] = temp[i]; } } - } + }//namespace /** * 创建一个球体的可渲染数据,球心为0,0,0,半径为1 @@ -459,15 +486,8 @@ namespace hgl * @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); + { + GeometryCreater3D gc(db,mtl); uint numberParallels = (numberSlices+1) / 2; uint numberVertices = (numberParallels + 1) * (numberSlices + 1); @@ -481,53 +501,41 @@ namespace hgl 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()); + if(!gc.Init(numberVertices)) + return(nullptr); - 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();} + float *vp=gc.GetVertexPointer(); + float *np=gc.GetNormalPointer(); + float *tp=gc.GetTangentPointer(); + float *tc=gc.GetTexCoordPointer(); for (uint i = 0; i < numberParallels + 1; i++) { 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); - + float y=sin(angleStep * (double) i) * cos(angleStep * (double) j); + float z=cos(angleStep * (double) i); + *vp=x;++vp; *vp=y;++vp; *vp=z;++vp; - if(normal) + if(np) { *np=x;++np; *np=y;++np; *np=z;++np; } - if(tex_coord) + if(tc) { tex_x=(float) j / (float) numberSlices; *tc=tex_x;++tc; *tc=1.0f - (float) i / (float) numberParallels;++tc; - if(tangent) + if(tp) { // use quaternion to get the tangent vector glusQuaternionRotateRyf(helpQuaternion, 360.0f * tex_x); @@ -539,30 +547,614 @@ namespace hgl } } } + + if(numberVertices<=0xffff) + CreateSphereIndices(gc.CreateIBO16(numberIndices),numberParallels,numberSlices); + else + CreateSphereIndices(gc.CreateIBO32(numberIndices),numberParallels,numberSlices); - 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; } + return gc.Finish(); + } + + vulkan::Renderable *CreateRenderableDome(SceneDB *db,vulkan::Material *mtl,const DomeCreateInfo *dci) + { + GeometryCreater3D gc(db,mtl); - vertex->End(); - render_obj->Set(vertex_binding,db->CreateVBO(vertex)); - render_obj->SetBoundingBox(vertex->GetAABB()); - delete vertex; + uint i, j; + uint numberParallels = dci->numberSlices / 4; + uint numberVertices = (numberParallels + 1) * (dci->numberSlices + 1); + uint numberIndices = numberParallels * dci->numberSlices * 6; + + float angleStep = (2.0f * HGL_PI) / ((float) dci->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; + + if (dci->numberSlices < 3 || numberVertices > GLUS_MAX_VERTICES || numberIndices > GLUS_MAX_INDICES) + return nullptr; + + if(!gc.Init(numberVertices)) + return(nullptr); + + float *vp=gc.GetVertexPointer(); + float *np=gc.GetNormalPointer(); + float *tp=gc.GetTangentPointer(); + float *tc=gc.GetTexCoordPointer(); + + for (i = 0; i < numberParallels + 1; i++) { - uint indices_number=numberParallels * numberSlices * 6; + for (j = 0; j < dci->numberSlices + 1; j++) + { + uint vertexIndex = (i * (dci->numberSlices + 1) + j) * 4; + uint normalIndex = (i * (dci->numberSlices + 1) + j) * 3; + uint tangentIndex = (i * (dci->numberSlices + 1) + j) * 3; + uint texCoordsIndex = (i * (dci->numberSlices + 1) + j) * 2; - if(numberVertices<=0xffff) - render_obj->Set(CreateSphereIndices(db->CreateIBO16(indices_number),numberParallels,numberSlices)); - else - render_obj->Set(CreateSphereIndices(db->CreateIBO32(indices_number),numberParallels,numberSlices)); + float x=dci->radius * sinf(angleStep * (float) i) * sinf(angleStep * (float) j); + float y=dci->radius * sinf(angleStep * (float) i) * cosf(angleStep * (float) j); + float z=dci->radius * cosf(angleStep * (float) i); + + *vp=x;++vp; + *vp=y;++vp; + *vp=z;++vp; + + if(np) + { + *np = x / dci->radius;++np; + *np = y / dci->radius;++np; + *np = z / dci->radius;++np; + } + + if(tc) + { + *tc = tex_x=(float) j / (float) dci->numberSlices;++tc; + *tc = 1.0f - (float) i / (float) numberParallels;++tc; + + if(tp) + { + // use quaternion to get the tangent vector + glusQuaternionRotateRyf(helpQuaternion, 360.0f * tex_x); + glusQuaternionGetMatrix4x4f(helpMatrix, helpQuaternion); + + glusMatrix4x4MultiplyVector3f(tp, helpMatrix, helpVector); + tp+=3; + } + } + } } + + if(numberVertices<=0xffff) + CreateSphereIndices(gc.CreateIBO16(numberIndices),numberParallels,dci->numberSlices); + else + CreateSphereIndices(gc.CreateIBO32(numberIndices),numberParallels,dci->numberSlices); - return render_obj; + return gc.Finish(); } - //vulkan::Renderable *CreateSphere(SceneDB *db,vulkan::Material *mtl,const SphereCreateInfo *sci) - //{ - //} + namespace + { + template + void CreateTorusIndices(T *tp,uint numberSlices,uint numberStacks) + { + // loop counters + uint sideCount, faceCount; + + // used to generate the indices + uint v0, v1, v2, v3; + + for (sideCount = 0; sideCount < numberSlices; ++sideCount) + { + for (faceCount = 0; faceCount < numberStacks; ++faceCount) + { + // get the number of the vertices for a face of the torus. They must be < numVertices + v0 = ((sideCount * (numberStacks + 1)) + faceCount); + v1 = (((sideCount + 1) * (numberStacks + 1)) + faceCount); + v2 = (((sideCount + 1) * (numberStacks + 1)) + (faceCount + 1)); + v3 = ((sideCount * (numberStacks + 1)) + (faceCount + 1)); + + // first triangle of the face, counter clock wise winding + *tp = v0; ++tp; + *tp = v1; ++tp; + *tp = v2; ++tp; + + // second triangle of the face, counter clock wise winding + *tp = v0; ++tp; + *tp = v2; ++tp; + *tp = v3; ++tp; + } + } + } + }//namespace + + vulkan::Renderable *CreateRenderableTorus(SceneDB *db,vulkan::Material *mtl,TorusCreateInfo *tci) + { + GeometryCreater3D gc(db,mtl); + + // s, t = parametric values of the equations, in the range [0,1] + float s = 0; + float t = 0; + + // sIncr, tIncr are increment values aplied to s and t on each loop iteration to generate the torus + float sIncr; + float tIncr; + + // to store precomputed sin and cos values + float cos2PIs, sin2PIs, cos2PIt, sin2PIt; + + uint sideCount,faceCount; + + uint numberVertices; + uint numberIndices; + + // used later to help us calculating tangents vectors + float helpVector[3] = { 0.0f, 1.0f, 0.0f }; + float helpQuaternion[4]; + float helpMatrix[16]; + + float torusRadius = (tci->outerRadius - tci->innerRadius) / 2.0f; + float centerRadius = tci->outerRadius - torusRadius; + + numberVertices = (tci->numberStacks + 1) * (tci->numberSlices + 1); + numberIndices = tci->numberStacks * tci->numberSlices * 2 * 3; // 2 triangles per face * 3 indices per triangle + + if (tci->numberSlices < 3 || tci->numberStacks < 3 || numberVertices > GLUS_MAX_VERTICES || numberIndices > GLUS_MAX_INDICES) + return(nullptr); + + sIncr = 1.0f / (float) tci->numberSlices; + tIncr = 1.0f / (float) tci->numberStacks; + + if(!gc.Init(numberVertices)) + return(nullptr); + + float *vp=gc.GetVertexPointer(); + float *np=gc.GetNormalPointer(); + float *tp=gc.GetTangentPointer(); + float *tc=gc.GetTexCoordPointer(); + + // generate vertices and its attributes + for (sideCount = 0; sideCount <= tci->numberSlices; ++sideCount, s += sIncr) + { + // precompute some values + cos2PIs = (float) cosf(2.0f * HGL_PI * s); + sin2PIs = (float) sinf(2.0f * HGL_PI * s); + + t = 0.0f; + for (faceCount = 0; faceCount <= tci->numberStacks; ++faceCount, t += tIncr) + { + // precompute some values + cos2PIt = (float) cosf(2.0f * HGL_PI * t); + sin2PIt = (float) sinf(2.0f * HGL_PI * t); + + // generate vertex and stores it in the right position + *vp = (centerRadius + torusRadius * cos2PIt) * cos2PIs; ++vp; + *vp = (centerRadius + torusRadius * cos2PIt) * sin2PIs; ++vp; + *vp = torusRadius * sin2PIt; ++vp; + + if(np) + { + // generate normal and stores it in the right position + // NOTE: cos (2PIx) = cos (x) and sin (2PIx) = sin (x) so, we can use this formula + // normal = {cos(2PIs)cos(2PIt) , sin(2PIs)cos(2PIt) ,sin(2PIt)} + *np = cos2PIs * cos2PIt; ++np; + *np = sin2PIs * cos2PIt; ++np; + *np = sin2PIt; ++np; + } + + if(tc) + { + // generate texture coordinates and stores it in the right position + *tc = s; ++tc; + *tc = t; ++tc; + } + + if(tp) + { + // use quaternion to get the tangent vector + glusQuaternionRotateRzf(helpQuaternion, 360.0f * s); + glusQuaternionGetMatrix4x4f(helpMatrix, helpQuaternion); + + glusMatrix4x4MultiplyVector3f(tp, helpMatrix, helpVector); + tp+=3; + } + } + } + + if(numberVertices<=0xffff) + CreateTorusIndices(gc.CreateIBO16(numberIndices),tci->numberSlices,tci->numberStacks); + else + CreateTorusIndices(gc.CreateIBO32(numberIndices),tci->numberSlices,tci->numberStacks); + + return gc.Finish(); + } + + namespace + { + template + void CreateCylinderIndices(T *tp,const uint numberSlices) + { + uint i; + + T centerIndex = 0; + T indexCounter = 1; + + for (i = 0; i < numberSlices; i++) + { + *tp = centerIndex; ++tp; + *tp = indexCounter + 1; ++tp; + *tp = indexCounter; ++tp; + + indexCounter++; + } + indexCounter++; + + // Top + centerIndex = indexCounter; + indexCounter++; + + for (i = 0; i < numberSlices; i++) + { + *tp = centerIndex; ++tp; + *tp = indexCounter; ++tp; + *tp = indexCounter + 1; ++tp; + + indexCounter++; + } + indexCounter++; + + // Sides + for (i = 0; i < numberSlices; i++) + { + *tp = indexCounter; ++tp; + *tp = indexCounter + 2; ++tp; + *tp = indexCounter + 1; ++tp; + + *tp = indexCounter + 2; ++tp; + *tp = indexCounter + 3; ++tp; + *tp = indexCounter + 1; ++tp; + + indexCounter += 2; + } + } + }//namespace + + vulkan::Renderable *CreateRenderableCylinder(SceneDB *db,vulkan::Material *mtl,CylinderCreateInfo *cci) + { + uint numberIndices = cci->numberSlices * 3 * 2 + cci->numberSlices * 6; + + if(numberIndices<=0) + return(nullptr); + + GeometryCreater3D gc(db,mtl); + + uint numberVertices = (cci->numberSlices + 2) * 2 + (cci->numberSlices + 1) * 2; + + if(!gc.Init(numberVertices)) + return(nullptr); + + float angleStep = (2.0f * HGL_PI) / ((float) cci->numberSlices); + + if (cci->numberSlices < 3 || numberVertices > GLUS_MAX_VERTICES || numberIndices > GLUS_MAX_INDICES) + return nullptr; + + float *vp=gc.GetVertexPointer(); + float *np=gc.GetNormalPointer(); + float *tp=gc.GetTangentPointer(); + float *tc=gc.GetTexCoordPointer(); + + *vp = 0.0f; ++vp; + *vp = 0.0f; ++vp; + *vp = -cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f; ++np; + *np = 0.0f; ++np; + *np = -1.0f; ++np; + } + + if(tp) + { + *tp = 0.0f; ++tp; + *tp = 1.0f; ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 0.0f; ++tc; + *tc = 0.0f; ++tc; + } + + for(uint i = 0; i < cci->numberSlices + 1; i++) + { + float currentAngle = angleStep * (float)i; + + *vp = cosf(currentAngle) * cci->radius;++vp; + *vp = -sinf(currentAngle) * cci->radius;++vp; + *vp = -cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f; ++np; + *np = 0.0f; ++np; + *np = -1.0f; ++np; + } + + if(tp) + { + *tp = sinf(currentAngle); ++tp; + *tp = cosf(currentAngle); ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 0.0f; ++tc; + *tc = 0.0f; ++tc; + } + } + + *vp = 0.0f; ++vp; + *vp = 0.0f; ++vp; + *vp = cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f; ++np; + *np = 0.0f; ++np; + *np = 1.0f; ++np; + } + + if(tp) + { + *tp = 0.0f; ++tp; + *tp = -1.0f; ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 1.0f; ++tc; + *tc = 1.0f; ++tc; + } + + for(uint i = 0; i < cci->numberSlices + 1; i++) + { + float currentAngle = angleStep * (float)i; + + *vp = cosf(currentAngle) * cci->radius;++vp; + *vp = -sinf(currentAngle) * cci->radius;++vp; + *vp = cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f; ++np; + *np = 0.0f; ++np; + *np = 1.0f; ++np; + } + + if(tp) + { + *tp = -sinf(currentAngle); ++tp; + *tp = -cosf(currentAngle); ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 1.0f; ++tc; + *tc = 1.0f; ++tc; + } + } + + for(uint i = 0; i < cci->numberSlices + 1; i++) + { + float currentAngle = angleStep * (float)i; + + float sign = -1.0f; + + for (uint j = 0; j < 2; j++) + { + *vp = cosf(currentAngle) * cci->radius; ++vp; + *vp = -sinf(currentAngle) * cci->radius; ++vp; + *vp = cci->halfExtend * sign; ++vp; + + if(np) + { + *np = cosf(currentAngle); ++np; + *np = -sinf(currentAngle); ++np; + *np = 0.0f; ++np; + } + + if(tp) + { + *tp = -sinf(currentAngle); ++tp; + *tp = -cosf(currentAngle); ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = (float)i / (float)cci->numberSlices; ++tc; + *tc = (sign + 1.0f) / 2.0f; ++tc; + } + + sign = 1.0f; + } + } + + if(numberVertices<=0xffff) + CreateCylinderIndices(gc.CreateIBO16(numberIndices),cci->numberSlices); + else + CreateCylinderIndices(gc.CreateIBO32(numberIndices),cci->numberSlices); + + return gc.Finish(); + } + + namespace + { + template + void CreateConeIndices(T *tp,const uint numberSlices,const uint numberStacks) + { + // Bottom + uint centerIndex = 0; + uint indexCounter = 1; + uint i,j; + + for (i = 0; i < numberSlices; i++) + { + *tp = centerIndex; ++tp; + *tp = indexCounter + 1; ++tp; + *tp = indexCounter; ++tp; + + indexCounter++; + } + indexCounter++; + + // Sides + for (j = 0; j < numberStacks; j++) + { + for (i = 0; i < numberSlices; i++) + { + *tp = indexCounter; ++tp; + *tp = indexCounter + 1; ++tp; + *tp = indexCounter + numberSlices + 1; ++tp; + + *tp = indexCounter + 1; ++tp; + *tp = indexCounter + numberSlices + 2; ++tp; + *tp = indexCounter + numberSlices + 1; ++tp; + + indexCounter++; + } + indexCounter++; + } + } + }//namespace + + vulkan::Renderable *CreateRenderableCone(SceneDB *db,vulkan::Material *mtl,ConeCreateInfo *cci) + { + GeometryCreater3D gc(db,mtl); + + uint i, j; + + uint numberVertices = (cci->numberSlices + 2) + (cci->numberSlices + 1) * (cci->numberStacks + 1); + + if(!gc.Init(numberVertices)) + return(nullptr); + + uint numberIndices = cci->numberSlices * 3 + cci->numberSlices * 6 * cci->numberStacks; + + float angleStep = (2.0f * HGL_PI) / ((float) cci->numberSlices); + + float h = 2.0f * cci->halfExtend; + float r = cci->radius; + float l = sqrtf(h*h + r*r); + + if (cci->numberSlices < 3 || cci->numberStacks < 1 || numberVertices > GLUS_MAX_VERTICES || numberIndices > GLUS_MAX_INDICES) + return nullptr; + + float *vp=gc.GetVertexPointer(); + float *np=gc.GetNormalPointer(); + float *tp=gc.GetTangentPointer(); + float *tc=gc.GetTexCoordPointer(); + + *vp = 0.0f; ++vp; + *vp = 0.0f; ++vp; + *vp = -cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f;++np; + *np = 0.0f;++np; + *np = -1.0f;++np; + } + + if(tp) + { + *tp = 0.0f; ++tp; + *tp = 1.0f; ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 0.0f; ++tc; + *tc = 0.0f; ++tc; + } + + for (i = 0; i < cci->numberSlices + 1; i++) + { + float currentAngle = angleStep * (float)i; + + *vp = cosf(currentAngle) * cci->radius;++vp; + *vp = -sinf(currentAngle) * cci->radius;++vp; + *vp = -cci->halfExtend; ++vp; + + if(np) + { + *np = 0.0f;++np; + *np = 0.0f;++np; + *np = -1.0f;++np; + } + + if(tp) + { + *tp = sinf(currentAngle); ++tp; + *tp = cosf(currentAngle); ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = 0.0f; ++tc; + *tc = 0.0f; ++tc; + } + } + + for (j = 0; j < cci->numberStacks + 1; j++) + { + float level = (float)j / (float)cci->numberStacks; + + for (i = 0; i < cci->numberSlices + 1; i++) + { + float currentAngle = angleStep * (float)i; + + *vp = cosf(currentAngle) * cci->radius * (1.0f - level); ++vp; + *vp = -sinf(currentAngle) * cci->radius * (1.0f - level); ++vp; + *vp = -cci->halfExtend + 2.0f * cci->halfExtend * level; ++vp; + + if(np) + { + *np = h / l * cosf(currentAngle); ++np; + *np = h / l * -sinf(currentAngle); ++np; + *np = r / l; ++np; + } + + if(tp) + { + *tp = -sinf(currentAngle); ++tp; + *tp = -cosf(currentAngle); ++tp; + *tp = 0.0f; ++tp; + } + + if(tc) + { + *tc = (float)i / (float)cci->numberSlices; ++tc; + *tc = level; ++tc; + } + } + } + + if(numberVertices<=0xffff) + CreateConeIndices(gc.CreateIBO16(numberIndices),cci->numberSlices,cci->numberStacks); + else + CreateConeIndices(gc.CreateIBO32(numberIndices),cci->numberSlices,cci->numberStacks); + + return gc.Finish(); + } }//namespace graph }//namespace hgl \ No newline at end of file