From afbed3d407683b34d145aca6d6d93ff29ef991a8 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 28 Dec 2024 23:01:07 -0800 Subject: [PATCH] Geometry Primitives: added sphere --- Common/interface/GeometryPrimitives.h | 28 ++++++- Common/src/GeometryPrimitives.cpp | 79 +++++++++++++++---- .../GraphicsTools/src/GraphicsUtilities.cpp | 3 +- 3 files changed, 90 insertions(+), 20 deletions(-) diff --git a/Common/interface/GeometryPrimitives.h b/Common/interface/GeometryPrimitives.h index 1b28d5a71..9b2d82480 100644 --- a/Common/interface/GeometryPrimitives.h +++ b/Common/interface/GeometryPrimitives.h @@ -72,9 +72,12 @@ DILIGENT_TYPED_ENUM(GEOMETRY_PRIMITIVE_TYPE, Uint32) GEOMETRY_PRIMITIVE_TYPE_UNDEFINED = 0u, /// Cube geometry primitive type. - GEOMETRY_PRIMITIVE_TYPE_CUBE = 1u, + GEOMETRY_PRIMITIVE_TYPE_CUBE, - GEOMETRY_PRIMITIVE_TYPE_LAST = GEOMETRY_PRIMITIVE_TYPE_CUBE + /// Sphere geometry primitive type. + GEOMETRY_PRIMITIVE_TYPE_SPHERE, + + GEOMETRY_PRIMITIVE_TYPE_COUNT }; // clang-format on @@ -130,6 +133,25 @@ struct CubeGeometryPrimitiveAttributes DILIGENT_DERIVE(GeometryPrimitiveAttribut }; // clang-format on + +/// Sphere geometry primitive attributes. +// clang-format off +struct SphereGeometryPrimitiveAttributes DILIGENT_DERIVE(GeometryPrimitiveAttributes) + + /// Sphere radius. + float Radius DEFAULT_INITIALIZER(1.f); + +#if DILIGENT_CPP_INTERFACE + explicit SphereGeometryPrimitiveAttributes(float _Radius = 1, + GEOMETRY_PRIMITIVE_VERTEX_FLAGS _VertexFlags = GEOMETRY_PRIMITIVE_VERTEX_FLAG_ALL, + Uint32 _NumSubdivision = 1) noexcept : + GeometryPrimitiveAttributes{GEOMETRY_PRIMITIVE_TYPE_SPHERE, _VertexFlags, _NumSubdivision}, + Radius{_Radius} + {} +#endif +}; +// clang-format on + /// Geometry primitive info. struct GeometryPrimitiveInfo { @@ -154,7 +176,7 @@ Uint32 GetGeometryPrimitiveVertexSize(GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlag /// The vertex components are stored as interleaved floating-point values. /// For example, if VertexFlags = GEOMETRY_PRIMITIVE_VERTEX_FLAG_POS_NORM, the vertex data will /// be stored as follows: -/// P0, N0, P1, N1, ..., Pn, Nn. +/// P0, N0, P1, N1, ..., Pn, Nn. /// \param [out] ppIndices - Address of the memory location where the pointer to the output index data blob will be stored. /// Index data is stored as 32-bit unsigned integers representing the triangle list. /// \param [out] pInfo - A pointer to the structure that will receive information about the created geometry primitive. diff --git a/Common/src/GeometryPrimitives.cpp b/Common/src/GeometryPrimitives.cpp index 76099b372..96700c3e3 100644 --- a/Common/src/GeometryPrimitives.cpp +++ b/Common/src/GeometryPrimitives.cpp @@ -42,20 +42,14 @@ Uint32 GetGeometryPrimitiveVertexSize(GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlag ((VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD) ? sizeof(float2) : 0)); } -void CreateCubeGeometry(const CubeGeometryPrimitiveAttributes& Attribs, - IDataBlob** ppVertices, - IDataBlob** ppIndices, - GeometryPrimitiveInfo* pInfo) +template +void CreateCubeGeometryInternal(Uint32 NumSubdivisions, + GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags, + IDataBlob** ppVertices, + IDataBlob** ppIndices, + GeometryPrimitiveInfo* pInfo, + VertexHandlerType&& HandleVertex) { - const float Size = Attribs.Size; - const Uint32 NumSubdivisions = Attribs.NumSubdivisions; - const GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags = Attribs.VertexFlags; - - if (Size <= 0) - { - UNEXPECTED("Size must be positive"); - return; - } if (NumSubdivisions == 0) { UNEXPECTED("NumSubdivisions must be positive"); @@ -123,7 +117,6 @@ void CreateCubeGeometry(const CubeGeometryPrimitiveAttributes& Attribs, { if (pVert != nullptr) { - const float3& Normal = FaceNormals[FaceIndex]; // 6 ______7______ 8 // | .'| .'| // | .' | .' | @@ -158,9 +151,11 @@ void CreateCubeGeometry(const CubeGeometryPrimitiveAttributes& Attribs, case 5: Pos = float3{+XY.x, XY.y, -0.5f}; break; } + float3 Normal = FaceNormals[FaceIndex]; + HandleVertex(Pos, Normal, UV); + if (VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION) { - Pos *= Size; memcpy(pVert, &Pos, sizeof(Pos)); pVert += sizeof(Pos); } @@ -214,6 +209,54 @@ void CreateCubeGeometry(const CubeGeometryPrimitiveAttributes& Attribs, VERIFY_EXPR(pIdx == nullptr || pIdx == pIndexData->GetConstDataPtr() + IndexDataSize / sizeof(Uint32)); } +void CreateCubeGeometry(const CubeGeometryPrimitiveAttributes& Attribs, + IDataBlob** ppVertices, + IDataBlob** ppIndices, + GeometryPrimitiveInfo* pInfo) +{ + const float Size = Attribs.Size; + if (Size <= 0) + { + UNEXPECTED("Size must be positive"); + return; + } + + CreateCubeGeometryInternal(Attribs.NumSubdivisions, + Attribs.VertexFlags, + ppVertices, + ppIndices, + pInfo, + [&](float3& Pos, float3& Normal, float2& UV) { + Pos *= Size; + }); +} + +void CreateSphereGeometry(const SphereGeometryPrimitiveAttributes& Attribs, + IDataBlob** ppVertices, + IDataBlob** ppIndices, + GeometryPrimitiveInfo* pInfo) +{ + const float Radius = Attribs.Radius; + if (Radius <= 0) + { + UNEXPECTED("Radius must be positive"); + return; + } + + CreateCubeGeometryInternal(Attribs.NumSubdivisions, + Attribs.VertexFlags, + ppVertices, + ppIndices, + pInfo, + [&](float3& Pos, float3& Normal, float2& UV) { + Normal = normalize(Pos); + Pos = Normal * Radius; + + UV.x = 0.5f + atan2(Normal.z, Normal.x) / (2 * PI_F); + UV.y = 0.5f - asin(Normal.y) / PI_F; + }); +} + void CreateGeometryPrimitive(const GeometryPrimitiveAttributes& Attribs, IDataBlob** ppVertices, IDataBlob** ppIndices, @@ -222,7 +265,7 @@ void CreateGeometryPrimitive(const GeometryPrimitiveAttributes& Attribs, DEV_CHECK_ERR(ppVertices == nullptr || *ppVertices == nullptr, "*ppVertices is not null which may cause memory leaks"); DEV_CHECK_ERR(ppIndices == nullptr || *ppIndices == nullptr, "*ppIndices is not null which may cause memory leaks"); - static_assert(GEOMETRY_PRIMITIVE_TYPE_LAST == 1, "Please update the switch below to handle the new geometry primitive type"); + static_assert(GEOMETRY_PRIMITIVE_TYPE_COUNT == 3, "Please update the switch below to handle the new geometry primitive type"); switch (Attribs.Type) { case GEOMETRY_PRIMITIVE_TYPE_UNDEFINED: @@ -233,6 +276,10 @@ void CreateGeometryPrimitive(const GeometryPrimitiveAttributes& Attribs, CreateCubeGeometry(static_cast(Attribs), ppVertices, ppIndices, pInfo); break; + case GEOMETRY_PRIMITIVE_TYPE_SPHERE: + CreateSphereGeometry(static_cast(Attribs), ppVertices, ppIndices, pInfo); + break; + default: UNEXPECTED("Unknown geometry primitive type"); } diff --git a/Graphics/GraphicsTools/src/GraphicsUtilities.cpp b/Graphics/GraphicsTools/src/GraphicsUtilities.cpp index 5ccdde531..f55443f1e 100644 --- a/Graphics/GraphicsTools/src/GraphicsUtilities.cpp +++ b/Graphics/GraphicsTools/src/GraphicsUtilities.cpp @@ -667,7 +667,7 @@ void CreateGeometryPrimitiveBuffers(IRenderDevice* pD IBuffer** ppIndices, GeometryPrimitiveInfo* pInfo) { - static_assert(GEOMETRY_PRIMITIVE_TYPE_LAST == 1, "Please handle the new primitive type"); + static_assert(GEOMETRY_PRIMITIVE_TYPE_COUNT == 3, "Please handle the new primitive type"); RefCntAutoPtr pVertexData; RefCntAutoPtr pIndexData; @@ -684,6 +684,7 @@ void CreateGeometryPrimitiveBuffers(IRenderDevice* pD switch (Attribs.Type) { case GEOMETRY_PRIMITIVE_TYPE_CUBE: PrimTypeStr = "Cube"; break; + case GEOMETRY_PRIMITIVE_TYPE_SPHERE: PrimTypeStr = "Sphere"; break; default: UNEXPECTED("Unexpected primitive type"); }