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