Skip to content

Commit 8320517

Browse files
Common: added geometry primitives
1 parent 0004b56 commit 8320517

File tree

3 files changed

+331
-0
lines changed

3 files changed

+331
-0
lines changed

Common/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ set(INTERFACE
2020
interface/FileWrapper.hpp
2121
interface/FilteringTools.hpp
2222
interface/FixedBlockMemoryAllocator.hpp
23+
interface/GeometryPrimitives.h
2324
interface/HashUtils.hpp
2425
interface/LRUCache.hpp
2526
interface/FixedLinearAllocator.hpp
@@ -56,6 +57,7 @@ set(SOURCE
5657
src/DefaultRawMemoryAllocator.cpp
5758
src/FileWrapper.cpp
5859
src/FixedBlockMemoryAllocator.cpp
60+
src/GeometryPrimitives.cpp
5961
src/MemoryFileStream.cpp
6062
src/Serializer.cpp
6163
src/SpinLock.cpp
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright 2024 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#pragma once
28+
29+
#include "../../Primitives/interface/DataBlob.h"
30+
#include "../../Primitives/interface/FlagEnum.h"
31+
32+
DILIGENT_BEGIN_NAMESPACE(Diligent)
33+
34+
/// Geometry primitive vertex flags.
35+
// clang-format off
36+
DILIGENT_TYPED_ENUM(GEOMETRY_PRIMITIVE_VERTEX_FLAGS, Uint32)
37+
{
38+
/// No flags.
39+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_NONE = 0u,
40+
41+
/// The geometry primitive vertex contains position.
42+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION = 1u << 0u,
43+
44+
/// The geometry primitive vertex contains normal.
45+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_NORMAL = 1u << 1u,
46+
47+
/// The geometry primitive vertex contains texture coordinates.
48+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD = 1u << 2u,
49+
50+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_LAST = GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD,
51+
52+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_ALL = GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION |
53+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_NORMAL |
54+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD,
55+
56+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_POS_NORM = GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION |
57+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_NORMAL,
58+
59+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_POS_TEX = GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION |
60+
GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD,
61+
};
62+
// clang-format on
63+
64+
DEFINE_FLAG_ENUM_OPERATORS(GEOMETRY_PRIMITIVE_VERTEX_FLAGS)
65+
66+
/// Returns the size of the geometry primitive vertex in bytes.
67+
Uint32 GetGeometryPrimitiveVertexSize(GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags);
68+
69+
/// Creates a cube geometry.
70+
///
71+
/// \param [in] Size The size of the cube.
72+
/// The cube is centered at (0, 0, 0) and has the size of Size x Size x Size.
73+
/// If the cube size is 1, the coordinates of the cube vertices are in the range [-0.5, 0.5].
74+
/// \param [in] NumSubdivisions The number of subdivisions.
75+
/// The cube faces are subdivided into Subdivision x Subdivision quads.
76+
/// \param [in] VertexFlags Flags that specify which vertex components to include in the output vertices.
77+
/// \param [out] ppVertices Address of the memory location where the pointer to the output vertex data blob will be stored.
78+
/// The vertex components are stored as interleaved floating-point values.
79+
/// For example, if VertexFlags = GEOMETRY_PRIMITIVE_VERTEX_FLAG_POS_NORM, the vertex data will
80+
/// be stored as follows:
81+
/// P0, N0, P1, N1, ..., Pn, Nn.
82+
/// \param [out] ppIndices Address of the memory location where the pointer to the output index data blob will be stored.
83+
/// Index data is stored as 32-bit unsigned integers representing the triangle list.
84+
/// \param [out] pNumVertices Address of the memory location where the number of vertices will be stored.
85+
/// This parameter can be null.
86+
/// \param [out] pNumIndices Address of the memory location where the number of indices will be stored.
87+
/// This parameter can be null.
88+
void DILIGENT_GLOBAL_FUNCTION(CreateCubeGeometry)(float Size,
89+
Uint32 NumSubdivisions,
90+
GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags,
91+
IDataBlob** ppVertices,
92+
IDataBlob** ppIndices,
93+
Uint32* pNumVertices DEFAULT_VALUE(nullptr),
94+
Uint32* pNumIndices DEFAULT_VALUE(nullptr));
95+
96+
DILIGENT_END_NAMESPACE // namespace Diligent

Common/src/GeometryPrimitives.cpp

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Copyright 2024 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#include "GeometryPrimitives.h"
28+
29+
#include <array>
30+
31+
#include "DebugUtilities.hpp"
32+
#include "BasicMath.hpp"
33+
#include "DataBlobImpl.hpp"
34+
35+
namespace Diligent
36+
{
37+
38+
Uint32 GetGeometryPrimitiveVertexSize(GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags)
39+
{
40+
return (((VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION) ? sizeof(float3) : 0) +
41+
((VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_NORMAL) ? sizeof(float3) : 0) +
42+
((VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD) ? sizeof(float2) : 0));
43+
}
44+
45+
void CreateCubeGeometry(float Size,
46+
Uint32 NumSubdivisions,
47+
GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags,
48+
IDataBlob** ppVertices,
49+
IDataBlob** ppIndices,
50+
Uint32* pNumVertices,
51+
Uint32* pNumIndices)
52+
{
53+
if (Size <= 0)
54+
{
55+
UNEXPECTED("Size must be positive");
56+
return;
57+
}
58+
if (NumSubdivisions == 0)
59+
{
60+
UNEXPECTED("NumSubdivisions must be positive");
61+
return;
62+
}
63+
if (NumSubdivisions > 2048)
64+
{
65+
UNEXPECTED("NumSubdivisions is too large");
66+
return;
67+
}
68+
69+
// ______ ______
70+
// | .'| .'|
71+
// | .' | .' |
72+
// |.'____|.'____| NumSubdivisions = 2
73+
// | .'| .'|
74+
// | .' | .' |
75+
// |.'____|.'____|
76+
//
77+
const Uint32 NumFaceVertices = (NumSubdivisions + 1) * (NumSubdivisions + 1);
78+
const Uint32 NumFaceTriangles = NumSubdivisions * NumSubdivisions * 2;
79+
const Uint32 NumFaceIndices = NumFaceTriangles * 3;
80+
const Uint32 VertexSize = GetGeometryPrimitiveVertexSize(VertexFlags);
81+
const Uint32 NumFaces = 6;
82+
const Uint32 VertexDataSize = NumFaceVertices * NumFaces * VertexSize;
83+
const Uint32 IndexDataSize = NumFaceIndices * NumFaces * sizeof(Uint32);
84+
85+
if (pNumVertices != nullptr)
86+
*pNumVertices = NumFaceVertices * NumFaces;
87+
if (pNumIndices != nullptr)
88+
*pNumIndices = NumFaceIndices * NumFaces;
89+
90+
RefCntAutoPtr<DataBlobImpl> pVertexData;
91+
Uint8* pVert = nullptr;
92+
if (ppVertices != nullptr && VertexFlags != GEOMETRY_PRIMITIVE_VERTEX_FLAG_NONE)
93+
{
94+
pVertexData = DataBlobImpl::Create(VertexDataSize);
95+
DEV_CHECK_ERR(*ppVertices == nullptr, "*ppVertices is not null, which may cause memory leak");
96+
pVertexData->QueryInterface(IID_DataBlob, reinterpret_cast<IObject**>(ppVertices));
97+
pVert = pVertexData->GetDataPtr<Uint8>();
98+
}
99+
100+
RefCntAutoPtr<DataBlobImpl> pIndexData;
101+
Uint32* pIdx = nullptr;
102+
if (ppIndices != nullptr)
103+
{
104+
pIndexData = DataBlobImpl::Create(IndexDataSize);
105+
DEV_CHECK_ERR(*ppIndices == nullptr, "*ppIndices is not null, which may cause memory leak");
106+
pIndexData->QueryInterface(IID_DataBlob, reinterpret_cast<IObject**>(ppIndices));
107+
pIdx = pIndexData->GetDataPtr<Uint32>();
108+
}
109+
110+
static constexpr std::array<float3, NumFaces> FaceNormals{
111+
float3{+1, 0, 0},
112+
float3{-1, 0, 0},
113+
float3{0, +1, 0},
114+
float3{0, -1, 0},
115+
float3{0, 0, +1},
116+
float3{0, 0, -1},
117+
};
118+
119+
for (Uint32 FaceIndex = 0; FaceIndex < NumFaces; ++FaceIndex)
120+
{
121+
if (pVert != nullptr)
122+
{
123+
const float3& Normal = FaceNormals[FaceIndex];
124+
// 6 ______7______ 8
125+
// | .'| .'|
126+
// | .' | .' |
127+
// |.'____|.'____|
128+
// 3| .'|4 .'|5
129+
// | .' | .' |
130+
// |.'____|.'____|
131+
// 0 1 2
132+
133+
for (Uint32 y = 0; y <= NumSubdivisions; ++y)
134+
{
135+
for (Uint32 x = 0; x <= NumSubdivisions; ++x)
136+
{
137+
float2 UV{
138+
static_cast<float>(x) / NumSubdivisions,
139+
static_cast<float>(y) / NumSubdivisions,
140+
};
141+
142+
float2 XY{
143+
UV.x - 0.5f,
144+
0.5f - UV.y,
145+
};
146+
147+
float3 Pos;
148+
switch (FaceIndex)
149+
{
150+
case 0: Pos = float3{+0.5f, XY.y, +XY.x}; break;
151+
case 1: Pos = float3{-0.5f, XY.y, -XY.x}; break;
152+
case 2: Pos = float3{XY.x, +0.5f, +XY.y}; break;
153+
case 3: Pos = float3{XY.x, -0.5f, -XY.y}; break;
154+
case 4: Pos = float3{-XY.x, XY.y, +0.5f}; break;
155+
case 5: Pos = float3{+XY.x, XY.y, -0.5f}; break;
156+
}
157+
158+
if (VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_POSITION)
159+
{
160+
Pos *= Size;
161+
memcpy(pVert, &Pos, sizeof(Pos));
162+
pVert += sizeof(Pos);
163+
}
164+
165+
if (VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_NORMAL)
166+
{
167+
memcpy(pVert, &Normal, sizeof(Normal));
168+
pVert += sizeof(Normal);
169+
}
170+
171+
if (VertexFlags & GEOMETRY_PRIMITIVE_VERTEX_FLAG_TEXCOORD)
172+
{
173+
memcpy(pVert, &UV, sizeof(UV));
174+
pVert += sizeof(UV);
175+
}
176+
}
177+
}
178+
}
179+
180+
if (pIdx != nullptr)
181+
{
182+
Uint32 FaceBaseVertex = FaceIndex * NumFaceVertices;
183+
for (Uint32 y = 0; y < NumSubdivisions; ++y)
184+
{
185+
for (Uint32 x = 0; x < NumSubdivisions; ++x)
186+
{
187+
// 01 11
188+
// *-----*
189+
// | .'|
190+
// | .' |
191+
// *'----*
192+
// 00 10
193+
Uint32 v00 = FaceBaseVertex + y * (NumSubdivisions + 1) + x;
194+
Uint32 v10 = v00 + 1;
195+
Uint32 v01 = v00 + NumSubdivisions + 1;
196+
Uint32 v11 = v01 + 1;
197+
198+
*pIdx++ = v00;
199+
*pIdx++ = v10;
200+
*pIdx++ = v11;
201+
202+
*pIdx++ = v00;
203+
*pIdx++ = v11;
204+
*pIdx++ = v01;
205+
}
206+
}
207+
}
208+
}
209+
210+
VERIFY_EXPR(pVert == nullptr || pVert == pVertexData->GetConstDataPtr<Uint8>() + VertexDataSize);
211+
VERIFY_EXPR(pIdx == nullptr || pIdx == pIndexData->GetConstDataPtr<Uint32>() + IndexDataSize / sizeof(Uint32));
212+
}
213+
214+
} // namespace Diligent
215+
216+
extern "C"
217+
{
218+
Diligent::Uint32 Diligent_GetGeometryPrimitiveVertexSize(Diligent::GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags)
219+
{
220+
return Diligent::GetGeometryPrimitiveVertexSize(VertexFlags);
221+
}
222+
223+
void Diligent_CreateCubeGeometry(float Size,
224+
Diligent::Uint32 SubdivisionLevel,
225+
Diligent::GEOMETRY_PRIMITIVE_VERTEX_FLAGS VertexFlags,
226+
Diligent::IDataBlob** ppVertices,
227+
Diligent::IDataBlob** ppIndices,
228+
Diligent::Uint32* pNumVertices,
229+
Diligent::Uint32* pNumIndices)
230+
{
231+
Diligent::CreateCubeGeometry(Size, SubdivisionLevel, VertexFlags, ppVertices, ppIndices, pNumVertices, pNumIndices);
232+
}
233+
}

0 commit comments

Comments
 (0)