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