1/*
2Open Asset Import Library (assimp)
3----------------------------------------------------------------------
4
5Copyright (c) 2006-2017, assimp team
6
7All rights reserved.
8
9Redistribution and use of this software in source and binary forms,
10with or without modification, are permitted provided that the
11following conditions are met:
12
13* Redistributions of source code must retain the above
14 copyright notice, this list of conditions and the
15 following disclaimer.
16
17* Redistributions in binary form must reproduce the above
18 copyright notice, this list of conditions and the
19 following disclaimer in the documentation and/or other
20 materials provided with the distribution.
21
22* Neither the name of the assimp team, nor the names of its
23 contributors may be used to endorse or promote products
24 derived from this software without specific prior
25 written permission of the assimp team.
26
27THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
30A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
31OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
32SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
33LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38
39----------------------------------------------------------------------
40*/
41/** @file Defines a helper class to represent an interleaved vertex
42 along with arithmetic operations to support vertex operations
43 such as subdivision, smoothing etc.
44
45 While the code is kept as general as possible, arithmetic operations
46 that are not currently well-defined (and would cause compile errors
47 due to missing operators in the math library), are commented.
48 */
49#ifndef AI_VERTEX_H_INC
50#define AI_VERTEX_H_INC
51
52#include <assimp/vector3.h>
53#include <assimp/mesh.h>
54#include <assimp/ai_assert.h>
55#include <functional>
56
57namespace Assimp {
58
59 ///////////////////////////////////////////////////////////////////////////
60 // std::plus-family operates on operands with identical types - we need to
61 // support all the (vectype op float) combinations in vector maths.
62 // Providing T(float) would open the way to endless implicit conversions.
63 ///////////////////////////////////////////////////////////////////////////
64 namespace Intern {
65 template <typename T0, typename T1, typename TRES = T0> struct plus {
66 TRES operator() (const T0& t0, const T1& t1) const {
67 return t0+t1;
68 }
69 };
70 template <typename T0, typename T1, typename TRES = T0> struct minus {
71 TRES operator() (const T0& t0, const T1& t1) const {
72 return t0-t1;
73 }
74 };
75 template <typename T0, typename T1, typename TRES = T0> struct multiplies {
76 TRES operator() (const T0& t0, const T1& t1) const {
77 return t0*t1;
78 }
79 };
80 template <typename T0, typename T1, typename TRES = T0> struct divides {
81 TRES operator() (const T0& t0, const T1& t1) const {
82 return t0/t1;
83 }
84 };
85 }
86
87// ------------------------------------------------------------------------------------------------
88/** Intermediate description a vertex with all possible components. Defines a full set of
89 * operators, so you may use such a 'Vertex' in basic arithmetics. All operators are applied
90 * to *all* vertex components equally. This is useful for stuff like interpolation
91 * or subdivision, but won't work if special handling is required for some vertex components. */
92// ------------------------------------------------------------------------------------------------
93class Vertex
94{
95 friend Vertex operator + (const Vertex&,const Vertex&);
96 friend Vertex operator - (const Vertex&,const Vertex&);
97
98// friend Vertex operator + (const Vertex&,ai_real);
99// friend Vertex operator - (const Vertex&,ai_real);
100 friend Vertex operator * (const Vertex&,ai_real);
101 friend Vertex operator / (const Vertex&,ai_real);
102
103// friend Vertex operator + (ai_real, const Vertex&);
104// friend Vertex operator - (ai_real, const Vertex&);
105 friend Vertex operator * (ai_real, const Vertex&);
106// friend Vertex operator / (ai_real, const Vertex&);
107
108public:
109
110 Vertex() {}
111
112 // ----------------------------------------------------------------------------
113 /** Extract a particular vertex from a mesh and interleave all components */
114 explicit Vertex(const aiMesh* msh, unsigned int idx) {
115 ai_assert(idx < msh->mNumVertices);
116 position = msh->mVertices[idx];
117
118 if (msh->HasNormals()) {
119 normal = msh->mNormals[idx];
120 }
121
122 if (msh->HasTangentsAndBitangents()) {
123 tangent = msh->mTangents[idx];
124 bitangent = msh->mBitangents[idx];
125 }
126
127 for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
128 texcoords[i] = msh->mTextureCoords[i][idx];
129 }
130
131 for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
132 colors[i] = msh->mColors[i][idx];
133 }
134 }
135
136public:
137
138 Vertex& operator += (const Vertex& v) {
139 *this = *this+v;
140 return *this;
141 }
142
143 Vertex& operator -= (const Vertex& v) {
144 *this = *this-v;
145 return *this;
146 }
147
148
149/*
150 Vertex& operator += (ai_real v) {
151 *this = *this+v;
152 return *this;
153 }
154
155 Vertex& operator -= (ai_real v) {
156 *this = *this-v;
157 return *this;
158 }
159*/
160 Vertex& operator *= (ai_real v) {
161 *this = *this*v;
162 return *this;
163 }
164
165 Vertex& operator /= (ai_real v) {
166 *this = *this/v;
167 return *this;
168 }
169
170public:
171
172 // ----------------------------------------------------------------------------
173 /** Convert back to non-interleaved storage */
174 void SortBack(aiMesh* out, unsigned int idx) const {
175
176 ai_assert(idx<out->mNumVertices);
177 out->mVertices[idx] = position;
178
179 if (out->HasNormals()) {
180 out->mNormals[idx] = normal;
181 }
182
183 if (out->HasTangentsAndBitangents()) {
184 out->mTangents[idx] = tangent;
185 out->mBitangents[idx] = bitangent;
186 }
187
188 for(unsigned int i = 0; out->HasTextureCoords(i); ++i) {
189 out->mTextureCoords[i][idx] = texcoords[i];
190 }
191
192 for(unsigned int i = 0; out->HasVertexColors(i); ++i) {
193 out->mColors[i][idx] = colors[i];
194 }
195 }
196
197private:
198
199 // ----------------------------------------------------------------------------
200 /** Construct from two operands and a binary operation to combine them */
201 template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
202 // this is a heavy task for the compiler to optimize ... *pray*
203
204 Vertex res;
205 res.position = op<aiVector3D>()(v0.position,v1.position);
206 res.normal = op<aiVector3D>()(v0.normal,v1.normal);
207 res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent);
208 res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent);
209
210 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
211 res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]);
212 }
213 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
214 res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]);
215 }
216 return res;
217 }
218
219 // ----------------------------------------------------------------------------
220 /** This time binary arithmetics of v0 with a floating-point number */
221 template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, ai_real f) {
222 // this is a heavy task for the compiler to optimize ... *pray*
223
224 Vertex res;
225 res.position = op<aiVector3D,ai_real,aiVector3D>()(v0.position,f);
226 res.normal = op<aiVector3D,ai_real,aiVector3D>()(v0.normal,f);
227 res.tangent = op<aiVector3D,ai_real,aiVector3D>()(v0.tangent,f);
228 res.bitangent = op<aiVector3D,ai_real,aiVector3D>()(v0.bitangent,f);
229
230 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
231 res.texcoords[i] = op<aiVector3D,ai_real,aiVector3D>()(v0.texcoords[i],f);
232 }
233 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
234 res.colors[i] = op<aiColor4D,ai_real,aiColor4D>()(v0.colors[i],f);
235 }
236 return res;
237 }
238
239 // ----------------------------------------------------------------------------
240 /** This time binary arithmetics of v0 with a floating-point number */
241 template <template <typename, typename, typename> class op> static Vertex BinaryOp(ai_real f, const Vertex& v0) {
242 // this is a heavy task for the compiler to optimize ... *pray*
243
244 Vertex res;
245 res.position = op<ai_real,aiVector3D,aiVector3D>()(f,v0.position);
246 res.normal = op<ai_real,aiVector3D,aiVector3D>()(f,v0.normal);
247 res.tangent = op<ai_real,aiVector3D,aiVector3D>()(f,v0.tangent);
248 res.bitangent = op<ai_real,aiVector3D,aiVector3D>()(f,v0.bitangent);
249
250 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
251 res.texcoords[i] = op<ai_real,aiVector3D,aiVector3D>()(f,v0.texcoords[i]);
252 }
253 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
254 res.colors[i] = op<ai_real,aiColor4D,aiColor4D>()(f,v0.colors[i]);
255 }
256 return res;
257 }
258
259public:
260
261 aiVector3D position;
262 aiVector3D normal;
263 aiVector3D tangent, bitangent;
264
265 aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
266 aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
267};
268
269
270
271// ------------------------------------------------------------------------------------------------
272AI_FORCE_INLINE Vertex operator + (const Vertex& v0,const Vertex& v1) {
273 return Vertex::BinaryOp<std::plus>(v0,v1);
274}
275
276AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) {
277 return Vertex::BinaryOp<std::minus>(v0,v1);
278}
279
280
281// ------------------------------------------------------------------------------------------------
282/*
283AI_FORCE_INLINE Vertex operator + (const Vertex& v0,ai_real f) {
284 return Vertex::BinaryOp<Intern::plus>(v0,f);
285}
286
287AI_FORCE_INLINE Vertex operator - (const Vertex& v0,ai_real f) {
288 return Vertex::BinaryOp<Intern::minus>(v0,f);
289}
290
291*/
292
293AI_FORCE_INLINE Vertex operator * (const Vertex& v0,ai_real f) {
294 return Vertex::BinaryOp<Intern::multiplies>(v0,f);
295}
296
297AI_FORCE_INLINE Vertex operator / (const Vertex& v0,ai_real f) {
298 return Vertex::BinaryOp<Intern::multiplies>(v0,1.f/f);
299}
300
301// ------------------------------------------------------------------------------------------------
302/*
303AI_FORCE_INLINE Vertex operator + (ai_real f,const Vertex& v0) {
304 return Vertex::BinaryOp<Intern::plus>(f,v0);
305}
306
307AI_FORCE_INLINE Vertex operator - (ai_real f,const Vertex& v0) {
308 return Vertex::BinaryOp<Intern::minus>(f,v0);
309}
310*/
311
312AI_FORCE_INLINE Vertex operator * (ai_real f,const Vertex& v0) {
313 return Vertex::BinaryOp<Intern::multiplies>(f,v0);
314}
315
316/*
317AI_FORCE_INLINE Vertex operator / (ai_real f,const Vertex& v0) {
318 return Vertex::BinaryOp<Intern::divides>(f,v0);
319}
320*/
321
322}
323#endif
324