| 1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
| 2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
| 3 | #pragma once |
| 4 | |
| 5 | #include "BsCorePrerequisites.h" |
| 6 | #include "Math/BsVector3.h" |
| 7 | |
| 8 | namespace bs |
| 9 | { |
| 10 | /** @addtogroup Utility-Core |
| 11 | * @{ |
| 12 | */ |
| 13 | |
| 14 | /** Normal packed in a 32-bit structure. */ |
| 15 | union PackedNormal |
| 16 | { |
| 17 | struct |
| 18 | { |
| 19 | UINT8 x; |
| 20 | UINT8 y; |
| 21 | UINT8 z; |
| 22 | UINT8 w; |
| 23 | }; |
| 24 | |
| 25 | UINT32 packed; |
| 26 | }; |
| 27 | |
| 28 | /** Performs various operations on mesh geometry. */ |
| 29 | class BS_CORE_EXPORT MeshUtility |
| 30 | { |
| 31 | public: |
| 32 | /** |
| 33 | * Calculates per-vertex normals based on the provided vertices and indices. |
| 34 | * |
| 35 | * @param[in] vertices Set of vertices containing vertex positions. |
| 36 | * @param[in] indices Set of indices containing indexes into vertex array for each triangle. |
| 37 | * @param[in] numVertices Number of vertices in the @p vertices array. |
| 38 | * @param[in] numIndices Number of indices in the @p indices array. Must be a multiple of three. |
| 39 | * @param[out] normals Pre-allocated buffer that will contain the calculated normals. Must be the same size |
| 40 | * as the vertex array. |
| 41 | * @param[in] indexSize Size of a single index in the indices array, in bytes. |
| 42 | * |
| 43 | * @note |
| 44 | * Vertices should be split before calling this method if there are any discontinuities. (for example a vertex on a |
| 45 | * corner of a cube should be split into three vertices used by three triangles in order for the normals to be |
| 46 | * valid.) |
| 47 | */ |
| 48 | static void calculateNormals(Vector3* vertices, UINT8* indices, UINT32 numVertices, |
| 49 | UINT32 numIndices, Vector3* normals, UINT32 indexSize = 4); |
| 50 | |
| 51 | /** |
| 52 | * Calculates per-vertex tangents and bitangents based on the provided vertices, uv coordinates and indices. |
| 53 | * |
| 54 | * @param[in] vertices Set of vertices containing vertex positions. |
| 55 | * @param[in] normals Set of normals to use when calculating tangents. Must the the same length as the |
| 56 | * number of vertices. |
| 57 | * @param[in] uv Set of UV coordinates to use when calculating tangents. Must the the same length as |
| 58 | * the number of vertices. |
| 59 | * @param[in] indices Set of indices containing indexes into vertex array for each triangle. |
| 60 | * @param[in] numVertices Number of vertices in the @p vertices, @p normals and @p uv arrays. |
| 61 | * @param[in] numIndices Number of indices in the @p indices array. Must be a multiple of three. |
| 62 | * @param[out] tangents Pre-allocated buffer that will contain the calculated tangents. Must be the same |
| 63 | * size as the vertex array. |
| 64 | * @param[out] bitangents Pre-allocated buffer that will contain the calculated bitangents. Must be the same |
| 65 | * size as the vertex array. |
| 66 | * @param[in] indexSize Size of a single index in the indices array, in bytes. |
| 67 | * @param[in] vertexStride Number of bytes to advance the @p vertices, @p normals and @p uv arrays with each |
| 68 | * vertex. If set to zero them each array is advanced according to its own size. |
| 69 | * |
| 70 | * @note |
| 71 | * Vertices should be split before calling this method if there are any discontinuities. (for example a vertex on a |
| 72 | * corner of a cube should be split into three vertices used by three triangles in order for the normals to be |
| 73 | * valid.) |
| 74 | */ |
| 75 | static void calculateTangents(Vector3* vertices, Vector3* normals, Vector2* uv, UINT8* indices, UINT32 numVertices, |
| 76 | UINT32 numIndices, Vector3* tangents, Vector3* bitangents, UINT32 indexSize = 4, UINT32 vertexStride = 0); |
| 77 | |
| 78 | /** |
| 79 | * Calculates per-vertex tangent space (normal, tangent, bitangent) based on the provided vertices, uv coordinates |
| 80 | * and indices. |
| 81 | * |
| 82 | * @param[in] vertices Set of vertices containing vertex positions. |
| 83 | * @param[in] uv Set of UV coordinates to use when calculating tangents. |
| 84 | * @param[in] indices Set of indices containing indexes into vertex array for each triangle. |
| 85 | * @param[in] numVertices Number of vertices in the "vertices" array. |
| 86 | * @param[in] numIndices Number of indices in the "indices" array. Must be a multiple of three. |
| 87 | * @param[out] normals Pre-allocated buffer that will contain the calculated normals. Must be the same size |
| 88 | * as the vertex array. |
| 89 | * @param[out] tangents Pre-allocated buffer that will contain the calculated tangents. Must be the same size |
| 90 | * as the vertex array. |
| 91 | * @param[out] bitangents Pre-allocated buffer that will contain the calculated bitangents. Must be the same size |
| 92 | * as the vertex array. |
| 93 | * @param[in] indexSize Size of a single index in the indices array, in bytes. |
| 94 | * |
| 95 | * @note |
| 96 | * Vertices should be split before calling this method if there are any discontinuities. (for example. a vertex on |
| 97 | * a corner of a cube should be split into three vertices used by three triangles in order for the normals to be |
| 98 | * valid.) |
| 99 | */ |
| 100 | static void calculateTangentSpace(Vector3* vertices, Vector2* uv, UINT8* indices, UINT32 numVertices, |
| 101 | UINT32 numIndices, Vector3* normals, Vector3* tangents, Vector3* bitangents, UINT32 indexSize = 4); |
| 102 | |
| 103 | /** |
| 104 | * Clips a set of two-dimensional vertices and uv coordinates against a set of arbitrary planes. |
| 105 | * |
| 106 | * @param[in] vertices A set of vertices in Vector2 format. Each vertex should be @p vertexStride bytes |
| 107 | * from each other. |
| 108 | * @param[in] uvs A set of UV coordinates in Vector2 format. Each coordinate should be |
| 109 | * @p vertexStride bytes from each other. Can be null if UV is not needed. |
| 110 | * @param[in] numTris Number of triangles to clip (must be number of vertices/uvs / 3). |
| 111 | * @param[in] vertexStride Distance in bytes between two separate vertex or UV values in the provided |
| 112 | * @p vertices and @p uvs buffers. |
| 113 | * @param[in] clipPlanes A set of planes to clip the vertices against. Since the vertices are |
| 114 | * two-dimensional the plane's Z coordinate should be zero. |
| 115 | * @param[in] writeCallback Callback that will be triggered when clipped vertices and UV coordinates are |
| 116 | * generated and need to be stored. Vertices are always generate in tuples of |
| 117 | * three, forming a single triangle. |
| 118 | */ |
| 119 | static void clip2D(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes, |
| 120 | const std::function<void(Vector2*, Vector2*, UINT32)>& writeCallback); |
| 121 | |
| 122 | /** |
| 123 | * Clips a set of three-dimensional vertices and uv coordinates against a set of arbitrary planes. |
| 124 | * |
| 125 | * @param[in] vertices A set of vertices in Vector3 format. Each vertex should be @p vertexStride bytes |
| 126 | * from each other. |
| 127 | * @param[in] uvs A set of UV coordinates in Vector2 format. Each coordinate should be |
| 128 | * @p vertexStride bytes from each other. Can be null if UV is not needed. |
| 129 | * @param[in] numTris Number of triangles to clip (must be number of vertices/uvs / 3). |
| 130 | * @param[in] vertexStride Distance in bytes between two separate vertex or UV values in the provided |
| 131 | * @p vertices and @p uvs buffers. |
| 132 | * @param[in] clipPlanes A set of planes to clip the vertices against. |
| 133 | * @param[in] writeCallback Callback that will be triggered when clipped vertices and UV coordinates are |
| 134 | * generated and need to be stored. Vertices are always generate in tuples of |
| 135 | * three, forming a single triangle. |
| 136 | */ |
| 137 | static void clip3D(UINT8* vertices, UINT8* uvs, UINT32 numTris, UINT32 vertexStride, const Vector<Plane>& clipPlanes, |
| 138 | const std::function<void(Vector3*, Vector2*, UINT32)>& writeCallback); |
| 139 | |
| 140 | /** |
| 141 | * Encodes normals from 32-bit float format into 4D 8-bit packed format. |
| 142 | * |
| 143 | * @param[in] source Buffer containing data to encode. Must have @p count entries. |
| 144 | * @param[out] destination Buffer to output the data to. Must have @p count entries, each 32-bits. |
| 145 | * @param[in] count Number of entries in the @p source and @p destination arrays. |
| 146 | * @param[in] inStride Distance between two entries in the @p source buffer, in bytes. |
| 147 | * @param[in] outStride Distance between two entries in the @p destination buffer, in bytes. |
| 148 | */ |
| 149 | static void packNormals(Vector3* source, UINT8* destination, UINT32 count, UINT32 inStride, UINT32 outStride); |
| 150 | |
| 151 | /** |
| 152 | * Encodes normals from 32-bit float format into 4D 8-bit packed format. |
| 153 | * |
| 154 | * @param[in] source Buffer containing data to encode. Must have @p count entries. |
| 155 | * @param[out] destination Buffer to output the data to. Must have @p count entries, each 32-bits. |
| 156 | * @param[in] count Number of entries in the @p source and @p destination arrays. |
| 157 | * @param[in] inStride Distance between two entries in the @p source buffer, in bytes. |
| 158 | * @param[in] outStride Distance between two entries in the @p destination buffer, in bytes. |
| 159 | */ |
| 160 | static void packNormals(Vector4* source, UINT8* destination, UINT32 count, UINT32 inStride, UINT32 outStride); |
| 161 | |
| 162 | /** |
| 163 | * Decodes normals from 4D 8-bit packed format into a 32-bit float format. |
| 164 | * |
| 165 | * @param[in] source Buffer containing data to encode. Must have @p count entries, each 32-bits. |
| 166 | * @param[out] destination Buffer to output the data to. Must have @p count entries. |
| 167 | * @param[in] count Number of entries in the @p source and @p destination arrays. |
| 168 | * @param[in] stride Distance between two entries in the @p source buffer, in bytes. |
| 169 | */ |
| 170 | static void unpackNormals(UINT8* source, Vector3* destination, UINT32 count, UINT32 stride); |
| 171 | |
| 172 | /** |
| 173 | * Decodes normals from 4D 8-bit packed format into a 32-bit float format. |
| 174 | * |
| 175 | * @param[in] source Buffer containing data to encode. Must have @p count entries, each 32-bits. |
| 176 | * @param[out] destination Buffer to output the data to. Must have @p count entries. |
| 177 | * @param[in] count Number of entries in the @p source and @p destination arrays. |
| 178 | * @param[in] stride Distance between two entries in the @p source buffer, in bytes. |
| 179 | */ |
| 180 | static void unpackNormals(UINT8* source, Vector4* destination, UINT32 count, UINT32 stride); |
| 181 | |
| 182 | /** Decodes a normal from 4D 8-bit packed format into a 32-bit float format. */ |
| 183 | static Vector3 unpackNormal(const UINT8* source) |
| 184 | { |
| 185 | const PackedNormal& packed = *(PackedNormal*)source; |
| 186 | Vector3 output; |
| 187 | |
| 188 | const float inv = (1.0f / 255.0f) * 2.0f; |
| 189 | output.x = (packed.x * inv - 1.0f); |
| 190 | output.y = (packed.y * inv - 1.0f); |
| 191 | output.z = (packed.z * inv - 1.0f); |
| 192 | |
| 193 | return output; |
| 194 | } |
| 195 | }; |
| 196 | |
| 197 | /** @} */ |
| 198 | } |
| 199 | |