Added support for cones and cylinders to NFF (the code to generate these primitives is hosted in StandardShapes.cpp).
Fixed some minor material bugs in NFF. Added some more test NFF files, refactored and commented the old ones. Added FromToMatrix function to aiMatrix4x4 Temporarily disabled animation support in SMD and fixed some minor bugs. Static models should load correctly in every case. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@254 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
5639220859
commit
be864ce4a0
|
@ -120,5 +120,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
#endif // !! ASSIMP_PCH_INCLUDED
|
||||
|
||||
|
|
|
@ -139,8 +139,8 @@ void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
|
|||
const static float LOWER_LIMIT = 0.1f;
|
||||
const static float UPPER_LIMIT = 0.9f;
|
||||
|
||||
const static float LOWER_EPSILON = 1e-3f;
|
||||
const static float UPPER_EPSILON = 1.f-1e-3f;
|
||||
const static float LOWER_EPSILON = 10e-3f;
|
||||
const static float UPPER_EPSILON = 1.f-10e-3f;
|
||||
|
||||
for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
|
||||
{
|
||||
|
|
|
@ -917,7 +917,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
|||
// Now compute the final local transformation matrix of the
|
||||
// node from the given translation, rotation and scaling values.
|
||||
// (the rotation is given in Euler angles, XYZ order)
|
||||
rootOut->mTransformation.FromEulerAngles(AI_DEG_TO_RAD(root->rotation) );
|
||||
rootOut->mTransformation.FromEulerAnglesXYZ(AI_DEG_TO_RAD(root->rotation) );
|
||||
|
||||
// apply scaling
|
||||
aiMatrix4x4& mat = rootOut->mTransformation;
|
||||
|
|
|
@ -147,6 +147,8 @@ bool LWOImporter::HandleTextures(MaterialHelper* pcMat, const TextureList& in, a
|
|||
aiUVTransform trafo;
|
||||
trafo.mScaling.x = (*it).wrapAmountW;
|
||||
trafo.mScaling.y = (*it).wrapAmountH;
|
||||
|
||||
pcMat->AddProperty((float*)&trafo,sizeof(aiUVTransform),AI_MATKEY_UVTRANSFORM(type,cur));
|
||||
}
|
||||
DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
|
||||
}
|
||||
|
|
|
@ -144,8 +144,8 @@ struct Frame
|
|||
*/
|
||||
struct TexCoord
|
||||
{
|
||||
uint16_t s;
|
||||
uint16_t t;
|
||||
int16_t s;
|
||||
int16_t t;
|
||||
} PACK_STRUCT;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
|
@ -413,8 +413,8 @@ void MD2Importer::InternReadFile( const std::string& pFile,
|
|||
|
||||
// the texture coordinates are absolute values but we
|
||||
// need relative values between 0 and 1
|
||||
pcOut.x = pcTexCoords[iIndex].s / fDivisorU;
|
||||
pcOut.y = 1.f - pcTexCoords[iIndex].t / fDivisorV;
|
||||
pcOut.y = pcTexCoords[iIndex].s / fDivisorU;
|
||||
pcOut.x = pcTexCoords[iIndex].t / fDivisorV;
|
||||
}
|
||||
}
|
||||
// FIX: flip the face order for use with OpenGL
|
||||
|
|
|
@ -665,32 +665,66 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
// 'tpp' - texture polygon patch primitive
|
||||
if ('t' == line[0])
|
||||
{
|
||||
if (meshesWithUVCoords.empty())
|
||||
currentMeshWithUVCoords = NULL;
|
||||
for (std::vector<MeshInfo>::iterator it = meshesWithUVCoords.begin(), end = meshesWithUVCoords.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if ((*it).shader == s)
|
||||
{
|
||||
currentMeshWithUVCoords = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentMeshWithUVCoords)
|
||||
{
|
||||
meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
||||
currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
||||
currentMeshWithUVCoords->shader = s;
|
||||
}
|
||||
|
||||
out = currentMeshWithUVCoords;
|
||||
}
|
||||
// 'pp' - polygon patch primitive
|
||||
else if ('p' == line[1])
|
||||
{
|
||||
if (meshesWithNormals.empty())
|
||||
currentMeshWithNormals = NULL;
|
||||
for (std::vector<MeshInfo>::iterator it = meshesWithNormals.begin(), end = meshesWithNormals.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if ((*it).shader == s)
|
||||
{
|
||||
currentMeshWithNormals = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentMeshWithNormals)
|
||||
{
|
||||
meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
||||
currentMeshWithNormals = &meshesWithNormals.back();
|
||||
currentMeshWithNormals->shader = s;
|
||||
}
|
||||
|
||||
sz = &line[2];out = currentMeshWithNormals;
|
||||
}
|
||||
// 'p' - polygon primitive
|
||||
else
|
||||
{
|
||||
if (meshes.empty())
|
||||
currentMesh = NULL;
|
||||
for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if ((*it).shader == s)
|
||||
{
|
||||
currentMesh = &(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentMesh)
|
||||
{
|
||||
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||
currentMesh = &meshes.back();
|
||||
currentMesh->shader = s;
|
||||
}
|
||||
sz = &line[1];out = currentMesh;
|
||||
}
|
||||
|
@ -711,7 +745,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
if(!GetNextLine(buffer,line))
|
||||
{
|
||||
DefaultLogger::get()->error("NFF: Unexpected EOF was encountered");
|
||||
DefaultLogger::get()->error("NFF: Unexpected EOF was encountered. Patch definition incomplete");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -764,7 +798,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
|
||||
// NFF2 uses full colors here so we need to use them too
|
||||
// although NFF uses simple scaling factors
|
||||
s.diffuse.g = s.diffuse.b = s.diffuse.r;
|
||||
s.diffuse.g = s.diffuse.b = s.diffuse.r;
|
||||
s.specular.g = s.specular.b = s.specular.r;
|
||||
|
||||
// if the next one is NOT a number we assume it is a texture file name
|
||||
|
@ -787,58 +821,14 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
AI_NFF_PARSE_FLOAT(s.ambient); // optional
|
||||
}
|
||||
|
||||
// check whether we have this material already -
|
||||
// although we have the RRM-Step, this is necessary here.
|
||||
// otherwise we would generate hundreds of small meshes
|
||||
// with just a few faces - this is surely never wanted.
|
||||
currentMesh = currentMeshWithNormals = currentMeshWithUVCoords = NULL;
|
||||
for (std::vector<MeshInfo>::iterator it = meshes.begin(), end = meshes.end();
|
||||
it != end;++it)
|
||||
{
|
||||
if ((*it).bLocked)continue;
|
||||
if ((*it).shader == s)
|
||||
{
|
||||
switch ((*it).pType)
|
||||
{
|
||||
case PatchType_Normals:
|
||||
currentMeshWithNormals = &(*it);
|
||||
break;
|
||||
|
||||
case PatchType_Simple:
|
||||
currentMesh = &(*it);
|
||||
break;
|
||||
|
||||
default:
|
||||
currentMeshWithUVCoords = &(*it);
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!currentMesh)
|
||||
{
|
||||
meshes.push_back(MeshInfo(PatchType_Simple));
|
||||
currentMesh = &meshes.back();
|
||||
currentMesh->shader = s;
|
||||
}
|
||||
if (!currentMeshWithNormals)
|
||||
{
|
||||
meshesWithNormals.push_back(MeshInfo(PatchType_Normals));
|
||||
currentMeshWithNormals = &meshesWithNormals.back();
|
||||
currentMeshWithNormals->shader = s;
|
||||
}
|
||||
if (!currentMeshWithUVCoords)
|
||||
{
|
||||
meshesWithUVCoords.push_back(MeshInfo(PatchType_UVAndNormals));
|
||||
currentMeshWithUVCoords = &meshesWithUVCoords.back();
|
||||
currentMeshWithUVCoords->shader = s;
|
||||
}
|
||||
}
|
||||
// 'shader' - other way to specify a texture
|
||||
else if (TokenMatch(sz,"shader",6))
|
||||
{
|
||||
// todo
|
||||
SkipSpaces(&sz);
|
||||
const char* old = sz;
|
||||
while (!IsSpaceOrNewLine(*sz))++sz;
|
||||
s.texFile = std::string(old, (uintptr_t)sz - (uintptr_t)old);
|
||||
}
|
||||
// 'l' - light source
|
||||
else if (TokenMatch(sz,"l",1))
|
||||
|
@ -856,7 +846,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_SPHERE;
|
||||
currentMesh.shader.mapping = aiTextureMapping_SPHERE;
|
||||
|
||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||
|
||||
|
@ -873,7 +863,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_SPHERE;
|
||||
currentMesh.shader.mapping = aiTextureMapping_SPHERE;
|
||||
|
||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||
|
||||
|
@ -891,7 +881,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_SPHERE;
|
||||
currentMesh.shader.mapping = aiTextureMapping_SPHERE;
|
||||
|
||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||
|
||||
|
@ -909,7 +899,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_SPHERE;
|
||||
currentMesh.shader.mapping = aiTextureMapping_SPHERE;
|
||||
|
||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||
|
||||
|
@ -927,7 +917,7 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_SPHERE;
|
||||
currentMesh.shader.mapping = aiTextureMapping_BOX;
|
||||
|
||||
AI_NFF_PARSE_SHAPE_INFORMATION();
|
||||
|
||||
|
@ -942,26 +932,54 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
else if (TokenMatch(sz,"c",1))
|
||||
{
|
||||
meshesLocked.push_back(MeshInfo(PatchType_Simple,true));
|
||||
MeshInfo& currentMesh = meshes.back();
|
||||
MeshInfo& currentMesh = meshesLocked.back();
|
||||
currentMesh.shader = s;
|
||||
s.mapping = aiTextureMapping_CYLINDER;
|
||||
currentMesh.shader.mapping = aiTextureMapping_CYLINDER;
|
||||
|
||||
if(!GetNextLine(buffer,line))
|
||||
{
|
||||
DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
|
||||
break;
|
||||
}
|
||||
sz = line;
|
||||
|
||||
// read the two center points and the respective radii
|
||||
aiVector3D center1, center2; float radius1, radius2;
|
||||
AI_NFF_PARSE_TRIPLE(center1);
|
||||
AI_NFF_PARSE_FLOAT(radius1);
|
||||
|
||||
if(!GetNextLine(buffer,line))
|
||||
{
|
||||
DefaultLogger::get()->error("NFF: Unexpected end of file (cone definition not complete)");
|
||||
break;
|
||||
}
|
||||
sz = line;
|
||||
|
||||
AI_NFF_PARSE_TRIPLE(center2);
|
||||
AI_NFF_PARSE_FLOAT(radius2);
|
||||
|
||||
// compute the center point of the cone/cylinder
|
||||
center2 = (center2-center1)/2.f;
|
||||
currentMesh.center = center1+center2;
|
||||
center1 = -center2;
|
||||
// compute the center point of the cone/cylinder -
|
||||
// it is its local transformation origin
|
||||
currentMesh.dir = center2-center1;
|
||||
currentMesh.center = center1+currentMesh.dir/2.f;
|
||||
|
||||
float f;
|
||||
if (( f = currentMesh.dir.Length()) < 10e-3f )
|
||||
{
|
||||
DefaultLogger::get()->error("NFF: Cone height is close to zero");
|
||||
continue;
|
||||
}
|
||||
currentMesh.dir /= f; // normalize
|
||||
|
||||
// generate the cone - it consists of simple triangles
|
||||
StandardShapes::MakeCone(center1, radius1, center2, radius2, iTesselation, currentMesh.vertices);
|
||||
StandardShapes::MakeCone(f, radius1, radius2,
|
||||
integer_pow(4, iTesselation), currentMesh.vertices);
|
||||
|
||||
// MakeCone() returns tris
|
||||
currentMesh.faces.resize(currentMesh.vertices.size()/3,3);
|
||||
|
||||
// generate a name for the mesh
|
||||
// generate a name for the mesh. 'cone' if it a cone,
|
||||
// 'cylinder' if it is a cylinder. Funny, isn't it?
|
||||
if (radius1 != radius2)
|
||||
::sprintf(currentMesh.name,"cone_%i",cone++);
|
||||
else ::sprintf(currentMesh.name,"cylinder_%i",cylinder++);
|
||||
|
@ -1125,13 +1143,16 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
node->mName.Set(src.name);
|
||||
|
||||
// setup the transformation matrix of the node
|
||||
node->mTransformation.a4 = src.center.x;
|
||||
node->mTransformation.b4 = src.center.y;
|
||||
node->mTransformation.c4 = src.center.z;
|
||||
aiMatrix4x4::FromToMatrix(aiVector3D(0.f,1.f,0.f),
|
||||
src.dir,node->mTransformation);
|
||||
|
||||
node->mTransformation.a1 = src.radius.x;
|
||||
node->mTransformation.b2 = src.radius.y;
|
||||
node->mTransformation.c3 = src.radius.z;
|
||||
aiMatrix4x4& mat = node->mTransformation;
|
||||
mat.a1 *= src.radius.x; mat.b1 *= src.radius.x; mat.c1 *= src.radius.x;
|
||||
mat.a2 *= src.radius.y; mat.b2 *= src.radius.y; mat.c2 *= src.radius.y;
|
||||
mat.a3 *= src.radius.z; mat.b3 *= src.radius.z; mat.c3 *= src.radius.z;
|
||||
mat.a4 = src.center.x;
|
||||
mat.b4 = src.center.y;
|
||||
mat.c4 = src.center.z;
|
||||
|
||||
++ppcChildren;
|
||||
}
|
||||
|
@ -1194,7 +1215,8 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
s.Set(AI_DEFAULT_MATERIAL_NAME);
|
||||
pcMat->AddProperty(&s, AI_MATKEY_NAME);
|
||||
|
||||
aiColor3D c = src.shader.color * src.shader.diffuse;
|
||||
// FIX: Ignore diffuse == 0
|
||||
aiColor3D c = src.shader.color * (src.shader.diffuse.r ? src.shader.diffuse : aiColor3D(1.f,1.f,1.f));
|
||||
pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_DIFFUSE);
|
||||
c = src.shader.color * src.shader.specular;
|
||||
pcMat->AddProperty(&c,1,AI_MATKEY_COLOR_SPECULAR);
|
||||
|
@ -1209,6 +1231,9 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
{
|
||||
s.Set(src.shader.texFile);
|
||||
pcMat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
|
||||
if (aiTextureMapping_UV != src.shader.mapping)
|
||||
pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0));
|
||||
}
|
||||
|
||||
// setup the name of the material
|
||||
|
@ -1218,11 +1243,6 @@ void NFFImporter::InternReadFile( const std::string& pFile,
|
|||
pcMat->AddProperty(&s,AI_MATKEY_NAME);
|
||||
}
|
||||
|
||||
if (aiTextureMapping_UV != src.shader.mapping)
|
||||
{
|
||||
pcMat->AddProperty((int*)&src.shader.mapping, 1,AI_MATKEY_MAPPING_DIFFUSE(0));
|
||||
}
|
||||
|
||||
// setup some more material properties that are specific to NFF2
|
||||
int i;
|
||||
if (src.shader.twoSided)
|
||||
|
|
|
@ -174,6 +174,7 @@ private:
|
|||
, bLocked (bL)
|
||||
, matIndex (0)
|
||||
, radius (1.f,1.f,1.f)
|
||||
, dir (0.f,1.f,0.f)
|
||||
{
|
||||
name[0] = '\0'; // by default meshes are unnamed
|
||||
}
|
||||
|
@ -183,7 +184,7 @@ private:
|
|||
bool bLocked;
|
||||
|
||||
// for spheres, cones and cylinders: center point of the object
|
||||
aiVector3D center, radius;
|
||||
aiVector3D center, radius, dir;
|
||||
|
||||
char name[128];
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
// internal headers
|
||||
#include "SMDLoader.h"
|
||||
#include "fast_atof.h"
|
||||
|
||||
#include "SkeletonMeshBuilder.h"
|
||||
|
||||
using namespace Assimp;
|
||||
|
||||
|
@ -93,6 +93,7 @@ bool SMDImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Setup configuration properties
|
||||
void SMDImporter::SetupProperties(const Importer* pImp)
|
||||
|
@ -105,6 +106,7 @@ void SMDImporter::SetupProperties(const Importer* pImp)
|
|||
configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Imports the given file into the given scene structure.
|
||||
void SMDImporter::InternReadFile(
|
||||
|
@ -120,7 +122,7 @@ void SMDImporter::InternReadFile(
|
|||
|
||||
iFileSize = (unsigned int)file->FileSize();
|
||||
|
||||
// allocate storage and copy the contents of the file to a memory buffer
|
||||
// Allocate storage and copy the contents of the file to a memory buffer
|
||||
this->pScene = pScene;
|
||||
|
||||
std::vector<char> buff(iFileSize+1);
|
||||
|
@ -132,20 +134,20 @@ void SMDImporter::InternReadFile(
|
|||
bHasUVs = true;
|
||||
iLineNumber = 1;
|
||||
|
||||
// reserve enough space for ... hm ... 10 textures
|
||||
// Reserve enough space for ... hm ... 10 textures
|
||||
aszTextures.reserve(10);
|
||||
|
||||
// reserve enough space for ... hm ... 1000 triangles
|
||||
// Reserve enough space for ... hm ... 1000 triangles
|
||||
asTriangles.reserve(1000);
|
||||
|
||||
// reserve enough space for ... hm ... 20 bones
|
||||
// Reserve enough space for ... hm ... 20 bones
|
||||
asBones.reserve(20);
|
||||
|
||||
|
||||
// parse the file ...
|
||||
ParseFile();
|
||||
|
||||
// if there are no triangles it seems to be an animation SMD,
|
||||
// If there are no triangles it seems to be an animation SMD,
|
||||
// containing only the animation skeleton.
|
||||
if (asTriangles.empty())
|
||||
{
|
||||
|
@ -154,14 +156,15 @@ void SMDImporter::InternReadFile(
|
|||
throw new ImportErrorException("SMD: No triangles and no bones have "
|
||||
"been found in the file. This file seems to be invalid.");
|
||||
}
|
||||
// set the flag in the scene structure which indicates
|
||||
|
||||
// Set the flag in the scene structure which indicates
|
||||
// that there is nothing than an animation skeleton
|
||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||
}
|
||||
|
||||
if (!asBones.empty())
|
||||
{
|
||||
// check whether all bones have been initialized
|
||||
// Check whether all bones have been initialized
|
||||
for (std::vector<SMD::Bone>::const_iterator
|
||||
i = asBones.begin();
|
||||
i != asBones.end();++i)
|
||||
|
@ -177,8 +180,9 @@ void SMDImporter::InternReadFile(
|
|||
FixTimeValues();
|
||||
|
||||
// compute absolute bone transformation matrices
|
||||
ComputeAbsoluteBoneTransformations();
|
||||
// ComputeAbsoluteBoneTransformations();
|
||||
}
|
||||
|
||||
if (!(pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE))
|
||||
{
|
||||
// create output meshes
|
||||
|
@ -193,36 +197,30 @@ void SMDImporter::InternReadFile(
|
|||
|
||||
// build output nodes (bones are added as empty dummy nodes)
|
||||
CreateOutputNodes();
|
||||
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE)
|
||||
{
|
||||
SkeletonMeshBuilder skeleton(pScene);
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Write an error message with line number to the log file
|
||||
void SMDImporter::LogErrorNoThrow(const char* msg)
|
||||
{
|
||||
char szTemp[1024];
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szTemp,"Line %i: %s",iLineNumber,msg);
|
||||
#else
|
||||
ai_assert(strlen(msg) < 1000);
|
||||
sprintf(szTemp,"Line %i: %s",iLineNumber,msg);
|
||||
#endif
|
||||
|
||||
DefaultLogger::get()->error(szTemp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Write a warning with line number to the log file
|
||||
void SMDImporter::LogWarning(const char* msg)
|
||||
{
|
||||
char szTemp[1024];
|
||||
|
||||
#if _MSC_VER >= 1400
|
||||
sprintf_s(szTemp,"Line %i: %s",iLineNumber,msg);
|
||||
#else
|
||||
ai_assert(strlen(msg) < 1000);
|
||||
sprintf(szTemp,"Line %i: %s",iLineNumber,msg);
|
||||
#endif
|
||||
DefaultLogger::get()->warn(szTemp);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Fix invalid time values in the file
|
||||
void SMDImporter::FixTimeValues()
|
||||
|
@ -243,10 +241,14 @@ void SMDImporter::FixTimeValues()
|
|||
}
|
||||
dLengthOfAnim = dMax;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output meshes
|
||||
void SMDImporter::CreateOutputMeshes()
|
||||
{
|
||||
if (aszTextures.empty())
|
||||
aszTextures.push_back(std::string());
|
||||
|
||||
// we need to sort all faces by their material index
|
||||
// in opposition to other loaders we can be sure that each
|
||||
// material is at least used once.
|
||||
|
@ -260,9 +262,8 @@ void SMDImporter::CreateOutputMeshes()
|
|||
unsigned int iNum = (unsigned int)asTriangles.size() / pScene->mNumMeshes;
|
||||
iNum += iNum >> 1;
|
||||
for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
|
||||
{
|
||||
aaiFaces[i].reserve(iNum);
|
||||
}
|
||||
|
||||
|
||||
// collect all faces
|
||||
iNum = 0;
|
||||
|
@ -402,10 +403,9 @@ void SMDImporter::CreateOutputMeshes()
|
|||
// now build all bones of the mesh
|
||||
iNum = 0;
|
||||
for (unsigned int iBone = 0; iBone < asBones.size();++iBone)
|
||||
{
|
||||
if (!aaiBones[iBone].empty())++iNum;
|
||||
}
|
||||
if (iNum)
|
||||
|
||||
if (false && iNum)
|
||||
{
|
||||
pcMesh->mNumBones = iNum;
|
||||
pcMesh->mBones = new aiBone*[pcMesh->mNumBones];
|
||||
|
@ -430,11 +430,11 @@ void SMDImporter::CreateOutputMeshes()
|
|||
++iNum;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] aaiBones;
|
||||
}
|
||||
delete[] aaiFaces;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// add bone child nodes
|
||||
void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
|
||||
|
@ -469,6 +469,7 @@ void SMDImporter::AddBoneChildren(aiNode* pcNode, uint32_t iParent)
|
|||
AddBoneChildren(pc,i);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output nodes
|
||||
void SMDImporter::CreateOutputNodes()
|
||||
|
@ -484,7 +485,7 @@ void SMDImporter::CreateOutputNodes()
|
|||
}
|
||||
|
||||
// now add all bones as dummy sub nodes to the graph
|
||||
AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
|
||||
// AddBoneChildren(pScene->mRootNode,(uint32_t)-1);
|
||||
|
||||
// if we have only one bone we can even remove the root node
|
||||
if (pScene->mFlags & AI_SCENE_FLAGS_INCOMPLETE &&
|
||||
|
@ -503,6 +504,7 @@ void SMDImporter::CreateOutputNodes()
|
|||
pScene->mRootNode->mName.length = 10;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output animations
|
||||
void SMDImporter::CreateOutputAnimations()
|
||||
|
@ -569,10 +571,11 @@ void SMDImporter::CreateOutputAnimations()
|
|||
// there are no scaling keys ...
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SMDImporter::ComputeAbsoluteBoneTransformations()
|
||||
{
|
||||
// for each bone: determine the key with the lowest time value
|
||||
// For each bone: determine the key with the lowest time value
|
||||
// theoretically the SMD format should have all keyframes
|
||||
// in order. However, I've seen a file where this wasn't true.
|
||||
for (unsigned int i = 0; i < asBones.size();++i)
|
||||
|
@ -609,27 +612,27 @@ void SMDImporter::ComputeAbsoluteBoneTransformations()
|
|||
const aiMatrix4x4& mat = bone.sAnim.asKeys[iIndex].matrix;
|
||||
aiMatrix4x4& matOut = bone.sAnim.asKeys[iIndex].matrixAbsolute;
|
||||
|
||||
// the same for the parent bone ...
|
||||
// The same for the parent bone ...
|
||||
iIndex = parentBone.sAnim.iFirstTimeKey;
|
||||
const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrix;
|
||||
const aiMatrix4x4& mat2 = parentBone.sAnim.asKeys[iIndex].matrixAbsolute;
|
||||
|
||||
// compute the absolute transformation matrix
|
||||
// Compute the absolute transformation matrix
|
||||
matOut = mat * mat2;
|
||||
}
|
||||
}
|
||||
++iParent;
|
||||
}
|
||||
|
||||
// store the inverse of the absolute transformation matrix
|
||||
// Store the inverse of the absolute transformation matrix
|
||||
// of the first key as bone offset matrix
|
||||
for (iParent = 0; iParent < asBones.size();++iParent)
|
||||
{
|
||||
SMD::Bone& bone = asBones[iParent];
|
||||
aiMatrix4x4& mat = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute;
|
||||
bone.mOffsetMatrix = mat;
|
||||
bone.mOffsetMatrix = bone.sAnim.asKeys[bone.sAnim.iFirstTimeKey].matrixAbsolute;
|
||||
bone.mOffsetMatrix.Inverse();
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// create output materials
|
||||
void SMDImporter::CreateOutputMaterials()
|
||||
|
@ -646,9 +649,12 @@ void SMDImporter::CreateOutputMaterials()
|
|||
szName.length = (size_t)::sprintf(szName.data,"Texture_%i",iMat);
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_NAME);
|
||||
|
||||
::strcpy(szName.data, aszTextures[iMat].c_str() );
|
||||
szName.length = aszTextures[iMat].length();
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
if (aszTextures[iMat].length())
|
||||
{
|
||||
::strcpy(szName.data, aszTextures[iMat].c_str() );
|
||||
szName.length = aszTextures[iMat].length();
|
||||
pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
|
||||
}
|
||||
}
|
||||
|
||||
// create a default material if necessary
|
||||
|
@ -675,6 +681,7 @@ void SMDImporter::CreateOutputMaterials()
|
|||
pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse the file
|
||||
void SMDImporter::ParseFile()
|
||||
|
@ -687,10 +694,8 @@ void SMDImporter::ParseFile()
|
|||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "version <n> \n", <n> should be 1 for hl and hl² SMD files
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"version",7) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+7)))
|
||||
if (TokenMatch(szCurrent,"version",7))
|
||||
{
|
||||
szCurrent += 8;
|
||||
if(!SkipSpaces(szCurrent,&szCurrent)) break;
|
||||
if (1 != strtol10(szCurrent,&szCurrent))
|
||||
{
|
||||
|
@ -700,35 +705,27 @@ void SMDImporter::ParseFile()
|
|||
continue;
|
||||
}
|
||||
// "nodes\n" - Starts the node section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"nodes",5) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+5)))
|
||||
if (TokenMatch(szCurrent,"nodes",5))
|
||||
{
|
||||
szCurrent += 6;
|
||||
ParseNodesSection(szCurrent,&szCurrent);
|
||||
continue;
|
||||
}
|
||||
// "triangles\n" - Starts the triangle section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"triangles",9) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+9)))
|
||||
if (TokenMatch(szCurrent,"triangles",9))
|
||||
{
|
||||
szCurrent += 10;
|
||||
ParseTrianglesSection(szCurrent,&szCurrent);
|
||||
continue;
|
||||
}
|
||||
// "vertexanimation\n" - Starts the vertex animation section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"vertexanimation",15) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+15)))
|
||||
if (TokenMatch(szCurrent,"vertexanimation",15))
|
||||
{
|
||||
bHasUVs = false;
|
||||
szCurrent += 16;
|
||||
ParseVASection(szCurrent,&szCurrent);
|
||||
continue;
|
||||
}
|
||||
// "skeleton\n" - Starts the skeleton section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"skeleton",8) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+8)))
|
||||
if (TokenMatch(szCurrent,"skeleton",8))
|
||||
{
|
||||
szCurrent += 9;
|
||||
ParseSkeletonSection(szCurrent,&szCurrent);
|
||||
continue;
|
||||
}
|
||||
|
@ -736,6 +733,7 @@ void SMDImporter::ParseFile()
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
unsigned int SMDImporter::GetTextureIndex(const std::string& filename)
|
||||
{
|
||||
|
@ -744,13 +742,14 @@ unsigned int SMDImporter::GetTextureIndex(const std::string& filename)
|
|||
i = aszTextures.begin();
|
||||
i != aszTextures.end();++i,++iIndex)
|
||||
{
|
||||
// case-insensitive ... just for safety
|
||||
// case-insensitive ... it's a path
|
||||
if (0 == ASSIMP_stricmp ( filename.c_str(),(*i).c_str()))return iIndex;
|
||||
}
|
||||
iIndex = (unsigned int)aszTextures.size();
|
||||
aszTextures.push_back(filename);
|
||||
return iIndex;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse the nodes section of the file
|
||||
void SMDImporter::ParseNodesSection(const char* szCurrent,
|
||||
|
@ -770,24 +769,21 @@ void SMDImporter::ParseNodesSection(const char* szCurrent,
|
|||
SkipSpacesAndLineEnd(szCurrent,&szCurrent);
|
||||
*szCurrentOut = szCurrent;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse the triangles section of the file
|
||||
void SMDImporter::ParseTrianglesSection(const char* szCurrent,
|
||||
const char** szCurrentOut)
|
||||
{
|
||||
// parse a triangle, parse another triangle, parse the next triangle ...
|
||||
// Parse a triangle, parse another triangle, parse the next triangle ...
|
||||
// and so on until we reach a token that looks quite similar to "end"
|
||||
while (true)
|
||||
{
|
||||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the triangles section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
{
|
||||
szCurrent += 4;
|
||||
if (TokenMatch(szCurrent,"end",3))
|
||||
break;
|
||||
}
|
||||
ParseTriangle(szCurrent,&szCurrent);
|
||||
}
|
||||
SkipSpacesAndLineEnd(szCurrent,&szCurrent);
|
||||
|
@ -804,39 +800,33 @@ void SMDImporter::ParseVASection(const char* szCurrent,
|
|||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the "vertexanimation" section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
{
|
||||
szCurrent += 4;
|
||||
//SkipLine(szCurrent,&szCurrent);
|
||||
if (TokenMatch(szCurrent,"end",3))
|
||||
break;
|
||||
}
|
||||
|
||||
// "time <n>\n"
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"time",4) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+4)))
|
||||
if (TokenMatch(szCurrent,"time",4))
|
||||
{
|
||||
szCurrent += 5;
|
||||
// NOTE: The doc says that time values COULD be negative ...
|
||||
// note2: this is the shape key -> valve docs
|
||||
// NOTE2: this is the shape key -> valve docs
|
||||
int iTime = 0;
|
||||
if(!ParseSignedInt(szCurrent,&szCurrent,iTime) || configFrameID != (unsigned int)iTime)break;
|
||||
SkipLine(szCurrent,&szCurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true);
|
||||
if(3 == ++iCurIndex)
|
||||
if(0 == iCurIndex)
|
||||
{
|
||||
asTriangles.push_back(SMD::Face());
|
||||
iCurIndex = 0;
|
||||
}
|
||||
if (++iCurIndex == 3)iCurIndex = 0;
|
||||
ParseVertex(szCurrent,&szCurrent,asTriangles.back().avVertices[iCurIndex],true);
|
||||
}
|
||||
}
|
||||
|
||||
if (iCurIndex)
|
||||
if (iCurIndex != 2 && !asTriangles.empty())
|
||||
{
|
||||
// no degenerates, so let this triangle
|
||||
aszTextures.pop_back();
|
||||
// we want to no degenerates, so throw this triangle away
|
||||
asTriangles.pop_back();
|
||||
}
|
||||
|
||||
SkipSpacesAndLineEnd(szCurrent,&szCurrent);
|
||||
|
@ -853,18 +843,12 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent,
|
|||
if(!SkipSpacesAndLineEnd(szCurrent,&szCurrent)) break;
|
||||
|
||||
// "end\n" - Ends the skeleton section
|
||||
if (0 == ASSIMP_strincmp(szCurrent,"end",3) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+3)))
|
||||
{
|
||||
szCurrent += 4;
|
||||
//SkipLine(szCurrent,&szCurrent);
|
||||
if (TokenMatch(szCurrent,"end",3))
|
||||
break;
|
||||
}
|
||||
|
||||
// "time <n>\n" - Specifies the current animation frame
|
||||
else if (0 == ASSIMP_strincmp(szCurrent,"time",4) &&
|
||||
IsSpaceOrNewLine(*(szCurrent+4)))
|
||||
else if (TokenMatch(szCurrent,"time",4))
|
||||
{
|
||||
szCurrent += 5;
|
||||
// NOTE: The doc says that time values COULD be negative ...
|
||||
if(!ParseSignedInt(szCurrent,&szCurrent,iTime))break;
|
||||
|
||||
|
@ -876,12 +860,12 @@ void SMDImporter::ParseSkeletonSection(const char* szCurrent,
|
|||
*szCurrentOut = szCurrent;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#define SMDI_PARSE_RETURN { \
|
||||
SkipLine(szCurrent,&szCurrent); \
|
||||
*szCurrentOut = szCurrent; \
|
||||
return; \
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a node line
|
||||
void SMDImporter::ParseNodeInfo(const char* szCurrent,
|
||||
|
@ -941,6 +925,7 @@ void SMDImporter::ParseNodeInfo(const char* szCurrent,
|
|||
// go to the beginning of the next line
|
||||
SMDI_PARSE_RETURN;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a skeleton element
|
||||
void SMDImporter::ParseSkeletonElement(const char* szCurrent,
|
||||
|
@ -997,7 +982,7 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent,
|
|||
SMDI_PARSE_RETURN;
|
||||
}
|
||||
// build the transformation matrix of the key
|
||||
key.matrix.FromEulerAngles(vRot.x,vRot.y,vRot.z);
|
||||
key.matrix.FromEulerAnglesXYZ(vRot.x,vRot.y,vRot.z);
|
||||
{
|
||||
aiMatrix4x4 mTemp;
|
||||
mTemp.a4 = vPos.x;
|
||||
|
@ -1009,6 +994,7 @@ void SMDImporter::ParseSkeletonElement(const char* szCurrent,
|
|||
// go to the beginning of the next line
|
||||
SMDI_PARSE_RETURN;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a triangle
|
||||
void SMDImporter::ParseTriangle(const char* szCurrent,
|
||||
|
@ -1027,10 +1013,10 @@ void SMDImporter::ParseTriangle(const char* szCurrent,
|
|||
const char* szLast = szCurrent;
|
||||
while (!IsSpaceOrNewLine(*szCurrent++));
|
||||
|
||||
face.iTexture = GetTextureIndex(std::string(szLast,
|
||||
(uintptr_t)szCurrent-(uintptr_t)szLast));
|
||||
// ... and get the index that belongs to this file name
|
||||
face.iTexture = GetTextureIndex(std::string(szLast,(uintptr_t)szCurrent-(uintptr_t)szLast));
|
||||
|
||||
SkipLine(szCurrent,&szCurrent);
|
||||
SkipSpacesAndLineEnd(szCurrent,&szCurrent);
|
||||
|
||||
// load three vertices
|
||||
for (unsigned int iVert = 0; iVert < 3;++iVert)
|
||||
|
@ -1040,6 +1026,7 @@ void SMDImporter::ParseTriangle(const char* szCurrent,
|
|||
}
|
||||
*szCurrentOut = szCurrent;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a float
|
||||
bool SMDImporter::ParseFloat(const char* szCurrent,
|
||||
|
@ -1051,6 +1038,7 @@ bool SMDImporter::ParseFloat(const char* szCurrent,
|
|||
*szCurrentOut = fast_atof_move(szCurrent,out);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse an unsigned int
|
||||
bool SMDImporter::ParseUnsignedInt(const char* szCurrent,
|
||||
|
@ -1062,6 +1050,7 @@ bool SMDImporter::ParseUnsignedInt(const char* szCurrent,
|
|||
out = strtol10(szCurrent,szCurrentOut);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a signed int
|
||||
bool SMDImporter::ParseSignedInt(const char* szCurrent,
|
||||
|
@ -1073,6 +1062,7 @@ bool SMDImporter::ParseSignedInt(const char* szCurrent,
|
|||
out = strtol10s(szCurrent,szCurrentOut);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Parse a vertex
|
||||
void SMDImporter::ParseVertex(const char* szCurrent,
|
||||
|
@ -1143,8 +1133,10 @@ void SMDImporter::ParseVertex(const char* szCurrent,
|
|||
i = vertex.aiBoneLinks.begin();
|
||||
i != vertex.aiBoneLinks.end();++i)
|
||||
{
|
||||
if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first))SMDI_PARSE_RETURN;
|
||||
if(!ParseFloat(szCurrent,&szCurrent,(*i).second))SMDI_PARSE_RETURN;
|
||||
if(!ParseUnsignedInt(szCurrent,&szCurrent,(*i).first))
|
||||
SMDI_PARSE_RETURN;
|
||||
if(!ParseFloat(szCurrent,&szCurrent,(*i).second))
|
||||
SMDI_PARSE_RETURN;
|
||||
}
|
||||
|
||||
// go to the beginning of the next line
|
||||
|
|
|
@ -114,6 +114,7 @@ aiMesh* StandardShapes::MakeMesh(const std::vector<aiVector3D>& positions,
|
|||
{
|
||||
if (positions.size() & numIndices || positions.empty() || !numIndices)return NULL;
|
||||
|
||||
// Determine which kinds of primitives the mesh will consist of
|
||||
aiMesh* out = new aiMesh();
|
||||
switch (numIndices)
|
||||
{
|
||||
|
@ -182,18 +183,18 @@ unsigned int StandardShapes::MakeIcosahedron(std::vector<aiVector3D>& positions)
|
|||
const float t = (1.f + 2.236067977f)/2.f;
|
||||
const float s = sqrt(1.f + t*t);
|
||||
|
||||
aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
|
||||
aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
|
||||
aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s;
|
||||
aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s;
|
||||
aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s;
|
||||
aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s;
|
||||
aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s;
|
||||
aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s;
|
||||
aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s;
|
||||
aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s;
|
||||
aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s;
|
||||
aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/s;
|
||||
const aiVector3D v0 = aiVector3D(t,1.f, 0.f)/s;
|
||||
const aiVector3D v1 = aiVector3D(-t,1.f, 0.f)/s;
|
||||
const aiVector3D v2 = aiVector3D(t,-1.f, 0.f)/s;
|
||||
const aiVector3D v3 = aiVector3D(-t,-1.f, 0.f)/s;
|
||||
const aiVector3D v4 = aiVector3D(1.f, 0.f, t)/s;
|
||||
const aiVector3D v5 = aiVector3D(1.f, 0.f,-t)/s;
|
||||
const aiVector3D v6 = aiVector3D(-1.f, 0.f,t)/s;
|
||||
const aiVector3D v7 = aiVector3D(-1.f, 0.f,-t)/s;
|
||||
const aiVector3D v8 = aiVector3D(0.f, t, 1.f)/s;
|
||||
const aiVector3D v9 = aiVector3D(0.f,-t, 1.f)/s;
|
||||
const aiVector3D v10 = aiVector3D(0.f, t,-1.f)/s;
|
||||
const aiVector3D v11 = aiVector3D(0.f,-t,-1.f)/s;
|
||||
|
||||
ADD_TRIANGLE(v0,v8,v4);
|
||||
ADD_TRIANGLE(v0,v5,v10);
|
||||
|
@ -232,26 +233,26 @@ unsigned int StandardShapes::MakeDodecahedron(std::vector<aiVector3D>& positions
|
|||
const float b = sqrt((3.f-2.23606797f)/6.f);
|
||||
const float c = sqrt((3.f+2.23606797f)/6.f);
|
||||
|
||||
aiVector3D v0 = aiVector3D(a,a,a);
|
||||
aiVector3D v1 = aiVector3D(a,a,-a);
|
||||
aiVector3D v2 = aiVector3D(a,-a,a);
|
||||
aiVector3D v3 = aiVector3D(a,-a,-a);
|
||||
aiVector3D v4 = aiVector3D(-a,a,a);
|
||||
aiVector3D v5 = aiVector3D(-a,a,-a);
|
||||
aiVector3D v6 = aiVector3D(-a,-a,a);
|
||||
aiVector3D v7 = aiVector3D(-a,-a,-a);
|
||||
aiVector3D v8 = aiVector3D(b,c,0.f);
|
||||
aiVector3D v9 = aiVector3D(-b,c,0.f);
|
||||
aiVector3D v10 = aiVector3D(b,-c,0.f);
|
||||
aiVector3D v11 = aiVector3D(-b,-c,0.f);
|
||||
aiVector3D v12 = aiVector3D(c, 0.f, b);
|
||||
aiVector3D v13 = aiVector3D(c, 0.f, -b);
|
||||
aiVector3D v14 = aiVector3D(-c, 0.f, b);
|
||||
aiVector3D v15 = aiVector3D(-c, 0.f, -b);
|
||||
aiVector3D v16 = aiVector3D(0.f, b, c);
|
||||
aiVector3D v17 = aiVector3D(0.f, -b, c);
|
||||
aiVector3D v18 = aiVector3D(0.f, b, -c);
|
||||
aiVector3D v19 = aiVector3D(0.f, -b, -c);
|
||||
const aiVector3D v0 = aiVector3D(a,a,a);
|
||||
const aiVector3D v1 = aiVector3D(a,a,-a);
|
||||
const aiVector3D v2 = aiVector3D(a,-a,a);
|
||||
const aiVector3D v3 = aiVector3D(a,-a,-a);
|
||||
const aiVector3D v4 = aiVector3D(-a,a,a);
|
||||
const aiVector3D v5 = aiVector3D(-a,a,-a);
|
||||
const aiVector3D v6 = aiVector3D(-a,-a,a);
|
||||
const aiVector3D v7 = aiVector3D(-a,-a,-a);
|
||||
const aiVector3D v8 = aiVector3D(b,c,0.f);
|
||||
const aiVector3D v9 = aiVector3D(-b,c,0.f);
|
||||
const aiVector3D v10 = aiVector3D(b,-c,0.f);
|
||||
const aiVector3D v11 = aiVector3D(-b,-c,0.f);
|
||||
const aiVector3D v12 = aiVector3D(c, 0.f, b);
|
||||
const aiVector3D v13 = aiVector3D(c, 0.f, -b);
|
||||
const aiVector3D v14 = aiVector3D(-c, 0.f, b);
|
||||
const aiVector3D v15 = aiVector3D(-c, 0.f, -b);
|
||||
const aiVector3D v16 = aiVector3D(0.f, b, c);
|
||||
const aiVector3D v17 = aiVector3D(0.f, -b, c);
|
||||
const aiVector3D v18 = aiVector3D(0.f, b, -c);
|
||||
const aiVector3D v19 = aiVector3D(0.f, -b, -c);
|
||||
|
||||
ADD_PENTAGON(v0, v8, v9, v4, v16);
|
||||
ADD_PENTAGON(v0, v12, v13, v1, v8);
|
||||
|
@ -274,12 +275,12 @@ unsigned int StandardShapes::MakeOctahedron(std::vector<aiVector3D>& positions)
|
|||
{
|
||||
positions.reserve(positions.size()+24);
|
||||
|
||||
aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ;
|
||||
aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
|
||||
aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
|
||||
aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
|
||||
aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
|
||||
aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
|
||||
const aiVector3D v0 = aiVector3D(1.0f, 0.f, 0.f) ;
|
||||
const aiVector3D v1 = aiVector3D(-1.0f, 0.f, 0.f);
|
||||
const aiVector3D v2 = aiVector3D(0.f, 1.0f, 0.f);
|
||||
const aiVector3D v3 = aiVector3D(0.f, -1.0f, 0.f);
|
||||
const aiVector3D v4 = aiVector3D(0.f, 0.f, 1.0f);
|
||||
const aiVector3D v5 = aiVector3D(0.f, 0.f, -1.0f);
|
||||
|
||||
ADD_TRIANGLE(v4,v0,v2);
|
||||
ADD_TRIANGLE(v4,v2,v1);
|
||||
|
@ -301,10 +302,10 @@ unsigned int StandardShapes::MakeTetrahedron(std::vector<aiVector3D>& positions)
|
|||
const float a = 1.41421f/3.f;
|
||||
const float b = 2.4494f/3.f;
|
||||
|
||||
aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
|
||||
aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
|
||||
aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
|
||||
aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
|
||||
const aiVector3D v0 = aiVector3D(0.f,0.f,1.f);
|
||||
const aiVector3D v1 = aiVector3D(2*a,0,-1.f/3.f);
|
||||
const aiVector3D v2 = aiVector3D(-a,b,-1.f/3.f);
|
||||
const aiVector3D v3 = aiVector3D(-a,-b,-1.f/3.f);
|
||||
|
||||
ADD_TRIANGLE(v0,v1,v2);
|
||||
ADD_TRIANGLE(v0,v2,v3);
|
||||
|
@ -318,16 +319,16 @@ unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
|
|||
bool polygons /*= false*/)
|
||||
{
|
||||
positions.reserve(positions.size()+36);
|
||||
float length = 1.f/1.73205080f;
|
||||
const float length = 1.f/1.73205080f;
|
||||
|
||||
aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
|
||||
aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
|
||||
aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
|
||||
aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
|
||||
aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
|
||||
aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
|
||||
aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
|
||||
aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length;
|
||||
const aiVector3D v0 = aiVector3D(-1.f,-1.f,-1.f)*length;
|
||||
const aiVector3D v1 = aiVector3D(1.f,-1.f,-1.f)*length;
|
||||
const aiVector3D v2 = aiVector3D(1.f,1.f,-1.f)*length;
|
||||
const aiVector3D v3 = aiVector3D(-1.f,1.f,-1.f)*length;
|
||||
const aiVector3D v4 = aiVector3D(-1.f,-1.f,1.f)*length;
|
||||
const aiVector3D v5 = aiVector3D(1.f,-1.f,1.f)*length;
|
||||
const aiVector3D v6 = aiVector3D(1.f,1.f,1.f)*length;
|
||||
const aiVector3D v7 = aiVector3D(-1.f,1.f,1.f)*length;
|
||||
|
||||
ADD_QUAD(v0,v3,v2,v1);
|
||||
ADD_QUAD(v0,v1,v5,v4);
|
||||
|
@ -347,22 +348,95 @@ unsigned int StandardShapes::MakeHexahedron(std::vector<aiVector3D>& positions,
|
|||
void StandardShapes::MakeSphere(unsigned int tess,
|
||||
std::vector<aiVector3D>& positions)
|
||||
{
|
||||
// Reserve enough storage. Every subdivision
|
||||
// splits each triangle in 4, the icosahedron consists of 60 verts
|
||||
positions.reserve(positions.size()+60 * integer_pow(4, tess));
|
||||
|
||||
// Construct an icosahedron to start with
|
||||
MakeIcosahedron(positions);
|
||||
|
||||
// ... and subdivide it until the requested output
|
||||
// tesselation is reached
|
||||
for (unsigned int i = 0; i<tess;++i)
|
||||
Subdivide(positions);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void StandardShapes::MakeCone(
|
||||
aiVector3D& center1,
|
||||
float radius1,
|
||||
aiVector3D& center2,
|
||||
float radius2,
|
||||
unsigned int tess,
|
||||
std::vector<aiVector3D>& positions,
|
||||
bool bOpened /*= false*/)
|
||||
void StandardShapes::MakeCone(float height,float radius1,
|
||||
float radius2,unsigned int tess,
|
||||
std::vector<aiVector3D>& positions,bool bOpen /*= false */)
|
||||
{
|
||||
// Sorry, a cone with less than 3 segments makes
|
||||
// ABSOLUTELY NO SENSE
|
||||
if (tess < 3 || !height)
|
||||
return;
|
||||
|
||||
// No negative radii
|
||||
radius1 = fabs(radius1);
|
||||
radius2 = fabs(radius2);
|
||||
|
||||
float halfHeight = height / 2;
|
||||
|
||||
// radius1 is always the smaller one
|
||||
if (radius2 > radius1)
|
||||
{
|
||||
std::swap(radius2,radius1);
|
||||
halfHeight = -halfHeight;
|
||||
}
|
||||
|
||||
// Use a large epsilon to check whether the cone is pointy
|
||||
if (radius1 < (radius2-radius1)*10e-3f)radius1 = 0.f;
|
||||
|
||||
// We will need 3*2 verts per segment + 3*2 verts per segment
|
||||
// if the cone is closed
|
||||
const unsigned int mem = tess*6 + (!bOpen ? tess*3 * (radius1 ? 2 : 1) : 0);
|
||||
positions.reserve(mem);
|
||||
|
||||
// Now construct all segments
|
||||
const float angle_delta = (float)AI_MATH_TWO_PI / tess;
|
||||
const float angle_max = (float)AI_MATH_TWO_PI;
|
||||
|
||||
float s = 1.f; // cos(angle == 0);
|
||||
float t = 0.f; // sin(angle == 0);
|
||||
|
||||
for (float angle = 0.f; angle < angle_max; )
|
||||
{
|
||||
const aiVector3D v1 = aiVector3D (s * radius1, -halfHeight, t * radius1 );
|
||||
const aiVector3D v2 = aiVector3D (s * radius2, halfHeight, t * radius2 );
|
||||
|
||||
const float next = angle + angle_delta;
|
||||
float s2 = cos(next);
|
||||
float t2 = sin(next);
|
||||
|
||||
const aiVector3D v3 = aiVector3D (s2 * radius2, halfHeight, t2 * radius2 );
|
||||
const aiVector3D v4 = aiVector3D (s2 * radius1, -halfHeight, t2 * radius1 );
|
||||
|
||||
positions.push_back(v1);
|
||||
positions.push_back(v3);
|
||||
positions.push_back(v2);
|
||||
positions.push_back(v4);
|
||||
positions.push_back(v3);
|
||||
positions.push_back(v1);
|
||||
|
||||
if (!bOpen)
|
||||
{
|
||||
// generate the end 'cap'
|
||||
positions.push_back(aiVector3D(s * radius2, halfHeight, t * radius2 ));
|
||||
positions.push_back(aiVector3D(0.f, halfHeight, 0.f));
|
||||
positions.push_back(aiVector3D(s2 * radius2, halfHeight, t2 * radius2 ));
|
||||
|
||||
if (radius1)
|
||||
{
|
||||
// generate the other end 'cap'
|
||||
positions.push_back(aiVector3D(s * radius1, -halfHeight, t * radius1 ));
|
||||
positions.push_back(aiVector3D(0.f, -halfHeight, 0.f));
|
||||
positions.push_back(aiVector3D(s2 * radius1, -halfHeight, t2 * radius1 ));
|
||||
}
|
||||
}
|
||||
s = s2;
|
||||
t = t2;
|
||||
angle = next;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -373,7 +447,7 @@ void StandardShapes::MakeCircle(
|
|||
unsigned int tess,
|
||||
std::vector<aiVector3D>& positions)
|
||||
{
|
||||
//aiVector3D current = aiVector3D ( normal.x,
|
||||
// todo
|
||||
}
|
||||
|
||||
} // ! Assimp
|
||||
|
|
|
@ -153,28 +153,28 @@ public:
|
|||
*
|
||||
* |-----| <- radius 1
|
||||
*
|
||||
* __x__ <- center 1
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* / \
|
||||
* /______x______\ <- center 2
|
||||
* __x__ <- ]
|
||||
* / \ | height
|
||||
* / \ |
|
||||
* / \ |
|
||||
* / \ |
|
||||
* /______x______\ <- ] <- end cap
|
||||
*
|
||||
* |-------------| <- radius 2
|
||||
*
|
||||
* @endcode
|
||||
*
|
||||
* @param center1 First center point
|
||||
* @param height Height of the cone
|
||||
* @param radius1 First radius
|
||||
* @param center2 Second center point
|
||||
* @param radius2 Second radius
|
||||
* @param tess Number of subdivisions
|
||||
* @param bOpened true for an open cone/cylinder.
|
||||
* @param positions Receives output triangles.
|
||||
* @param tess Number of triangles.
|
||||
* @param bOpened true for an open cone/cylinder. An open shape has
|
||||
* no 'end caps'
|
||||
* @param positions Receives output triangles
|
||||
*/
|
||||
static void MakeCone(aiVector3D& center1,float radius1,
|
||||
aiVector3D& center2,float radius2,unsigned int tess,
|
||||
std::vector<aiVector3D>& positions,bool bOpened = false);
|
||||
static void MakeCone(float height,float radius1,
|
||||
float radius2,unsigned int tess,
|
||||
std::vector<aiVector3D>& positions,bool bOpen= false);
|
||||
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
@ -185,7 +185,7 @@ public:
|
|||
* @param normal Normal vector of the circle.
|
||||
* This is also the normal vector of all triangles generated by
|
||||
* this function.
|
||||
* @param tess Number of triangles
|
||||
* @param tess Number of segments.
|
||||
* @param positions Receives output triangles.
|
||||
*/
|
||||
static void MakeCircle(const aiVector3D& center, const aiVector3D& normal,
|
||||
|
|
|
@ -54,7 +54,6 @@ namespace Assimp
|
|||
// @param max Maximum number of characters to be written, including '\0'
|
||||
// @param number Number to be written
|
||||
// @return Number of bytes written. Including '\0'.
|
||||
// ---------------------------------------------------------------------------
|
||||
inline unsigned int itoa10( char* out, unsigned int max, int32_t number)
|
||||
{
|
||||
ai_assert(NULL != out);
|
||||
|
@ -96,7 +95,6 @@ inline unsigned int itoa10( char* out, unsigned int max, int32_t number)
|
|||
// Secure template overload
|
||||
// The compiler should choose this function if he is able to determine the
|
||||
// size of the array automatically.
|
||||
// ---------------------------------------------------------------------------
|
||||
template <unsigned int length>
|
||||
inline unsigned int itoa10( char(& out)[length], int32_t number)
|
||||
{
|
||||
|
@ -113,13 +111,16 @@ inline unsigned int itoa10( char(& out)[length], int32_t number)
|
|||
* \param s1 First input string
|
||||
* \param s2 Second input string
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
||||
{
|
||||
#if (defined _MSC_VER)
|
||||
|
||||
return ::_stricmp(s1,s2);
|
||||
|
||||
#elif defined( __GNUC__ )
|
||||
|
||||
return ::strcasecmp(s1,s2);
|
||||
|
||||
#else
|
||||
register char c1, c2;
|
||||
do
|
||||
|
@ -136,7 +137,6 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2)
|
|||
// ---------------------------------------------------------------------------
|
||||
/** \brief Case independent comparison of two std::strings
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
||||
{
|
||||
register int i = (int)b.length()-(int)a.length();
|
||||
|
@ -154,13 +154,16 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b)
|
|||
* \param s2 Second input string
|
||||
* \param n Macimum number of characters to compare
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
|
||||
{
|
||||
#if (defined _MSC_VER)
|
||||
|
||||
return ::_strnicmp(s1,s2,n);
|
||||
|
||||
#elif defined( __GNUC__ )
|
||||
|
||||
return ::strncasecmp(s1,s2, n);
|
||||
|
||||
#else
|
||||
register char c1, c2;
|
||||
unsigned int p = 0;
|
||||
|
@ -175,6 +178,18 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n)
|
|||
return c1 - c2;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Evaluates an integer power.
|
||||
inline unsigned int integer_pow (unsigned int base, unsigned int power)
|
||||
{
|
||||
unsigned int res = 1;
|
||||
for (unsigned int i = 0; i < power;++i)
|
||||
res *= base;
|
||||
|
||||
return res;
|
||||
}
|
||||
} // end of namespace
|
||||
|
||||
#endif // ! AI_STRINGCOMPARISON_H_INC
|
||||
|
|
|
@ -511,7 +511,7 @@ void ValidateDSProcess::Validate( const aiMesh* pMesh)
|
|||
// check whether all bone weights for a vertex sum to 1.0 ...
|
||||
for (unsigned int i = 0; i < pMesh->mNumVertices;++i)
|
||||
{
|
||||
if (afSum[i] && (afSum[i] <= 0.995 || afSum[i] >= 1.005))
|
||||
if (afSum[i] && (afSum[i] <= 0.94 || afSum[i] >= 1.05))
|
||||
{
|
||||
ReportWarning("aiMesh::mVertices[%i]: bone weight sum != 1.0 (sum is %f)",i,afSum[i]);
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
/** Compares two paths and check whether the point to identical files.
|
||||
*
|
||||
* The dummy implementation of this virtual performs a
|
||||
* case-insensitive comparison of the path strings.
|
||||
* case-insensitive comparison of the absolute path strings.
|
||||
* @param one First file
|
||||
* @param second Second file
|
||||
* @return true if the paths point to the same file. The file needn't
|
||||
|
|
|
@ -118,8 +118,8 @@ struct aiMatrix4x4
|
|||
* \param y Rotation angle for the y-axis, in radians
|
||||
* \param z Rotation angle for the z-axis, in radians
|
||||
*/
|
||||
inline void FromEulerAngles(float x, float y, float z);
|
||||
inline void FromEulerAngles(const aiVector3D& blubb);
|
||||
inline void FromEulerAnglesXYZ(float x, float y, float z);
|
||||
inline void FromEulerAnglesXYZ(const aiVector3D& blubb);
|
||||
|
||||
|
||||
/** \brief Returns a rotation matrix for a rotation around the x axis
|
||||
|
@ -158,6 +158,18 @@ struct aiMatrix4x4
|
|||
*/
|
||||
static aiMatrix4x4& Translation( const aiVector3D& v, aiMatrix4x4& out);
|
||||
|
||||
|
||||
/** A function for creating a rotation matrix that rotates a vector called
|
||||
* "from" into another vector called "to".
|
||||
* Input : from[3], to[3] which both must be *normalized* non-zero vectors
|
||||
* Output: mtx[3][3] -- a 3x3 matrix in colum-major form
|
||||
* Authors: Tomas Möller, John Hughes
|
||||
* "Efficiently Building a Matrix to Rotate One Vector to Another"
|
||||
* Journal of Graphics Tools, 4(4):1-4, 1999
|
||||
*/
|
||||
static aiMatrix4x4& FromToMatrix(const aiVector3D& from,
|
||||
const aiVector3D& to, aiMatrix4x4& out);
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
float a1, a2, a3, a4;
|
||||
|
|
|
@ -87,12 +87,16 @@ inline aiMatrix4x4& aiMatrix4x4::Inverse()
|
|||
float det = Determinant();
|
||||
if(det == 0.0f)
|
||||
{
|
||||
// Matrix not invertible. Setting all elements to nan is not really
|
||||
// correct in a mathematical sense but it is easy to debug for the
|
||||
// programmer.
|
||||
const float nan = std::numeric_limits<float>::quiet_NaN();
|
||||
*this = aiMatrix4x4(
|
||||
nan,nan,nan,nan,
|
||||
nan,nan,nan,nan,
|
||||
nan,nan,nan,nan,
|
||||
nan,nan,nan,nan);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -204,43 +208,62 @@ inline void aiMatrix4x4::DecomposeNoScaling (aiQuaternion& rotation,
|
|||
rotation = aiQuaternion((aiMatrix3x3)_this);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
inline void aiMatrix4x4::FromEulerAngles(const aiVector3D& blubb)
|
||||
inline void aiMatrix4x4::FromEulerAnglesXYZ(const aiVector3D& blubb)
|
||||
{
|
||||
FromEulerAngles(blubb.x,blubb.y,blubb.z);
|
||||
FromEulerAnglesXYZ(blubb.x,blubb.y,blubb.z);
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
inline void aiMatrix4x4::FromEulerAngles(float x, float y, float z)
|
||||
inline void aiMatrix4x4::FromEulerAnglesXYZ(float x, float y, float z)
|
||||
{
|
||||
aiMatrix4x4& _this = *this;
|
||||
|
||||
const float A = ::cos(x);
|
||||
const float B = ::sin(x);
|
||||
const float C = ::cos(y);
|
||||
const float D = ::sin(y);
|
||||
const float E = ::cos(z);
|
||||
const float F = ::sin(z);
|
||||
const float AD = A * D;
|
||||
const float BD = B * D;
|
||||
_this.a1 = C * E;
|
||||
_this.a2 = -C * F;
|
||||
_this.a3 = D;
|
||||
_this.b1 = BD * E + A * F;
|
||||
_this.b2 = -BD * F + A * E;
|
||||
_this.b3 = -B * C;
|
||||
_this.c1 = -AD * E + B * F;
|
||||
_this.c2 = AD * F + B * E;
|
||||
_this.c3 = A * C;
|
||||
_this.a4 = _this.b4 = _this.c4 = _this.d1 = _this.d2 = _this.d3 = 0.0f;
|
||||
_this.d4 = 1.0f;
|
||||
float cr = cos( x );
|
||||
float sr = sin( x );
|
||||
float cp = cos( y );
|
||||
float sp = sin( y );
|
||||
float cy = cos( z );
|
||||
float sy = sin( z );
|
||||
|
||||
_this.a1 = cp*cy ;
|
||||
_this.a2 = cp*sy;
|
||||
_this.a3 = -sp ;
|
||||
|
||||
float srsp = sr*sp;
|
||||
float crsp = cr*sp;
|
||||
|
||||
_this.b1 = srsp*cy-cr*sy ;
|
||||
_this.b2 = srsp*sy+cr*cy ;
|
||||
_this.b3 = sr*cp ;
|
||||
|
||||
_this.c1 = crsp*cy+sr*sy ;
|
||||
_this.c2 = crsp*sy-sr*cy ;
|
||||
_this.c3 = cr*cp ;
|
||||
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
inline bool aiMatrix4x4::IsIdentity() const
|
||||
{
|
||||
return !(a1 != 1.0f || a2 || a3 || a4 ||
|
||||
b1 || b2 != 1.0f || b3 || b4 ||
|
||||
c1 || c2 || c3 != 1.0f || a4 ||
|
||||
d1 || d2 || d3 || d4 != 1.0f);
|
||||
// Use a small epsilon to solve floating-point inaccuracies
|
||||
const static float epsilon = 10e-3f;
|
||||
|
||||
return (a2 <= epsilon && a2 >= -epsilon &&
|
||||
a3 <= epsilon && a3 >= -epsilon &&
|
||||
a4 <= epsilon && a4 >= -epsilon &&
|
||||
b1 <= epsilon && b1 >= -epsilon &&
|
||||
b3 <= epsilon && b3 >= -epsilon &&
|
||||
b4 <= epsilon && b4 >= -epsilon &&
|
||||
c1 <= epsilon && c1 >= -epsilon &&
|
||||
c2 <= epsilon && c2 >= -epsilon &&
|
||||
c3 <= epsilon && c3 >= -epsilon &&
|
||||
d1 <= epsilon && d1 >= -epsilon &&
|
||||
d2 <= epsilon && d2 >= -epsilon &&
|
||||
d3 <= epsilon && d3 >= -epsilon &&
|
||||
a1 <= 1.f+epsilon && a1 >= 1.f-epsilon &&
|
||||
b2 <= 1.f+epsilon && b2 >= 1.f-epsilon &&
|
||||
c3 <= 1.f+epsilon && c3 >= 1.f-epsilon &&
|
||||
d4 <= 1.f+epsilon && d4 >= 1.f-epsilon);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiMatrix4x4& aiMatrix4x4::RotationX(float a, aiMatrix4x4& out)
|
||||
{
|
||||
|
@ -312,5 +335,95 @@ inline aiMatrix4x4& aiMatrix4x4::Translation( const aiVector3D& v, aiMatrix4x4&
|
|||
return out;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
/** A function for creating a rotation matrix that rotates a vector called
|
||||
* "from" into another vector called "to".
|
||||
* Input : from[3], to[3] which both must be *normalized* non-zero vectors
|
||||
* Output: mtx[3][3] -- a 3x3 matrix in colum-major form
|
||||
* Authors: Tomas Möller, John Hughes
|
||||
* "Efficiently Building a Matrix to Rotate One Vector to Another"
|
||||
* Journal of Graphics Tools, 4(4):1-4, 1999
|
||||
*/
|
||||
// ---------------------------------------------------------------------------
|
||||
inline aiMatrix4x4& aiMatrix4x4::FromToMatrix(const aiVector3D& from,
|
||||
const aiVector3D& to, aiMatrix4x4& mtx)
|
||||
{
|
||||
const aiVector3D v = from ^ to;
|
||||
const float e = from * to;
|
||||
const float f = (e < 0)? -e:e;
|
||||
|
||||
if (f > 1.0 - 0.00001f) /* "from" and "to"-vector almost parallel */
|
||||
{
|
||||
aiVector3D u,v; /* temporary storage vectors */
|
||||
aiVector3D x; /* vector most nearly orthogonal to "from" */
|
||||
|
||||
x.x = (from.x > 0.0)? from.x : -from.x;
|
||||
x.y = (from.y > 0.0)? from.y : -from.y;
|
||||
x.z = (from.z > 0.0)? from.z : -from.z;
|
||||
|
||||
if (x.x < x.y)
|
||||
{
|
||||
if (x.x < x.z)
|
||||
{
|
||||
x.x = 1.0; x.y = x.z = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x.z = 1.0; x.y = x.z = 0.0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x.y < x.z)
|
||||
{
|
||||
x.y = 1.0; x.x = x.z = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x.z = 1.0; x.x = x.y = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
u.x = x.x - from.x; u.y = x.y - from.y; u.z = x.z - from.z;
|
||||
v.x = x.x - to.x; v.y = x.y - to.y; v.z = x.z - to.z;
|
||||
|
||||
const float c1 = 2.0f / (u * u);
|
||||
const float c2 = 2.0f / (v * v);
|
||||
const float c3 = c1 * c2 * (u * v);
|
||||
|
||||
for (unsigned int i = 0; i < 3; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < 3; j++)
|
||||
{
|
||||
mtx[i][j] = - c1 * u[i] * u[j] - c2 * v[i] * v[j]
|
||||
+ c3 * v[i] * u[j];
|
||||
}
|
||||
mtx[i][i] += 1.0;
|
||||
}
|
||||
}
|
||||
else /* the most common case, unless "from"="to", or "from"=-"to" */
|
||||
{
|
||||
/* ... use this hand optimized version (9 mults less) */
|
||||
const float h = 1.0f/(1.0f + e); /* optimization by Gottfried Chen */
|
||||
const float hvx = h * v.x;
|
||||
const float hvz = h * v.z;
|
||||
const float hvxy = hvx * v.y;
|
||||
const float hvxz = hvx * v.z;
|
||||
const float hvyz = hvz * v.y;
|
||||
mtx[0][0] = e + hvx * v.x;
|
||||
mtx[0][1] = hvxy - v.z;
|
||||
mtx[0][2] = hvxz + v.y;
|
||||
|
||||
mtx[1][0] = hvxy + v.z;
|
||||
mtx[1][1] = e + h * v.y * v.y;
|
||||
mtx[1][2] = hvyz - v.x;
|
||||
|
||||
mtx[2][0] = hvxz - v.y;
|
||||
mtx[2][1] = hvyz + v.x;
|
||||
mtx[2][2] = e + hvz * v.z;
|
||||
}
|
||||
return mtx;
|
||||
}
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // AI_MATRIX4x4_INL_INC
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,25 @@
|
|||
b 0.078 0.361 0.753
|
||||
v
|
||||
from 2.1 1.3 1.7
|
||||
at 0 0 0
|
||||
up 0 0 1
|
||||
angle 45
|
||||
hither 0.01
|
||||
resolution 512 512
|
||||
l 4 3 2
|
||||
l 1 -4 4
|
||||
l -3 1 5
|
||||
|
||||
f 1 0.9 0.7 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthSpherical.jpg
|
||||
s 0 0 0 0.5
|
||||
|
||||
f 1 0.9 0.7 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthSpherical.jpg
|
||||
s 0.272166 0.272166 0.544331 0.16665
|
||||
s 0.643951 0.172546 1.11022e-16 0.16665
|
||||
s 0.172546 0.643951 1.11022e-16 0.16665
|
||||
s -0.371785 0.0996195 0.544331 0.16665
|
||||
s -0.471405 0.471405 1.11022e-16 0.16665
|
||||
s -0.643951 -0.172546 1.11022e-16 0.16665
|
||||
s 0.0996195 -0.371785 0.544331 0.16665
|
||||
s -0.172546 -0.643951 1.11022e-16 0.16665
|
||||
s 0.471405 -0.471405 1.11022e-16 0.16665
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#red
|
||||
f 1.0 0.0 0.0 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthCylindric.jpg
|
||||
|
||||
|
||||
tess 4
|
||||
|
||||
|
||||
# a simple cone - should go directly through the center
|
||||
c
|
||||
10 10 10 3
|
||||
-10 -10 -10 6
|
||||
|
||||
|
||||
f 1.0 1.0 1.0 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthSpherical.jpg
|
||||
s -10 -10 -10 2
|
||||
s 10 10 10 3
|
||||
|
||||
|
||||
#white
|
||||
f 1.0 1.0 1.0 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthCylindric.jpg
|
||||
|
||||
# another cone, closed this time
|
||||
c
|
||||
20 20 20 6
|
||||
11 11 11 0
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
#red
|
||||
f 1 0.9 0.7 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthCylindric.jpg
|
||||
|
||||
tess 4
|
||||
|
||||
# a simple cylinder - should go directly through the center
|
||||
c
|
||||
10 10 10 6
|
||||
-10 -10 -10 6
|
|
@ -1,27 +1,36 @@
|
|||
|
||||
# Enable high-quality subdivision
|
||||
tess 4
|
||||
|
||||
|
||||
# This represents a C4H10 molecule (Butan)
|
||||
|
||||
|
||||
f 0.3 0.3 0.3 1 1
|
||||
|
||||
# a centered sphere
|
||||
|
||||
|
||||
s 0 0 0 5
|
||||
|
||||
s 20 0 0 5
|
||||
|
||||
s 40 0 0 5
|
||||
|
||||
s 60 0 0 5
|
||||
|
||||
|
||||
|
||||
# Switch to white
|
||||
f 1 1 1 1 1
|
||||
|
||||
s -5 0 0 3
|
||||
|
||||
s 0 5 0 3
|
||||
s 0 -5 0 3
|
||||
s 20 5 0 3
|
||||
s 20 -5 0 3
|
||||
s 40 5 0 3
|
||||
s 40 -5 0 3
|
||||
s 60 5 0 3
|
||||
s 60 -5 0 3
|
||||
s 65 0 0 3
|
||||
|
||||
|
||||
# Now a tube to connect them
|
||||
c
|
||||
0 0 0 0.8
|
||||
60 0 0 0.8
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
s 5.0 5.0 5.0 3.0
|
||||
|
||||
#blue
|
||||
f 0.0 0.0 1.0 0 1 1
|
||||
f 0.0 0.0 1.0 0 1 1 1
|
||||
|
||||
# Another simple sphere
|
||||
s 5.0 4.0 8.0 3.0
|
||||
|
||||
#green
|
||||
f 0.0 1.0 0.0 0 1 1
|
||||
f 1.0 1.0 1.0 0.5 0.5 45.2776 0 1 ./../../LWOFiles/LWo2/MappingModes/EarthCylindric.jpg
|
||||
|
||||
# And another one
|
||||
s 1.0 -4.0 2.0 4.0 2 2
|
||||
|
@ -19,10 +19,6 @@ s 1.0 -4.0 2.0 4.0 2 2
|
|||
#red
|
||||
f 1.0 0.0 0.0 0 1 1
|
||||
|
||||
# a simple cone
|
||||
c 10 10 5 3
|
||||
c 14 14 3 6
|
||||
|
||||
|
||||
# An icosahedron
|
||||
tess 0
|
||||
|
|
Loading…
Reference in New Issue