From ed076ad9cac293b0acbee864c831e6bf4bd415eb Mon Sep 17 00:00:00 2001 From: hyzboy Date: Tue, 21 May 2019 21:28:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=B7=BB=E5=8A=A0SceneGraph?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + inc/hgl/graph/AABox.h | 53 +++++++++++ inc/hgl/graph/Axis.h | 23 ----- inc/hgl/graph/Camera.h | 71 +++++++++++++++ inc/hgl/graph/Light.h | 1 + inc/hgl/graph/SceneNode.h | 104 ++++++++++++++++++++++ inc/hgl/graph/SceneOrient.h | 44 ++++++++++ inc/hgl/math/Matrix.h | 2 +- src/CMakeLists.txt | 3 +- src/RenderDevice/Vulkan/CMakeLists.txt | 10 +-- src/SceneGraph/AABox.cpp | 54 ++++++++++++ src/SceneGraph/CMakeLists.txt | 17 ++++ src/SceneGraph/Camera.cpp | 42 +++++++++ src/SceneGraph/RenderList.cpp | 84 ++++++++++++++++++ src/SceneGraph/SceneNode.cpp | 116 +++++++++++++++++++++++++ src/SceneGraph/SceneOrient.cpp | 43 +++++++++ 16 files changed, 638 insertions(+), 30 deletions(-) create mode 100644 inc/hgl/graph/AABox.h delete mode 100644 inc/hgl/graph/Axis.h create mode 100644 inc/hgl/graph/Camera.h create mode 100644 inc/hgl/graph/SceneNode.h create mode 100644 inc/hgl/graph/SceneOrient.h create mode 100644 src/SceneGraph/AABox.cpp create mode 100644 src/SceneGraph/CMakeLists.txt create mode 100644 src/SceneGraph/Camera.cpp create mode 100644 src/SceneGraph/RenderList.cpp create mode 100644 src/SceneGraph/SceneNode.cpp create mode 100644 src/SceneGraph/SceneOrient.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 034eb82e..364c263c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ add_subdirectory(src) SET(ULRE ULRE.Base # ULRE.Util ULRE.RenderDevice.Vulkan + ULRE.SceneGraph ULRE.Platform MathGeoLib spirv-cross-core diff --git a/inc/hgl/graph/AABox.h b/inc/hgl/graph/AABox.h new file mode 100644 index 00000000..7f8e492a --- /dev/null +++ b/inc/hgl/graph/AABox.h @@ -0,0 +1,53 @@ +#ifndef HGL_GRAPH_AABOX_INCLUDE +#define HGL_GRAPH_AABOX_INCLUDE + +#include +namespace hgl +{ + namespace graph + { + /** + * AABox + */ + struct AABox + { + Vector3f corner; + Vector3f center; + Vector3f length; + Vector3f corner_max; + + public: + + AABox(); + + void SetCornerLength(const Vector3f &c,float x,float y,float z) ///<按顶角和长度设置盒子范围 + { + corner=c; + length=Vector3f(x,y,z); + corner_max=Vector3f(c[0]+x,c[1]+y,c[2]+z); + center=(corner+corner_max)/2.0f; + } + + void SetCornerLength(const Vector3f &c,const Vector3f &l) ///<按顶角和长度设置盒子范围 + { + SetCornerLength(c,l[0],l[1],l[2]); + } + + void SetMinMax(const Vector3f &min_v,const Vector3f &max_v) ///<按最小最大值设置盒子范围 + { + corner=min_v; + corner_max=max_v; + length=max_v-min_v; + center=(min_v+max_v)/2.0f; + } + + Vector3f GetVertexP(const Vector3f &)const; + Vector3f GetVertexN(const Vector3f &)const; + + public: + + void operator += (const AABox &); ///<融合另一个AABox + };//struct AABox + }//namespace graph +}//namespace hgl +#endif//HGL_GRAPH_AABOX_INCLUDE diff --git a/inc/hgl/graph/Axis.h b/inc/hgl/graph/Axis.h deleted file mode 100644 index fadaaede..00000000 --- a/inc/hgl/graph/Axis.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef HGL_GRAPH_AXIS_INCLUDE -#define HGL_GRAPH_AXIS_INCLUDE -namespace hgl -{ - namespace graph - { - /** - * 轴枚举 - */ - enum Axis - { - HGL_AXIS_NONE=0, - - HGL_AXIS_X, - HGL_AXIS_Y, - HGL_AXIS_Z, - - HGL_AXIS_END - - };//enum Axis - }//namespace graph -}//namespace hgl -#endif//HGL_GRAPH_AXIS_INCLUDE diff --git a/inc/hgl/graph/Camera.h b/inc/hgl/graph/Camera.h new file mode 100644 index 00000000..ef1aa138 --- /dev/null +++ b/inc/hgl/graph/Camera.h @@ -0,0 +1,71 @@ +#ifndef HGL_GRAPH_CAMERA_INCLUDE +#define HGL_GRAPH_CAMERA_INCLUDE + +#include +namespace hgl +{ + namespace graph + { + /** + * 摄像机数据结构 + */ + struct Camera + { + float width; ///<视图宽 + float height; ///<视图高 + + float fov; ///<水平FOV + float znear,zfar; /// +#include namespace hgl { namespace graph diff --git a/inc/hgl/graph/SceneNode.h b/inc/hgl/graph/SceneNode.h new file mode 100644 index 00000000..e8325627 --- /dev/null +++ b/inc/hgl/graph/SceneNode.h @@ -0,0 +1,104 @@ +#ifndef HGL_GRAPH_SCENE_NODE_INCLUDE +#define HGL_GRAPH_SCENE_NODE_INCLUDE + +#include +#include +namespace hgl +{ + namespace graph + { + class SceneNode; + struct Camera; + class Frustum; + class Renderable; + + typedef List RenderList; ///<渲染列表类型重定义 + + typedef float (*RenderListCompFunc)(Camera *,SceneNode *,SceneNode *); ///<渲染列表排序比较函数 + + float CameraLengthComp(Camera *,SceneNode *,SceneNode *); ///<摄像机距离比较函数 + + typedef bool (*FilterSceneNodeFunc)(const SceneNode *,void *); ///<场景节点过滤函数重定义 + + bool FrustumClipFilter(const SceneNode *,void *); ///<平截头截减过滤函数 + + /** + * 场景节点数据类
+ * 从场景坐标变换(SceneOrient)类继承 + */ + class SceneNode:public SceneOrient ///场景节点类 + { + protected: + + AABB BoundingBox; ///<绑定盒 +// AABB LocalBoundingBox; ///<本地坐标绑定盒 +// AABB WorldBoundingBox; ///<世界坐标绑定盒 + + Vector3f Center; ///<中心点 + Vector3f LocalCenter; ///<本地坐标中心点 + Vector3f WorldCenter; ///<世界坐标中心点 + + public: + + List SubData; ///<可渲染数据 + ObjectList SubNode; ///<子节点 + + public: + + SceneNode()=default; + virtual ~SceneNode() + { + ClearSubNode(); + ClearRenderable(); + } + + void Add(Renderable *r){if(r)SubData.Add(r);} ///<增加一个可渲染数据 + void ClearRenderable(){SubData.Clear();} ///<清除可渲染数据 + + void AddSubNode(SceneNode *n){if(n)SubNode.Add(n);} ///<增加一个子节点 + SceneNode * CreateSubNode() ///<创建一个子节点 + { + SceneNode *sn=new SceneNode(); + SubNode.Add(sn); + return sn; + } + + SceneNode * AddSubNode(Renderable *r,const Matrix4f &m) + { + if(!r)return(nullptr); + + SceneNode *sn=CreateSubNode(); + sn->Add(r); + sn->SetLocalMatrix(m); + return sn; + } + + void ClearSubNode(){SubNode.Clear();} ///<清除子节点 + + public: //坐标相关方法 + + virtual void SetBoundingBox (const AABB &bb){BoundingBox=bb;} ///<设置绑定盒 + + virtual void RefreshMatrix (const Matrix4f *mat=nullptr); ///<刷新世界变换矩阵 + virtual void RefreshBoundingBox (); ///<刷新绑定盒 + + virtual const AABB & GetBoundingBox ()const{return BoundingBox;} ///<取得绑定盒 +// virtual const AABB & GetLocalBoundingBox ()const{return LocalBoundingBox;} ///<取得本地坐标绑定盒 +// virtual const AABB & GetWorldBoundingBox ()const{return WorldBoundingBox;} ///<取得世界坐标绑定盒 + + virtual const Vector3f & GetCenter ()const{return Center;} ///<取得中心点 + virtual const Vector3f & GetLocalCenter ()const{return LocalCenter;} ///<取得本地坐标中心点 + virtual const Vector3f & GetWorldCenter ()const{return WorldCenter;} ///<取得世界坐标中心点 + + public: //渲染列表相关方法 + + virtual bool ExpendToList(RenderList *,FilterSceneNodeFunc func=nullptr,void *func_data=nullptr)const; ///<展开到渲染列表 + bool ExpendToList(RenderList *rl,Frustum *f)const ///<展开到渲染列表(使用平截头裁剪) + {return ExpendToList(rl,FrustumClipFilter,f);} + + bool ExpendToList(RenderList *,const Matrix4f &,const Matrix4f &,RenderListCompFunc=nullptr)const; ///<展开到渲染列表(使用平截头裁剪并排序) + bool ExpendToList(RenderList *,Camera *,RenderListCompFunc=nullptr)const; ///<展开到渲染列表(使用摄像机平截头裁剪并排序) + };//class SceneNode + }//namespace graph +}//namespace hgl +#endif//HGL_GRAPH_SCENE_NODE_INCLUDE diff --git a/inc/hgl/graph/SceneOrient.h b/inc/hgl/graph/SceneOrient.h new file mode 100644 index 00000000..1056f256 --- /dev/null +++ b/inc/hgl/graph/SceneOrient.h @@ -0,0 +1,44 @@ +#ifndef HGL_GRAPH_SCENE_ORIENT_INCLUDE +#define HGL_GRAPH_SCENE_ORIENT_INCLUDE + +//#include +#include +//#include +namespace hgl +{ + namespace graph + { + /** + * 方向定位数据基类 + */ + class SceneOrient ///场景定位类 + { + protected: + + //ObjectList TransformList; + + Matrix4f LocalMatrix; ///<当前矩阵 + Matrix4f LocalToWorldMatrix; ///<当前到世界矩阵 + + Matrix4f InverseLocalMatrix; ///<反向当前矩阵 + Matrix4f InverseLocalToWorldMatrix; ///<反向当前到世界矩阵 + + public: + + SceneOrient(); + virtual ~SceneOrient()=default; + + Matrix4f & SetLocalMatrix (const Matrix4f &); ///<设定当前节点矩阵 + Matrix4f & SetLocalToWorldMatrix (const Matrix4f &); ///<设定当前节点到世界矩阵 + + const Matrix4f & GetLocalMatrix ()const {return LocalMatrix;} + const Matrix4f & GetLocalToWorldMatrix ()const {return LocalToWorldMatrix;} + + const Matrix4f & GetInverseLocalMatrix ()const {return InverseLocalMatrix;} + const Matrix4f & GetInverseLocalToWorldMatrix()const {return InverseLocalToWorldMatrix;} + + void RefreshLocalToWorldMatrix (const Matrix4f *); ///<刷新到世界空间矩阵 + };//class SceneOrient + }//namespace graph +}//namespace hgl +#endif//HGL_GRAPH_SCENE_ORIENT_INCLUDE diff --git a/inc/hgl/math/Matrix.h b/inc/hgl/math/Matrix.h index 47708f0d..31d7545b 100644 --- a/inc/hgl/math/Matrix.h +++ b/inc/hgl/math/Matrix.h @@ -2,7 +2,7 @@ #define HGL_ALGORITHM_MATH_VECTOR_MATRIX_INCLUDE #include - +#include //注:GLM/CML(OpenGLMode)是列矩阵,计算坐标matrix*pos // 而MGL是行矩阵,需要反过来pos*matrix diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0dd78eb0..862f9e1f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ -add_subdirectory(Base) +add_subdirectory(Base) #add_subdirectory(Util) add_subdirectory(RenderDevice) +add_subdirectory(SceneGraph) add_subdirectory(Platform) diff --git a/src/RenderDevice/Vulkan/CMakeLists.txt b/src/RenderDevice/Vulkan/CMakeLists.txt index 8befc53f..5ef3d7a3 100644 --- a/src/RenderDevice/Vulkan/CMakeLists.txt +++ b/src/RenderDevice/Vulkan/CMakeLists.txt @@ -22,8 +22,8 @@ ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKShaderModuleManage.h ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKSurfaceExtensionName.h ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKVertexAttributeBinding.h - ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKTexture.h - ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKSampler.h) + ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKTexture.h + ${ROOT_INCLUDE_PATH}/hgl/graph/vulkan/VKSampler.h) SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKInstance.cpp @@ -34,7 +34,7 @@ SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKDeviceCreater.cpp VKDevice.cpp VKDeviceBuffer.cpp - VKDeviceTexture.cpp + VKDeviceTexture.cpp VKBuffer.cpp VKDescriptorSets.cpp VKDescriptorSetLayoutCreater.cpp @@ -50,8 +50,8 @@ SET(RENDER_DEVICE_VULKAN_SOURCE VKFormat.cpp VKFence.cpp VKMaterial.cpp VKRenderable.cpp - VKTexture.cpp - VKSampler.cpp) + VKTexture.cpp + VKSampler.cpp) SET(RENDER_DEVICE_VULKAN_POD_SOURCE pod/VKPipelineCreateInfo.POD.cpp) diff --git a/src/SceneGraph/AABox.cpp b/src/SceneGraph/AABox.cpp new file mode 100644 index 00000000..d9310b71 --- /dev/null +++ b/src/SceneGraph/AABox.cpp @@ -0,0 +1,54 @@ +#include +namespace hgl +{ + namespace graph + { + AABox::AABox(void) + { + corner[0] = 0; + corner[1] = 0; + corner[2] = 0; + + length[0] = 1.0f; + length[1] = 1.0f; + length[2] = 1.0f; + } + + Vector3f AABox::GetVertexP(const Vector3f &normal) const + { + Vector3f res = corner; + + if (normal[0] > 0)res[0] += length[0]; + if (normal[1] > 0)res[1] += length[1]; + if (normal[2] > 0)res[2] += length[2]; + + return(res); + } + + Vector3f AABox::GetVertexN(const Vector3f &normal) const + { + Vector3f res = corner; + + if (normal[0] < 0)res[0] += length[0]; + if (normal[1] < 0)res[1] += length[1]; + if (normal[2] < 0)res[2] += length[2]; + + return(res); + } + + void AABox::operator+=(const AABox &box) + { + corner[0]=hgl_min(corner[0],box.corner[0]); + corner[1]=hgl_min(corner[1],box.corner[1]); + corner[2]=hgl_min(corner[2],box.corner[2]); + + corner_max[0]=hgl_max(corner_max[0],box.corner_max[0]); + corner_max[1]=hgl_max(corner_max[1],box.corner_max[1]); + corner_max[2]=hgl_max(corner_max[2],box.corner_max[2]); + + length=corner_max-corner; + + center=(corner+corner_max)/2.0f; + } + }//namespace graph +}//namespace hgl diff --git a/src/SceneGraph/CMakeLists.txt b/src/SceneGraph/CMakeLists.txt new file mode 100644 index 00000000..af9efa61 --- /dev/null +++ b/src/SceneGraph/CMakeLists.txt @@ -0,0 +1,17 @@ +SET(SCENE_GRAPH_HEADER ${ROOT_INCLUDE_PATH}/hgl/graph/AABox.h + ${ROOT_INCLUDE_PATH}/hgl/graph/Camera.h + ${ROOT_INCLUDE_PATH}/hgl/graph/Light.h + ${ROOT_INCLUDE_PATH}/hgl/graph/SceneNode.h + ${ROOT_INCLUDE_PATH}/hgl/graph/SceneOrient.h) + +SET(SCENE_GRAPH_SOURCE AABox.cpp + Camera.cpp +# RenderList.cpp + SceneNode.cpp + SceneOrient.cpp) + +SOURCE_GROUP("Header Files" FILES ${SCENE_GRAPH_HEADER}) +SOURCE_GROUP("Source Files" FILES ${SCENE_GRAPH_SOURCE}) + +add_library(ULRE.SceneGraph STATIC ${SCENE_GRAPH_HEADER} + ${SCENE_GRAPH_SOURCE}) diff --git a/src/SceneGraph/Camera.cpp b/src/SceneGraph/Camera.cpp new file mode 100644 index 00000000..14f5dcc8 --- /dev/null +++ b/src/SceneGraph/Camera.cpp @@ -0,0 +1,42 @@ +#include +namespace hgl +{ + namespace graph + { + inline Matrix4f LookAt(const Vector3f &eye,const Vector3f &target,const Vector3f &up) + { + Vector3f forward=target-eye; + + normalize(forward); + + Vector3f side=cross(forward,up); + + normalize(side); + + Vector3f nup=cross(side,forward); + + Matrix4f result(side.x, side.y, side.z, 0.0f, + nup.x, nup.y, nup.z, 0.0f, + -forward.x, -forward.y, -forward.z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + + return result*translate(-eye); + } + + void CameraToFrustum(Frustum *f,const Camera *cam) + { + if(!f||!cam)return; + + f->SetVerticalFovAndAspectRatio(DegToRad(cam->fov),cam->width/cam->height); + f->SetViewPlaneDistances(cam->znear,cam->zfar); + + //Matrix4f projection_matrix=f->ProjectionMatrix(); //可以用Frustum来算projection matrix + } + + void MakeCameraMatrix(Matrix4f *proj,Matrix4f *mv,const Camera *cam) + { + *proj=perspective(cam->width/cam->height,cam->fov,cam->znear,cam->zfar); + *mv=hgl::graph::LookAt(cam->eye,cam->center,cam->up_vector); + } + }//namespace graph +}//namespace hgl diff --git a/src/SceneGraph/RenderList.cpp b/src/SceneGraph/RenderList.cpp new file mode 100644 index 00000000..d0f8dda3 --- /dev/null +++ b/src/SceneGraph/RenderList.cpp @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +//#include + +#include + +namespace hgl +{ + namespace graph + { +/* float CameraLengthComp(Camera *cam,SceneNode *obj_one,SceneNode *obj_two) + { + if(!cam||!obj_one||!obj_two) + return(0); + + return( length_squared(obj_one->GetCenter(),cam->eye)- + length_squared(obj_two->GetCenter(),cam->eye)); + } + + bool FrustumClipFilter(const SceneNode *node,void *fc) + { + if(!node||!fc)return(false); + + return (((Frustum *)fc)->BoxIn(node->GetWorldBoundingBox())!=Frustum::OUTSIDE); + }*/ + + /** + * 使用指定矩阵渲染一个渲染列表 + * @param rl 渲染列表 + * @param proj 透视矩阵 + * @param mv 视图矩阵 + * @return 是否渲染成功 + */ + bool Render(const RenderList *rl,const Matrix4f *proj,const Matrix4f *mv) + { + if(!rl) + return(false); + + int count=rl->GetCount(); + const SceneNode **node=rl->GetData(); + + for(int i=0;iGetLocalToWorldMatrix(); + + int sn=(*node)->SubData.GetCount(); + Renderable **p=(*node)->SubData.GetData(); + + for(int j=0;j +//#include +namespace hgl +{ + namespace graph + { + /** + * 刷新矩阵 + * @param root 根矩阵 + */ + void SceneNode::RefreshMatrix(const Matrix4f *root_matrix) + { + if(root_matrix) + RefreshLocalToWorldMatrix(root_matrix); + else + LocalToWorldMatrix=LocalMatrix; + + const int count=SubNode.GetCount(); + + SceneNode **sub=SubNode.GetData(); + + for(int i=0;iRefreshMatrix(&LocalToWorldMatrix); + + sub++; + } + } + + /** + * 刷新绑定盒 + */ + void SceneNode::RefreshBoundingBox() + { + int count=SubNode.GetCount(); + SceneNode **sub=SubNode.GetData(); + + Vector3f min_v,max_v; + + for(int i=0;iRefreshBoundingBox(); + + if(i==0) + { +// min_v=(*sub)->GetBounding(); + } + + sub++; + } + } + + /** + * 从当前节点展开输出到一个渲染列表 + * @param rl 渲染列表 + * @param func 过滤函数 + * @param func_data 过滤函数用辅助数据 + * @return 成功与否 + */ + bool SceneNode::ExpendToList(RenderList *rl,FilterSceneNodeFunc func,void *func_data)const + { + if(!rl)return(false); + + if(func) + if(!func(this,func_data)) + return(false); + + if(SubData.GetCount()) + rl->Add(this); //增加当前节点 + + int count=SubNode.GetCount(); + SceneNode **sub=SubNode.GetData(); + + for(int i=0;iExpendToList(rl,func,func_data); //展开子节点 + + sub++; + } + + return(true); + } + + bool SceneNode::ExpendToList(RenderList *rl,const Matrix4f &proj,const Matrix4f &mv,RenderListCompFunc comp_func)const + { + if(!rl)return(false); + + + } + + /** + * 从当前节点展开输出到一个渲染列表 + * @param rl 渲染列表 + * @param cam 摄像机 + * @param comp_func 渲染列表远近比较函数 + */ + bool SceneNode::ExpendToList(RenderList *rl,Camera *cam,RenderListCompFunc comp_func)const + { + if(!rl||!cam)return(false); + +// Frustum f; + +// MakeCameraFrustum(&f,cam); + +// if(!ExpendToList(rl,&f)) + if(!ExpendToList(rl)) + return(false); + + if(comp_func) + { + } + + return(true); + } + }//namespace graph +}//namespace hgl diff --git a/src/SceneGraph/SceneOrient.cpp b/src/SceneGraph/SceneOrient.cpp new file mode 100644 index 00000000..7692b3cf --- /dev/null +++ b/src/SceneGraph/SceneOrient.cpp @@ -0,0 +1,43 @@ +#include +namespace hgl +{ + namespace graph + { + Matrix4f Ortho2DMatrix; ///<全局2D视图矩阵 + + SceneOrient::SceneOrient() + { + LocalMatrix= + LocalToWorldMatrix= + InverseLocalMatrix= + InverseLocalToWorldMatrix=identity(); + } + + Matrix4f &SceneOrient::SetLocalMatrix(const Matrix4f &m) + { + LocalMatrix=m; + + InverseLocalMatrix=inverse(LocalMatrix); + + return LocalMatrix; + } + + Matrix4f &SceneOrient::SetLocalToWorldMatrix(const Matrix4f &m) + { + LocalToWorldMatrix=m; + + InverseLocalToWorldMatrix=inverse(LocalToWorldMatrix); + + return LocalToWorldMatrix; + } + + /** + * 刷新世界矩阵 + * @param m 上一级local to world矩阵 + */ + void SceneOrient::RefreshLocalToWorldMatrix(const Matrix4f *m) + { + SetLocalToWorldMatrix((*m)*LocalMatrix); + } + }//namespace graph +}//namespace hgl