|
| 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