Small fix to the ASE loader - workaround for bitmaps with filename "None".
Further work on the IRR loader. Still work in progress. Fixed a minor issue in StandardShapes. Fixed a bug in the Q3D loader causing models without textures to load incorrectly. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@225 67173fc5-114c-0410-ac8e-9d2fd5bffc1fpull/1/head
parent
df85f0aead
commit
240dbfd864
|
@ -587,7 +587,10 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
if(!ParseString(temp,"*MAP_CLASS"))
|
if(!ParseString(temp,"*MAP_CLASS"))
|
||||||
SkipToNextToken();
|
SkipToNextToken();
|
||||||
if (temp != "Bitmap")
|
if (temp != "Bitmap")
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
|
||||||
parsePath = false;
|
parsePath = false;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// path to the texture
|
// path to the texture
|
||||||
|
@ -595,6 +598,15 @@ void Parser::ParseLV3MapBlock(Texture& map)
|
||||||
{
|
{
|
||||||
if(!ParseString(map.mMapName,"*BITMAP"))
|
if(!ParseString(map.mMapName,"*BITMAP"))
|
||||||
SkipToNextToken();
|
SkipToNextToken();
|
||||||
|
|
||||||
|
if (map.mMapName == "None")
|
||||||
|
{
|
||||||
|
// Files with 'None' as map name are produced by
|
||||||
|
// an Maja to ASE exporter which name I forgot ..
|
||||||
|
DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
|
||||||
|
map.mMapName = "";
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// offset on the u axis
|
// offset on the u axis
|
||||||
|
|
|
@ -208,7 +208,7 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name,
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline bool AllIdentical(T* in, unsigned int num)
|
inline bool AllIdentical(T* in, unsigned int num)
|
||||||
{
|
{
|
||||||
if (!num)return true;
|
if (num <= 1)return true;
|
||||||
for (unsigned int i = 0; i < num-1;++i)
|
for (unsigned int i = 0; i < num-1;++i)
|
||||||
{
|
{
|
||||||
if (in[i] != in[i+1])return false;
|
if (in[i] != in[i+1])return false;
|
||||||
|
|
|
@ -102,6 +102,129 @@ bool IRRImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler) const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
||||||
|
BatchLoader& batch,
|
||||||
|
std::vector<aiMesh*>& meshes,
|
||||||
|
std::vector<aiNodeAnim*>& anims,
|
||||||
|
std::vector<AttachmentInfo>& attach)
|
||||||
|
{
|
||||||
|
// Setup the name of this node
|
||||||
|
rootOut->mName.Set(root->name);
|
||||||
|
|
||||||
|
unsigned int oldMeshSize = (unsigned int)meshes.size();
|
||||||
|
|
||||||
|
// Now determine the type of the node
|
||||||
|
switch (root->type)
|
||||||
|
{
|
||||||
|
case Node::ANIMMESH:
|
||||||
|
case Node::MESH:
|
||||||
|
{
|
||||||
|
// get the loaded mesh from the scene and add it to
|
||||||
|
// the list of all scenes to be attached to the
|
||||||
|
// graph we're currently building
|
||||||
|
aiScene* scene = batch.GetImport(root->meshPath);
|
||||||
|
if (!scene)
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
attach.push_back(AttachmentInfo(scene,rootOut));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Node::LIGHT:
|
||||||
|
case Node::CAMERA:
|
||||||
|
|
||||||
|
// We're already finished with lights and cameras
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case Node::SPHERE:
|
||||||
|
{
|
||||||
|
// generate the sphere model. Our input parameter to
|
||||||
|
// the sphere generation algorithm is the number of
|
||||||
|
// subdivisions of each triangle - but here we have
|
||||||
|
// the number of poylgons on a specific axis. Just
|
||||||
|
// use some limits ...
|
||||||
|
unsigned int mul = root->spherePolyCountX*root->spherePolyCountY;
|
||||||
|
if (mul < 100)mul = 2;
|
||||||
|
else if (mul < 300)mul = 3;
|
||||||
|
else mul = 4;
|
||||||
|
|
||||||
|
meshes.push_back(StandardShapes::MakeMesh(mul,&StandardShapes::MakeSphere));
|
||||||
|
|
||||||
|
// Adjust scaling
|
||||||
|
root->scaling *= root->sphereRadius;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Node::CUBE:
|
||||||
|
case Node::SKYBOX:
|
||||||
|
{
|
||||||
|
// Skyboxes and normal cubes - generate the cube first
|
||||||
|
meshes.push_back(StandardShapes::MakeMesh(&StandardShapes::MakeHexahedron));
|
||||||
|
|
||||||
|
// Adjust scaling
|
||||||
|
root->scaling *= root->sphereRadius;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Node::TERRAIN:
|
||||||
|
{
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check whether we added a mesh. In this case we'll also
|
||||||
|
// need to attach it to the node
|
||||||
|
if (oldMeshSize != (unsigned int) meshes.size())
|
||||||
|
{
|
||||||
|
rootOut->mNumMeshes = 1;
|
||||||
|
rootOut->mMeshes = new unsigned int[1];
|
||||||
|
rootOut->mMeshes[0] = oldMeshSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
aiMatrix4x4 m;
|
||||||
|
rootOut->mTransformation = aiMatrix4x4::RotationX(AI_DEG_TO_RAD(root->rotation.x),m)
|
||||||
|
* aiMatrix4x4::RotationY(AI_DEG_TO_RAD(root->rotation.y),m)
|
||||||
|
* aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(root->rotation.z),m);
|
||||||
|
|
||||||
|
// apply scaling
|
||||||
|
aiMatrix4x4& mat = rootOut->mTransformation;
|
||||||
|
mat.a1 *= root->scaling.x;
|
||||||
|
mat.b1 *= root->scaling.x;
|
||||||
|
mat.c1 *= root->scaling.x;
|
||||||
|
mat.a2 *= root->scaling.y;
|
||||||
|
mat.b2 *= root->scaling.y;
|
||||||
|
mat.c2 *= root->scaling.y;
|
||||||
|
mat.a3 *= root->scaling.z;
|
||||||
|
mat.b3 *= root->scaling.z;
|
||||||
|
mat.c3 *= root->scaling.z;
|
||||||
|
|
||||||
|
// apply translation
|
||||||
|
mat.a4 = root->position.x;
|
||||||
|
mat.b4 = root->position.y;
|
||||||
|
mat.c4 = root->position.z;
|
||||||
|
|
||||||
|
// Add all children recursively. First allocate enough storage
|
||||||
|
// for them, then call us again
|
||||||
|
rootOut->mNumChildren = (unsigned int)root->children.size();
|
||||||
|
if (rootOut->mNumChildren)
|
||||||
|
{
|
||||||
|
rootOut->mChildren = new aiNode*[rootOut->mNumChildren];
|
||||||
|
for (unsigned int i = 0; i < rootOut->mNumChildren;++i)
|
||||||
|
{
|
||||||
|
aiNode* node = rootOut->mChildren[i] = new aiNode();
|
||||||
|
node->mParent = rootOut;
|
||||||
|
GenerateGraph(root->children[i],node,scene,batch,meshes,anims,attach);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// Imports the given file into the given scene structure.
|
// Imports the given file into the given scene structure.
|
||||||
void IRRImporter::InternReadFile( const std::string& pFile,
|
void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
|
@ -133,7 +256,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
// List of output lights
|
// List of output lights
|
||||||
std::vector<aiLight*> lights;
|
std::vector<aiLight*> lights;
|
||||||
|
|
||||||
|
// Batch loader used to load external models
|
||||||
BatchLoader batch(pIOHandler);
|
BatchLoader batch(pIOHandler);
|
||||||
|
|
||||||
cameras.reserve(5);
|
cameras.reserve(5);
|
||||||
|
@ -391,6 +514,10 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
{
|
{
|
||||||
curAnim->circleRadius = prop.value;
|
curAnim->circleRadius = prop.value;
|
||||||
}
|
}
|
||||||
|
else if (curAnim->type == Animator::FOLLOW_SPLINE && prop.name == "Tightness")
|
||||||
|
{
|
||||||
|
curAnim->tightness = prop.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -439,13 +566,12 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
|
lights.back()->mAngleInnerCone = AI_DEG_TO_RAD( prop.value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// radius of the sphere to be generated
|
// radius of the sphere to be generated -
|
||||||
else if (Node::SPHERE == curNode->type)
|
// or alternatively, size of the cube
|
||||||
|
else if (Node::SPHERE == curNode->type && prop.name == "Radius" ||
|
||||||
|
Node::CUBE == curNode->type && prop.name == "Size" )
|
||||||
{
|
{
|
||||||
if (prop.name == "Radius")
|
curNode->sphereRadius = prop.value;
|
||||||
{
|
|
||||||
curNode->sphereRadius = prop.value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,6 +650,34 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
batch.AddLoadRequest(prop.value,pp,&map);
|
batch.AddLoadRequest(prop.value,pp,&map);
|
||||||
|
curNode->meshPath = prop.value;
|
||||||
|
}
|
||||||
|
else if (inAnimator && prop.name == "Type")
|
||||||
|
{
|
||||||
|
// type of the animator
|
||||||
|
if (prop.value == "rotation")
|
||||||
|
{
|
||||||
|
curAnim->type = Animator::ROTATION;
|
||||||
|
}
|
||||||
|
else if (prop.value == "flyCircle")
|
||||||
|
{
|
||||||
|
curAnim->type = Animator::FLY_CIRCLE;
|
||||||
|
}
|
||||||
|
else if (prop.value == "flyStraight")
|
||||||
|
{
|
||||||
|
curAnim->type = Animator::FLY_CIRCLE;
|
||||||
|
}
|
||||||
|
else if (prop.value == "followSpline")
|
||||||
|
{
|
||||||
|
curAnim->type = Animator::FOLLOW_SPLINE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
|
||||||
|
+ prop.value);
|
||||||
|
|
||||||
|
curAnim->type = Animator::UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -603,7 +757,6 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
tempScene->mLights = new aiLight*[tempScene->mNumLights];
|
tempScene->mLights = new aiLight*[tempScene->mNumLights];
|
||||||
::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
|
::memcpy(tempScene->mLights,&lights[0],sizeof(void*)*tempScene->mNumLights);
|
||||||
|
|
||||||
|
|
||||||
// temporary data
|
// temporary data
|
||||||
std::vector< aiNodeAnim*> anims;
|
std::vector< aiNodeAnim*> anims;
|
||||||
std::vector< AttachmentInfo > attach;
|
std::vector< AttachmentInfo > attach;
|
||||||
|
@ -615,8 +768,8 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
/* Now process our scenegraph recursively: generate final
|
/* Now process our scenegraph recursively: generate final
|
||||||
* meshes and generate animation channels for all nodes.
|
* meshes and generate animation channels for all nodes.
|
||||||
*/
|
*/
|
||||||
// GenerateGraph(root,tempScene->mRootNode, tempScene,
|
GenerateGraph(root,tempScene->mRootNode, tempScene,
|
||||||
// batch, meshes, anims, attach);
|
batch, meshes, anims, attach);
|
||||||
|
|
||||||
if (!anims.empty())
|
if (!anims.empty())
|
||||||
{
|
{
|
||||||
|
@ -644,9 +797,21 @@ void IRRImporter::InternReadFile( const std::string& pFile,
|
||||||
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
|
||||||
DefaultLogger::get()->info("IRR: No Meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE flag");
|
DefaultLogger::get()->info("IRR: No Meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE flag");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// copy all meshes to the temporary scene
|
||||||
|
tempScene->mNumMeshes = (unsigned int)meshes.size();
|
||||||
|
tempScene->mMeshes = new aiMesh*[tempScene->mNumMeshes];
|
||||||
|
::memcpy(tempScene->mMeshes,&meshes[0],tempScene->mNumMeshes);
|
||||||
|
}
|
||||||
|
|
||||||
/* Now merge all sub scenes and attach them to the correct
|
/* Now merge all sub scenes and attach them to the correct
|
||||||
* attachment points in the scenegraph.
|
* attachment points in the scenegraph.
|
||||||
*/
|
*/
|
||||||
SceneCombiner::MergeScenes(pScene,tempScene,attach);
|
SceneCombiner::MergeScenes(pScene,tempScene,attach);
|
||||||
|
|
||||||
|
|
||||||
|
/* Finished ... everything destructs automatically and all
|
||||||
|
* temporary scenes have already been deleted by MergeScenes()
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#define AI_IRRLOADER_H_INCLUDED
|
#define AI_IRRLOADER_H_INCLUDED
|
||||||
|
|
||||||
#include "IRRMeshLoader.h"
|
#include "IRRMeshLoader.h"
|
||||||
|
#include "SceneCombiner.h"
|
||||||
|
|
||||||
namespace Assimp {
|
namespace Assimp {
|
||||||
|
|
||||||
|
@ -208,6 +209,9 @@ private:
|
||||||
// 0.f if not specified
|
// 0.f if not specified
|
||||||
float framesPerSecond;
|
float framesPerSecond;
|
||||||
|
|
||||||
|
// Meshes: path to the mesh to be loaded
|
||||||
|
std::string meshPath;
|
||||||
|
|
||||||
// Meshes: List of materials to be assigned
|
// Meshes: List of materials to be assigned
|
||||||
// along with their corresponding material flags
|
// along with their corresponding material flags
|
||||||
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
|
std::vector< std::pair<aiMaterial*, unsigned int> > materials;
|
||||||
|
@ -221,6 +225,16 @@ private:
|
||||||
// List of all animators assigned to the node
|
// List of all animators assigned to the node
|
||||||
std::list<Animator> animators;
|
std::list<Animator> animators;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Fill the scenegraph recursively
|
||||||
|
*/
|
||||||
|
void GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
|
||||||
|
BatchLoader& batch,
|
||||||
|
std::vector<aiMesh*>& meshes,
|
||||||
|
std::vector<aiNodeAnim*>& anims,
|
||||||
|
std::vector<AttachmentInfo>& attach);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end of namespace Assimp
|
} // end of namespace Assimp
|
||||||
|
|
|
@ -194,10 +194,10 @@ void Q3DImporter::InternReadFile( const std::string& pFile,
|
||||||
normals[i].z = stream.GetF4();
|
normals[i].z = stream.GetF4();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numTextures)
|
numVerts = (unsigned int)stream.GetI4();
|
||||||
|
if (numTextures && numVerts)
|
||||||
{
|
{
|
||||||
// read all texture coordinates
|
// read all texture coordinates
|
||||||
numVerts = (unsigned int)stream.GetI4();
|
|
||||||
std::vector<aiVector3D>& uv = mesh.uv;
|
std::vector<aiVector3D>& uv = mesh.uv;
|
||||||
uv.resize(numVerts);
|
uv.resize(numVerts);
|
||||||
|
|
||||||
|
@ -435,10 +435,14 @@ outer:
|
||||||
mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE);
|
mat->AddProperty(&srcMat.diffuse, 1,AI_MATKEY_COLOR_DIFFUSE);
|
||||||
mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
|
mat->AddProperty(&srcMat.specular, 1,AI_MATKEY_COLOR_SPECULAR);
|
||||||
mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
|
mat->AddProperty(&srcMat.ambient, 1,AI_MATKEY_COLOR_AMBIENT);
|
||||||
|
|
||||||
|
// NOTE: Ignore transparency for the moment - it seems
|
||||||
|
// unclear how to interpret the data
|
||||||
|
#if 0
|
||||||
if (!(minor > '0' && major == '3'))
|
if (!(minor > '0' && major == '3'))
|
||||||
srcMat.transparency = 1.0f - srcMat.transparency;
|
srcMat.transparency = 1.0f - srcMat.transparency;
|
||||||
mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
|
mat->AddProperty(&srcMat.transparency, 1, AI_MATKEY_OPACITY);
|
||||||
|
#endif
|
||||||
|
|
||||||
// add shininess - Quick3D seems to use it ins its viewer
|
// add shininess - Quick3D seems to use it ins its viewer
|
||||||
srcMat.transparency = 16.f;
|
srcMat.transparency = 16.f;
|
||||||
|
@ -522,7 +526,7 @@ outer:
|
||||||
else *norms = m.normals[ face.indices[n] ];
|
else *norms = m.normals[ face.indices[n] ];
|
||||||
|
|
||||||
// copy texture coordinates
|
// copy texture coordinates
|
||||||
if (uv)
|
if (uv && m.uv.size())
|
||||||
{
|
{
|
||||||
if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
|
if (m.prevUVIdx != 0xffffffff && m.uv.size() >= m.verts.size()) // workaround
|
||||||
{
|
{
|
||||||
|
|
|
@ -166,12 +166,12 @@ aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiMesh* StandardShapes::MakeMesh ( unsigned int (*GenerateFunc)(
|
aiMesh* StandardShapes::MakeMesh (unsigned int num, void (*GenerateFunc)(
|
||||||
unsigned int,std::vector<aiVector3D>&))
|
unsigned int,std::vector<aiVector3D>&))
|
||||||
{
|
{
|
||||||
std::vector<aiVector3D> temp;
|
std::vector<aiVector3D> temp;
|
||||||
unsigned num = (*GenerateFunc)(4,temp);
|
(*GenerateFunc)(num,temp);
|
||||||
return MakeMesh(temp,num);
|
return MakeMesh(temp,3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -78,7 +78,7 @@ public:
|
||||||
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
|
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
|
||||||
(std::vector<aiVector3D>&, bool));
|
(std::vector<aiVector3D>&, bool));
|
||||||
|
|
||||||
static aiMesh* MakeMesh ( unsigned int (*GenerateFunc)
|
static aiMesh* MakeMesh ( unsigned int n, void (*GenerateFunc)
|
||||||
(unsigned int,std::vector<aiVector3D>&));
|
(unsigned int,std::vector<aiVector3D>&));
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|
|
@ -211,41 +211,41 @@ inline aiQuaternion::aiQuaternion( aiVector3D normalized)
|
||||||
// Congrats, gmtl!
|
// Congrats, gmtl!
|
||||||
inline void aiQuaternion::Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor)
|
inline void aiQuaternion::Interpolate( aiQuaternion& pOut, const aiQuaternion& pStart, const aiQuaternion& pEnd, float pFactor)
|
||||||
{
|
{
|
||||||
// calc cosine theta
|
// calc cosine theta
|
||||||
float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
|
float cosom = pStart.x * pEnd.x + pStart.y * pEnd.y + pStart.z * pEnd.z + pStart.w * pEnd.w;
|
||||||
|
|
||||||
// adjust signs (if necessary)
|
// adjust signs (if necessary)
|
||||||
aiQuaternion end = pEnd;
|
aiQuaternion end = pEnd;
|
||||||
if( cosom < 0.0f)
|
if( cosom < 0.0f)
|
||||||
{
|
{
|
||||||
cosom = -cosom;
|
cosom = -cosom;
|
||||||
end.x = -end.x; // Reverse all signs
|
end.x = -end.x; // Reverse all signs
|
||||||
end.y = -end.y;
|
end.y = -end.y;
|
||||||
end.z = -end.z;
|
end.z = -end.z;
|
||||||
end.w = -end.w;
|
end.w = -end.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate coefficients
|
// Calculate coefficients
|
||||||
float sclp, sclq;
|
float sclp, sclq;
|
||||||
if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon
|
if( (1.0f - cosom) > 0.0001f) // 0.0001 -> some epsillon
|
||||||
{
|
{
|
||||||
// Standard case (slerp)
|
// Standard case (slerp)
|
||||||
float omega, sinom;
|
float omega, sinom;
|
||||||
omega = acos( cosom); // extract theta from dot product's cos theta
|
omega = acos( cosom); // extract theta from dot product's cos theta
|
||||||
sinom = sin( omega);
|
sinom = sin( omega);
|
||||||
sclp = sin( (1.0f - pFactor) * omega) / sinom;
|
sclp = sin( (1.0f - pFactor) * omega) / sinom;
|
||||||
sclq = sin( pFactor * omega) / sinom;
|
sclq = sin( pFactor * omega) / sinom;
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// Very close, do linear interp (because it's faster)
|
// Very close, do linear interp (because it's faster)
|
||||||
sclp = 1.0f - pFactor;
|
sclp = 1.0f - pFactor;
|
||||||
sclq = pFactor;
|
sclq = pFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pOut.x = sclp * pStart.x + sclq * end.x;
|
pOut.x = sclp * pStart.x + sclq * end.x;
|
||||||
pOut.y = sclp * pStart.y + sclq * end.y;
|
pOut.y = sclp * pStart.y + sclq * end.y;
|
||||||
pOut.z = sclp * pStart.z + sclq * end.z;
|
pOut.z = sclp * pStart.z + sclq * end.z;
|
||||||
pOut.w = sclp * pStart.w + sclq * end.w;
|
pOut.w = sclp * pStart.w + sclq * end.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end extern "C"
|
} // end extern "C"
|
||||||
|
|
Loading…
Reference in New Issue