302 lines
10 KiB
C
302 lines
10 KiB
C
|
/*
|
||
|
Open Asset Import Library (ASSIMP)
|
||
|
----------------------------------------------------------------------
|
||
|
|
||
|
Copyright (c) 2006-2008, ASSIMP Development Team
|
||
|
All rights reserved.
|
||
|
|
||
|
Redistribution and use of this software in source and binary forms,
|
||
|
with or without modification, are permitted provided that the
|
||
|
following conditions are met:
|
||
|
|
||
|
* Redistributions of source code must retain the above
|
||
|
copyright notice, this list of conditions and the
|
||
|
following disclaimer.
|
||
|
|
||
|
* Redistributions in binary form must reproduce the above
|
||
|
copyright notice, this list of conditions and the
|
||
|
following disclaimer in the documentation and/or other
|
||
|
materials provided with the distribution.
|
||
|
|
||
|
* Neither the name of the ASSIMP team, nor the names of its
|
||
|
contributors may be used to endorse or promote products
|
||
|
derived from this software without specific prior
|
||
|
written permission of the ASSIMP Development Team.
|
||
|
|
||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
||
|
----------------------------------------------------------------------
|
||
|
*/
|
||
|
/** @file Defines a helper class to represent an interleaved vertex */
|
||
|
#ifndef AI_VERTEX_H_INC
|
||
|
#define AI_VERTEX_H_INC
|
||
|
namespace Assimp {
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
// std::plus-family operates on operands with identical types - we need to
|
||
|
// support all the (vectype op float) combinations in vector maths.
|
||
|
// Providing T(float) would open the way to endless implicit conversions.
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
namespace Intern {
|
||
|
template <typename T0, typename T1, typename TRES = T0> struct plus {
|
||
|
TRES operator() (const T0& t0, const T1& t1) const {
|
||
|
return t0+t1;
|
||
|
}
|
||
|
};
|
||
|
template <typename T0, typename T1, typename TRES = T0> struct minus {
|
||
|
TRES operator() (const T0& t0, const T1& t1) const {
|
||
|
return t0-t1;
|
||
|
}
|
||
|
};
|
||
|
template <typename T0, typename T1, typename TRES = T0> struct multiplies {
|
||
|
TRES operator() (const T0& t0, const T1& t1) const {
|
||
|
return t0*t1;
|
||
|
}
|
||
|
};
|
||
|
template <typename T0, typename T1, typename TRES = T0> struct divides {
|
||
|
TRES operator() (const T0& t0, const T1& t1) const {
|
||
|
return t0/t1;
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
/** Intermediate description a vertex with all possible components. Defines a full set of
|
||
|
* operators, so you may use such a 'Vertex' in basic arithmetics. All operators are applied
|
||
|
* to *all* vertex components equally. This is useful for stuff like interpolation
|
||
|
* or subdivision, but won't work if special handling is required for some vertex components. */
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
class Vertex
|
||
|
{
|
||
|
friend Vertex operator + (const Vertex&,const Vertex&);
|
||
|
friend Vertex operator - (const Vertex&,const Vertex&);
|
||
|
|
||
|
friend Vertex operator + (const Vertex&,float);
|
||
|
friend Vertex operator - (const Vertex&,float);
|
||
|
friend Vertex operator * (const Vertex&,float);
|
||
|
friend Vertex operator / (const Vertex&,float);
|
||
|
|
||
|
friend Vertex operator + (float, const Vertex&);
|
||
|
friend Vertex operator - (float, const Vertex&);
|
||
|
friend Vertex operator * (float, const Vertex&);
|
||
|
friend Vertex operator / (float, const Vertex&);
|
||
|
|
||
|
public:
|
||
|
|
||
|
Vertex() {}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
/** Extract a particular vertex from a mesh and interleave all components */
|
||
|
explicit Vertex(const aiMesh* msh, unsigned int idx) {
|
||
|
ai_assert(idx < msh->mNumVertices);
|
||
|
position = msh->mVertices[idx];
|
||
|
|
||
|
if (msh->HasNormals()) {
|
||
|
normal = msh->mNormals[idx];
|
||
|
}
|
||
|
|
||
|
if (msh->HasTangentsAndBitangents()) {
|
||
|
tangent = msh->mTangents[idx];
|
||
|
bitangent = msh->mBitangents[idx];
|
||
|
}
|
||
|
|
||
|
for (unsigned int i = 0; msh->HasTextureCoords(i); ++i) {
|
||
|
texcoords[i] = msh->mTextureCoords[i][idx];
|
||
|
}
|
||
|
|
||
|
for (unsigned int i = 0; msh->HasVertexColors(i); ++i) {
|
||
|
colors[i] = msh->mColors[i][idx];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
Vertex& operator += (const Vertex& v) {
|
||
|
*this = *this+v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
Vertex& operator -= (const Vertex& v) {
|
||
|
*this = *this-v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
Vertex& operator += (float v) {
|
||
|
*this = *this+v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
Vertex& operator -= (float v) {
|
||
|
*this = *this-v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
Vertex& operator *= (float v) {
|
||
|
*this = *this*v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
Vertex& operator /= (float v) {
|
||
|
*this = *this/v;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
/** Convert back to non-interleaved storage */
|
||
|
void SortBack(aiMesh* out, unsigned int idx) const {
|
||
|
|
||
|
ai_assert(idx<out->mNumVertices);
|
||
|
out->mVertices[idx] = position;
|
||
|
|
||
|
if (out->HasNormals()) {
|
||
|
out->mNormals[idx] = normal;
|
||
|
}
|
||
|
|
||
|
if (out->HasTangentsAndBitangents()) {
|
||
|
out->mTangents[idx] = tangent;
|
||
|
out->mBitangents[idx] = bitangent;
|
||
|
}
|
||
|
|
||
|
for(unsigned int i = 0; out->HasTextureCoords(i); ++i) {
|
||
|
out->mTextureCoords[i][idx] = texcoords[i];
|
||
|
}
|
||
|
|
||
|
for(unsigned int i = 0; out->HasVertexColors(i); ++i) {
|
||
|
out->mColors[i][idx] = colors[i];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
/** Construct from two operands and a binary operation to combine them */
|
||
|
template <template <typename t> class op> static Vertex BinaryOp(const Vertex& v0, const Vertex& v1) {
|
||
|
// this is a heavy task for the compiler to optimize ... *pray*
|
||
|
|
||
|
Vertex res;
|
||
|
res.position = op<aiVector3D>()(v0.position,v1.position);
|
||
|
res.normal = op<aiVector3D>()(v0.normal,v1.normal);
|
||
|
res.tangent = op<aiVector3D>()(v0.tangent,v1.tangent);
|
||
|
res.bitangent = op<aiVector3D>()(v0.bitangent,v1.bitangent);
|
||
|
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||
|
res.texcoords[i] = op<aiVector3D>()(v0.texcoords[i],v1.texcoords[i]);
|
||
|
}
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||
|
res.colors[i] = op<aiColor4D>()(v0.colors[i],v1.colors[i]);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
/** This time binary arithmetics of v0 with a floating-point number */
|
||
|
template <template <typename, typename, typename> class op> static Vertex BinaryOp(const Vertex& v0, float f) {
|
||
|
// this is a heavy task for the compiler to optimize ... *pray*
|
||
|
|
||
|
Vertex res;
|
||
|
res.position = op<aiVector3D,float,aiVector3D>()(v0.position,f);
|
||
|
res.normal = op<aiVector3D,float,aiVector3D>()(v0.normal,f);
|
||
|
res.tangent = op<aiVector3D,float,aiVector3D>()(v0.tangent,f);
|
||
|
res.bitangent = op<aiVector3D,float,aiVector3D>()(v0.bitangent,f);
|
||
|
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||
|
res.texcoords[i] = op<aiVector3D,float,aiVector3D>()(v0.texcoords[i],f);
|
||
|
}
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||
|
res.colors[i] = op<aiColor4D,float,aiColor4D>()(v0.colors[i],f);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// ----------------------------------------------------------------------------
|
||
|
/** This time binary arithmetics of v0 with a floating-point number */
|
||
|
template <template <typename, typename, typename> class op> static Vertex BinaryOp(float f, const Vertex& v0) {
|
||
|
// this is a heavy task for the compiler to optimize ... *pray*
|
||
|
|
||
|
Vertex res;
|
||
|
res.position = op<float,aiVector3D,aiVector3D>()(f,v0.position);
|
||
|
res.normal = op<float,aiVector3D,aiVector3D>()(f,v0.normal);
|
||
|
res.tangent = op<float,aiVector3D,aiVector3D>()(f,v0.tangent);
|
||
|
res.bitangent = op<float,aiVector3D,aiVector3D>()(f,v0.bitangent);
|
||
|
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
|
||
|
res.texcoords[i] = op<float,aiVector3D,aiVector3D>()(f,v0.texcoords[i]);
|
||
|
}
|
||
|
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
|
||
|
res.colors[i] = op<float,aiColor4D,aiColor4D>()(f,v0.colors[i]);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
|
||
|
aiVector3D position;
|
||
|
aiVector3D normal;
|
||
|
aiVector3D tangent, bitangent;
|
||
|
|
||
|
aiVector3D texcoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
|
||
|
aiColor4D colors[AI_MAX_NUMBER_OF_COLOR_SETS];
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
AI_FORCE_INLINE Vertex operator + (const Vertex& v0,const Vertex& v1) {
|
||
|
return Vertex::BinaryOp<std::plus>(v0,v1);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator - (const Vertex& v0,const Vertex& v1) {
|
||
|
return Vertex::BinaryOp<std::minus>(v0,v1);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
AI_FORCE_INLINE Vertex operator + (const Vertex& v0,float f) {
|
||
|
return Vertex::BinaryOp<Intern::plus>(v0,f);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator - (const Vertex& v0,float f) {
|
||
|
return Vertex::BinaryOp<Intern::minus>(v0,f);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator * (const Vertex& v0,float f) {
|
||
|
return Vertex::BinaryOp<Intern::multiplies>(v0,f);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator / (const Vertex& v0,float f) {
|
||
|
return Vertex::BinaryOp<Intern::divides>(v0,f);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------------------------------------------------------------------
|
||
|
AI_FORCE_INLINE Vertex operator + (float f,const Vertex& v0) {
|
||
|
return Vertex::BinaryOp<Intern::plus>(f,v0);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator - (float f,const Vertex& v0) {
|
||
|
return Vertex::BinaryOp<Intern::minus>(f,v0);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator * (float f,const Vertex& v0) {
|
||
|
return Vertex::BinaryOp<Intern::multiplies>(f,v0);
|
||
|
}
|
||
|
|
||
|
AI_FORCE_INLINE Vertex operator / (float f,const Vertex& v0) {
|
||
|
return Vertex::BinaryOp<Intern::divides>(f,v0);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
#endif
|