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-9d2fd5bffc1f
pull/1/head
aramis_acg 2008-11-28 23:02:27 +00:00
parent 5639220859
commit be864ce4a0
22 changed files with 601 additions and 305 deletions

View File

@ -120,5 +120,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#endif // !! ASSIMP_PCH_INCLUDED

View File

@ -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)
{

View File

@ -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;

View File

@ -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");
}

View File

@ -144,8 +144,8 @@ struct Frame
*/
struct TexCoord
{
uint16_t s;
uint16_t t;
int16_t s;
int16_t t;
} PACK_STRUCT;
// ---------------------------------------------------------------------------

View File

@ -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

View File

@ -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)

View File

@ -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];

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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]);
}

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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