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