mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-12 15:14:35 +00:00
Merge pull request #42 from OTHGMars/Assimp_WIP
Node transform and vertex weight fixes.
This commit is contained in:
commit
5a93bfd39b
6 changed files with 225 additions and 135 deletions
|
|
@ -37,6 +37,15 @@ AssimpAppMesh::AssimpAppMesh(const struct aiMesh* mesh, AssimpAppNode* node)
|
||||||
: mMeshData(mesh), appNode(node)
|
: mMeshData(mesh), appNode(node)
|
||||||
{
|
{
|
||||||
Con::printf("[ASSIMP] Mesh Created: %s", getName());
|
Con::printf("[ASSIMP] Mesh Created: %s", getName());
|
||||||
|
|
||||||
|
// See if it's a skinned mesh
|
||||||
|
mIsSkinMesh = false;
|
||||||
|
for (U32 b = 0; b < mesh->mNumBones; b++)
|
||||||
|
if (mMeshData->mBones[b]->mNumWeights > 0)
|
||||||
|
{
|
||||||
|
mIsSkinMesh = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* AssimpAppMesh::getName(bool allowFixed)
|
const char* AssimpAppMesh::getName(bool allowFixed)
|
||||||
|
|
@ -59,12 +68,11 @@ MatrixF AssimpAppMesh::getMeshTransform(F32 time)
|
||||||
return appNode->getNodeTransform(time);
|
return appNode->getNodeTransform(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objOffset)
|
||||||
{
|
{
|
||||||
// After this function, the following are expected to be populated:
|
// After this function, the following are expected to be populated:
|
||||||
// points, normals, uvs, primitives, indices
|
// points, normals, uvs, primitives, indices
|
||||||
// There is also colors and uv2s but those don't seem to be required.
|
// There is also colors and uv2s but those don't seem to be required.
|
||||||
|
|
||||||
points.reserve(mMeshData->mNumVertices);
|
points.reserve(mMeshData->mNumVertices);
|
||||||
uvs.reserve(mMeshData->mNumVertices);
|
uvs.reserve(mMeshData->mNumVertices);
|
||||||
normals.reserve(mMeshData->mNumVertices);
|
normals.reserve(mMeshData->mNumVertices);
|
||||||
|
|
@ -74,23 +82,19 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
{
|
{
|
||||||
// Points and Normals
|
// Points and Normals
|
||||||
aiVector3D pt = mMeshData->mVertices[i];
|
aiVector3D pt = mMeshData->mVertices[i];
|
||||||
aiVector3D nrm = mMeshData->mNormals[i];
|
aiVector3D nrm;
|
||||||
|
if (mMeshData->HasNormals())
|
||||||
|
nrm = mMeshData->mNormals[i];
|
||||||
|
else
|
||||||
|
nrm.Set(0, 0, 0);
|
||||||
|
|
||||||
Point3F tmpVert;
|
Point3F tmpVert;
|
||||||
Point3F tmpNormal;
|
Point3F tmpNormal;
|
||||||
|
|
||||||
if (Con::getBoolVariable("$Assimp::SwapYZ", false))
|
tmpVert = Point3F(pt.x, pt.y, pt.z);
|
||||||
{
|
tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
|
||||||
tmpVert = Point3F(pt.x, pt.z, pt.y);
|
|
||||||
tmpNormal = Point3F(nrm.x, nrm.z, nrm.y);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tmpVert = Point3F(pt.x, pt.y, pt.z);
|
|
||||||
tmpNormal = Point3F(nrm.x, nrm.y, nrm.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
//objectOffset.mulP(tmpVert);
|
objOffset.mulP(tmpVert);
|
||||||
|
|
||||||
points.push_back(tmpVert);
|
points.push_back(tmpVert);
|
||||||
|
|
||||||
|
|
@ -128,8 +132,7 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 numFaces = mMeshData->mNumFaces;
|
U32 numFaces = mMeshData->mNumFaces;
|
||||||
U32 primCount = 0;
|
//primitives.reserve(numFaces);
|
||||||
primitives.reserve(numFaces);
|
|
||||||
|
|
||||||
//Fetch the number of indices
|
//Fetch the number of indices
|
||||||
U32 indicesCount = 0;
|
U32 indicesCount = 0;
|
||||||
|
|
@ -140,41 +143,18 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
|
|
||||||
indices.reserve(indicesCount);
|
indices.reserve(indicesCount);
|
||||||
|
|
||||||
/*U32 idxCount = 0;
|
// Create TSMesh primitive
|
||||||
|
primitives.increment();
|
||||||
for (U32 j = 0; j<mModel->mMaterials.size(); j++)
|
TSDrawPrimitive& primitive = primitives.last();
|
||||||
{
|
primitive.start = 0;
|
||||||
MikuModel::Material &mat = mModel->mMaterials[j];
|
primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | (S32)mMeshData->mMaterialIndex;
|
||||||
U32 nextIdxCount = idxCount + mat.numIndices;
|
primitive.numElements = indicesCount;
|
||||||
|
|
||||||
primitives.increment();
|
|
||||||
|
|
||||||
TSDrawPrimitive& primitive = primitives.last();
|
|
||||||
primitive.start = indices.size();
|
|
||||||
primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | j;
|
|
||||||
primitive.numElements = mat.numIndices;
|
|
||||||
|
|
||||||
for (U32 i = idxCount; i<nextIdxCount; i++)
|
|
||||||
{
|
|
||||||
indices.push_back(mModel->mIndices[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
idxCount = nextIdxCount;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
for ( U32 n = 0; n < mMeshData->mNumFaces; ++n)
|
for ( U32 n = 0; n < mMeshData->mNumFaces; ++n)
|
||||||
{
|
{
|
||||||
const struct aiFace* face = &mMeshData->mFaces[n];
|
const struct aiFace* face = &mMeshData->mFaces[n];
|
||||||
if ( face->mNumIndices == 3 )
|
if ( face->mNumIndices == 3 )
|
||||||
{
|
{
|
||||||
// Create TSMesh primitive
|
|
||||||
primitives.increment();
|
|
||||||
TSDrawPrimitive& primitive = primitives.last();
|
|
||||||
primitive.start = indices.size();
|
|
||||||
primitive.matIndex = (TSDrawPrimitive::Triangles | TSDrawPrimitive::Indexed) | (S32)mMeshData->mMaterialIndex;
|
|
||||||
//primitive.numElements = face->mNumIndices;//3;
|
|
||||||
primitive.numElements = 3;
|
|
||||||
|
|
||||||
if (Con::getBoolVariable("$Assimp::FlipNormals", true))
|
if (Con::getBoolVariable("$Assimp::FlipNormals", true))
|
||||||
{
|
{
|
||||||
U32 indexCount = face->mNumIndices;
|
U32 indexCount = face->mNumIndices;
|
||||||
|
|
@ -193,11 +173,6 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
indices.push_back(index);
|
indices.push_back(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the indices in.
|
|
||||||
//indices.push_back(face->mIndices[0]);
|
|
||||||
//indices.push_back(face->mIndices[1]);
|
|
||||||
//indices.push_back(face->mIndices[2]);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -206,39 +181,67 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 boneCount = mMeshData->mNumBones;
|
U32 boneCount = mMeshData->mNumBones;
|
||||||
|
|
||||||
bones.setSize(boneCount);
|
bones.setSize(boneCount);
|
||||||
|
|
||||||
|
// Count the total number of weights for all of the bones.
|
||||||
|
U32 totalWeights = 0;
|
||||||
|
U32 nonZeroWeights = 0;
|
||||||
|
for (U32 b = 0; b < boneCount; b++)
|
||||||
|
totalWeights += mMeshData->mBones[b]->mNumWeights;
|
||||||
|
|
||||||
|
// Assimp gives weights sorted by bone index. We need them in vertex order.
|
||||||
|
Vector<F32> tmpWeight;
|
||||||
|
Vector<S32> tmpBoneIndex;
|
||||||
|
Vector<S32> tmpVertexIndex;
|
||||||
|
tmpWeight.setSize(totalWeights);
|
||||||
|
tmpBoneIndex.setSize(totalWeights);
|
||||||
|
tmpVertexIndex.setSize(totalWeights);
|
||||||
|
|
||||||
for (U32 b = 0; b < boneCount; b++)
|
for (U32 b = 0; b < boneCount; b++)
|
||||||
{
|
{
|
||||||
String name = mMeshData->mBones[b]->mName.C_Str();
|
String name = mMeshData->mBones[b]->mName.C_Str();
|
||||||
|
aiNode* nodePtr = AssimpAppNode::findChildNodeByName(mMeshData->mBones[b]->mName.C_Str(), appNode->mScene->mRootNode);
|
||||||
|
bones[b] = new AssimpAppNode(appNode->mScene, nodePtr);
|
||||||
|
|
||||||
MatrixF boneTransform;
|
MatrixF boneTransform;
|
||||||
|
AssimpAppNode::assimpToTorqueMat(mMeshData->mBones[b]->mOffsetMatrix, boneTransform);
|
||||||
for (U32 m = 0; m < 16; ++m)
|
initialTransforms.push_back(boneTransform);
|
||||||
{
|
|
||||||
boneTransform[m] = *mMeshData->mBones[b]->mOffsetMatrix[m];
|
|
||||||
}
|
|
||||||
|
|
||||||
//initialTransforms.push_back(boneTransform);
|
|
||||||
initialTransforms.push_back(MatrixF::Identity);
|
|
||||||
|
|
||||||
//Weights
|
//Weights
|
||||||
U32 numWeights = mMeshData->mBones[b]->mNumWeights;
|
U32 numWeights = mMeshData->mBones[b]->mNumWeights;
|
||||||
|
|
||||||
weight.setSize(numWeights);
|
|
||||||
vertexIndex.setSize(numWeights);
|
|
||||||
|
|
||||||
for (U32 w = 0; w < numWeights; ++w)
|
for (U32 w = 0; w < numWeights; ++w)
|
||||||
{
|
{
|
||||||
aiVertexWeight* aiWeight = mMeshData->mBones[b]->mWeights;
|
aiVertexWeight* aiWeight = &mMeshData->mBones[b]->mWeights[w];
|
||||||
|
|
||||||
weight[w] = aiWeight->mWeight;
|
if (aiWeight->mWeight > 0.0f)
|
||||||
vertexIndex[w] = aiWeight->mVertexId;
|
{
|
||||||
boneIndex[w] = b;
|
tmpWeight[nonZeroWeights] = aiWeight->mWeight;
|
||||||
//vertWeight. = aiWeight->
|
tmpVertexIndex[nonZeroWeights] = aiWeight->mVertexId;
|
||||||
|
tmpBoneIndex[nonZeroWeights] = b;
|
||||||
|
nonZeroWeights++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
weight.setSize(nonZeroWeights);
|
||||||
|
vertexIndex.setSize(nonZeroWeights);
|
||||||
|
boneIndex.setSize(nonZeroWeights);
|
||||||
|
|
||||||
|
// Copy the weights to our vectors in vertex order
|
||||||
|
U32 nextWeight = 0;
|
||||||
|
for (U32 i = 0; i < mMeshData->mNumVertices; i++)
|
||||||
|
{
|
||||||
|
for (U32 ind = 0; ind < nonZeroWeights; ind++)
|
||||||
|
{
|
||||||
|
if (tmpVertexIndex[ind] == i)
|
||||||
|
{
|
||||||
|
weight[nextWeight] = tmpWeight[ind];
|
||||||
|
vertexIndex[nextWeight] = tmpVertexIndex[ind];
|
||||||
|
boneIndex[nextWeight] = tmpBoneIndex[ind];
|
||||||
|
nextWeight++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//= mNumWeights
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( noUVFound )
|
if ( noUVFound )
|
||||||
|
|
@ -246,8 +249,8 @@ void AssimpAppMesh::lockMesh(F32 t, const MatrixF& objectOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssimpAppMesh::lookupSkinData()
|
void AssimpAppMesh::lookupSkinData()
|
||||||
{
|
{ // This function is intentionally left blank. The skin data - bones, weights and indexes are
|
||||||
|
// processed in lockMesh() with the rest of the mesh data.
|
||||||
}
|
}
|
||||||
|
|
||||||
F32 AssimpAppMesh::getVisValue(F32 t)
|
F32 AssimpAppMesh::getVisValue(F32 t)
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ class AssimpAppMesh : public AppMesh
|
||||||
protected:
|
protected:
|
||||||
class AssimpAppNode* appNode; ///< Pointer to the node that owns this mesh
|
class AssimpAppNode* appNode; ///< Pointer to the node that owns this mesh
|
||||||
const struct aiMesh* mMeshData;
|
const struct aiMesh* mMeshData;
|
||||||
|
bool mIsSkinMesh;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -100,14 +101,14 @@ public:
|
||||||
/// Return true if this mesh is a skin
|
/// Return true if this mesh is a skin
|
||||||
bool isSkin()
|
bool isSkin()
|
||||||
{
|
{
|
||||||
return false;
|
return mIsSkinMesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate the vertex, normal and triangle data for the mesh.
|
/// Generate the vertex, normal and triangle data for the mesh.
|
||||||
///
|
///
|
||||||
/// @param time Time at which to generate the mesh data
|
/// @param time Time at which to generate the mesh data
|
||||||
/// @param objectOffset Transform to apply to the generated data (bounds transform)
|
/// @param objectOffset Transform to apply to the generated data (bounds transform)
|
||||||
void lockMesh(F32 time, const MatrixF& objectOffset);
|
void lockMesh(F32 time, const MatrixF& objOffset);
|
||||||
|
|
||||||
/// Get the transform of this mesh at a certain time
|
/// Get the transform of this mesh at a certain time
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@
|
||||||
#include <assimp/types.h>
|
#include <assimp/types.h>
|
||||||
|
|
||||||
AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* node, AssimpAppNode* parent)
|
AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* node, AssimpAppNode* parent)
|
||||||
|
: mInvertMeshes(false),
|
||||||
|
mLastTransformTime(TSShapeLoader::DefaultTime - 1),
|
||||||
|
mDefaultTransformValid(false)
|
||||||
{
|
{
|
||||||
mScene = scene;
|
mScene = scene;
|
||||||
mNode = node;
|
mNode = node;
|
||||||
|
|
@ -45,7 +48,8 @@ AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* n
|
||||||
}
|
}
|
||||||
|
|
||||||
mParentName = dStrdup(parent ? parent->getName() : "ROOT");
|
mParentName = dStrdup(parent ? parent->getName() : "ROOT");
|
||||||
Con::printf("[ASSIMP] Node Created: %s", mName);
|
assimpToTorqueMat(node->mTransformation, mNodeTransform);
|
||||||
|
Con::printf("[ASSIMP] Node Created: %s, Parent: %s", mName, mParentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all child nodes
|
// Get all child nodes
|
||||||
|
|
@ -73,66 +77,27 @@ void AssimpAppNode::buildMeshList()
|
||||||
|
|
||||||
MatrixF AssimpAppNode::getTransform(F32 time)
|
MatrixF AssimpAppNode::getTransform(F32 time)
|
||||||
{
|
{
|
||||||
// Translate from assimp matrix to torque matrix.
|
// Check if we can use the last computed transform
|
||||||
// They're both row major, I wish I could just cast
|
if (time == mLastTransformTime)
|
||||||
// but that doesn't seem to be an option.
|
return mLastTransform;
|
||||||
|
|
||||||
// Note: this should be cached, it doesn't change
|
if (appParent) {
|
||||||
// at this level. This is base transform.
|
// Get parent node's transform
|
||||||
|
mLastTransform = appParent->getTransform(time);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// no parent (ie. root level) => scale by global shape <unit>
|
||||||
|
mLastTransform.identity();
|
||||||
|
if (!isBounds())
|
||||||
|
convertMat(mLastTransform);
|
||||||
|
|
||||||
// Y and Z and optionally swapped.
|
//mLastTransform.scale(ColladaUtils::getOptions().unit);
|
||||||
|
|
||||||
MatrixF mat(false);
|
|
||||||
mat.setRow(0, Point4F((F32)mNode->mTransformation.a1,
|
|
||||||
(F32)mNode->mTransformation.a3,
|
|
||||||
(F32)mNode->mTransformation.a2,
|
|
||||||
(F32)mNode->mTransformation.a4)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check for Y Z Swap
|
|
||||||
if ( Con::getBoolVariable("$Assimp::SwapYZ", false) )
|
|
||||||
{
|
|
||||||
mat.setRow(1, Point4F((F32)mNode->mTransformation.c1,
|
|
||||||
(F32)mNode->mTransformation.c3,
|
|
||||||
(F32)mNode->mTransformation.c2,
|
|
||||||
(F32)mNode->mTransformation.c4)
|
|
||||||
);
|
|
||||||
mat.setRow(2, Point4F((F32)mNode->mTransformation.b1,
|
|
||||||
(F32)mNode->mTransformation.b3,
|
|
||||||
(F32)mNode->mTransformation.b2,
|
|
||||||
(F32)mNode->mTransformation.b4)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mat.setRow(1, Point4F((F32)mNode->mTransformation.b1,
|
|
||||||
(F32)mNode->mTransformation.b3,
|
|
||||||
(F32)mNode->mTransformation.b2,
|
|
||||||
(F32)mNode->mTransformation.b4)
|
|
||||||
);
|
|
||||||
mat.setRow(2, Point4F((F32)mNode->mTransformation.c1,
|
|
||||||
(F32)mNode->mTransformation.c3,
|
|
||||||
(F32)mNode->mTransformation.c2,
|
|
||||||
(F32)mNode->mTransformation.c4)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mat.setRow(3, Point4F((F32)mNode->mTransformation.d1,
|
mLastTransform.mul(mNodeTransform);
|
||||||
(F32)mNode->mTransformation.d3,
|
mLastTransformTime = time;
|
||||||
(F32)mNode->mTransformation.d2,
|
|
||||||
(F32)mNode->mTransformation.d4)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Node transformations are carried down the hiearchy
|
return mLastTransform;
|
||||||
// so we need all of our parents transforms to make
|
|
||||||
// this work.
|
|
||||||
/*if ( appParent != 0 )
|
|
||||||
{
|
|
||||||
MatrixF parentMat = appParent->getNodeTransform(time);
|
|
||||||
mat.mul(parentMat);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return mat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
|
bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
|
||||||
|
|
@ -143,5 +108,99 @@ bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
|
||||||
/// Get the world transform of the node at the specified time
|
/// Get the world transform of the node at the specified time
|
||||||
MatrixF AssimpAppNode::getNodeTransform(F32 time)
|
MatrixF AssimpAppNode::getNodeTransform(F32 time)
|
||||||
{
|
{
|
||||||
return getTransform(time);
|
// Avoid re-computing the default transform if possible
|
||||||
|
if (mDefaultTransformValid && time == TSShapeLoader::DefaultTime)
|
||||||
|
{
|
||||||
|
return mDefaultNodeTransform;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MatrixF nodeTransform = getTransform(time);
|
||||||
|
|
||||||
|
// Check for inverted node coordinate spaces => can happen when modelers
|
||||||
|
// use the 'mirror' tool in their 3d app. Shows up as negative <scale>
|
||||||
|
// transforms in the collada model.
|
||||||
|
if (m_matF_determinant(nodeTransform) < 0.0f)
|
||||||
|
{
|
||||||
|
// Mark this node as inverted so we can mirror mesh geometry, then
|
||||||
|
// de-invert the transform matrix
|
||||||
|
mInvertMeshes = true;
|
||||||
|
nodeTransform.scale(Point3F(1, 1, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the default transform
|
||||||
|
if (time == TSShapeLoader::DefaultTime)
|
||||||
|
{
|
||||||
|
mDefaultTransformValid = true;
|
||||||
|
mDefaultNodeTransform = nodeTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nodeTransform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssimpAppNode::assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat)
|
||||||
|
{
|
||||||
|
outMat.setRow(0, Point4F((F32)inAssimpMat.a1, (F32)inAssimpMat.a2,
|
||||||
|
(F32)inAssimpMat.a3, (F32)inAssimpMat.a4));
|
||||||
|
|
||||||
|
outMat.setRow(1, Point4F((F32)inAssimpMat.b1, (F32)inAssimpMat.b2,
|
||||||
|
(F32)inAssimpMat.b3, (F32)inAssimpMat.b4));
|
||||||
|
|
||||||
|
outMat.setRow(2, Point4F((F32)inAssimpMat.c1, (F32)inAssimpMat.c2,
|
||||||
|
(F32)inAssimpMat.c3, (F32)inAssimpMat.c4));
|
||||||
|
|
||||||
|
outMat.setRow(3, Point4F((F32)inAssimpMat.d1, (F32)inAssimpMat.d2,
|
||||||
|
(F32)inAssimpMat.d3, (F32)inAssimpMat.d4));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssimpAppNode::convertMat(MatrixF& outMat)
|
||||||
|
{
|
||||||
|
MatrixF rot(true);
|
||||||
|
|
||||||
|
// This is copied directly from ColladaUtils::convertTransform()
|
||||||
|
// ColladaUtils::getOptions().upAxis has been temporarily replaced with $Assimp::OverrideUpAxis for testing
|
||||||
|
// We need a plan for how the full set of assimp import options and settings is going to be managed.
|
||||||
|
switch (Con::getIntVariable("$Assimp::OverrideUpAxis", 2))
|
||||||
|
{
|
||||||
|
case 0: //UPAXISTYPE_X_UP:
|
||||||
|
// rotate 90 around Y-axis, then 90 around Z-axis
|
||||||
|
rot(0, 0) = 0.0f; rot(1, 0) = 1.0f;
|
||||||
|
rot(1, 1) = 0.0f; rot(2, 1) = 1.0f;
|
||||||
|
rot(0, 2) = 1.0f; rot(2, 2) = 0.0f;
|
||||||
|
|
||||||
|
// pre-multiply the transform by the rotation matrix
|
||||||
|
outMat.mulL(rot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: //UPAXISTYPE_Y_UP:
|
||||||
|
// rotate 180 around Y-axis, then 90 around X-axis
|
||||||
|
rot(0, 0) = -1.0f;
|
||||||
|
rot(1, 1) = 0.0f; rot(2, 1) = 1.0f;
|
||||||
|
rot(1, 2) = 1.0f; rot(2, 2) = 0.0f;
|
||||||
|
|
||||||
|
// pre-multiply the transform by the rotation matrix
|
||||||
|
outMat.mulL(rot);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: //UPAXISTYPE_Z_UP:
|
||||||
|
default:
|
||||||
|
// nothing to do
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aiNode* AssimpAppNode::findChildNodeByName(const char* nodeName, aiNode* rootNode)
|
||||||
|
{
|
||||||
|
aiNode* retNode = NULL;
|
||||||
|
if (strcmp(nodeName, rootNode->mName.C_Str()) == 0)
|
||||||
|
return rootNode;
|
||||||
|
|
||||||
|
for (U32 i = 0; i < rootNode->mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
retNode = findChildNodeByName(nodeName, rootNode->mChildren[i]);
|
||||||
|
if (retNode)
|
||||||
|
return retNode;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +33,10 @@
|
||||||
#include "ts/collada/colladaExtensions.h"
|
#include "ts/collada/colladaExtensions.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef AI_TYPES_H_INC
|
||||||
|
#include <assimp/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class AssimpAppNode : public AppNode
|
class AssimpAppNode : public AppNode
|
||||||
{
|
{
|
||||||
typedef AppNode Parent;
|
typedef AppNode Parent;
|
||||||
|
|
@ -44,9 +48,16 @@ class AssimpAppNode : public AppNode
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const struct aiScene* mScene;
|
const struct aiScene* mScene;
|
||||||
const struct aiNode* mNode; ///< Pointer to the node in the Collada DOM
|
const struct aiNode* mNode; ///< Pointer to the assimp scene node
|
||||||
AssimpAppNode* appParent; ///< Parent node in Collada-space
|
AssimpAppNode* appParent; ///< Parent node
|
||||||
|
MatrixF mNodeTransform; ///< Scene node transform converted to TorqueSpace (filled for ALL nodes)
|
||||||
|
|
||||||
|
bool mInvertMeshes; ///< True if this node's coordinate space is inverted (left handed)
|
||||||
|
F32 mLastTransformTime; ///< Time of the last transform lookup (getTransform)
|
||||||
|
MatrixF mLastTransform; ///< Last transform lookup (getTransform) (Only Non-Dummy Nodes)
|
||||||
|
bool mDefaultTransformValid; ///< Flag indicating whether the defaultNodeTransform is valid
|
||||||
|
MatrixF mDefaultNodeTransform; ///< Transform at DefaultTime (Only Non-Dummy Nodes)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
@ -93,6 +104,10 @@ public:
|
||||||
MatrixF getNodeTransform(F32 time);
|
MatrixF getNodeTransform(F32 time);
|
||||||
bool animatesTransform(const AppSequence* appSeq);
|
bool animatesTransform(const AppSequence* appSeq);
|
||||||
bool isParentRoot() { return (appParent == NULL); }
|
bool isParentRoot() { return (appParent == NULL); }
|
||||||
|
|
||||||
|
static void assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat);
|
||||||
|
static void convertMat(MatrixF& outMat);
|
||||||
|
static aiNode* findChildNodeByName(const char* nodeName, aiNode* rootNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _ASSIMP_APPNODE_H_
|
#endif // _ASSIMP_APPNODE_H_
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,8 @@ MODULE_BEGIN( AssimpShapeLoader )
|
||||||
TSShapeLoader::addFormat("3D GameStudio (3DGS)", "mdl");
|
TSShapeLoader::addFormat("3D GameStudio (3DGS)", "mdl");
|
||||||
TSShapeLoader::addFormat("3D GameStudio (3DGS) Terrain", "hmp");
|
TSShapeLoader::addFormat("3D GameStudio (3DGS) Terrain", "hmp");
|
||||||
TSShapeLoader::addFormat("Izware Nendo", "ndo");
|
TSShapeLoader::addFormat("Izware Nendo", "ndo");
|
||||||
TSShapeLoader::addFormat("gltf", "gltf");
|
TSShapeLoader::addFormat("gltf", "gltf");
|
||||||
|
TSShapeLoader::addFormat("gltf binary", "glb");
|
||||||
}
|
}
|
||||||
MODULE_END;
|
MODULE_END;
|
||||||
|
|
||||||
|
|
@ -146,7 +147,7 @@ void AssimpShapeLoader::enumerateScene()
|
||||||
Con::getBoolVariable("$Assimp::OptimizeMeshes", false) ? aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph : 0 |
|
Con::getBoolVariable("$Assimp::OptimizeMeshes", false) ? aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph : 0 |
|
||||||
0;
|
0;
|
||||||
|
|
||||||
if(Con::getBoolVariable("$Assimp::Triangulate", false))
|
if(Con::getBoolVariable("$Assimp::Triangulate", true))
|
||||||
ppsteps |= aiProcess_Triangulate;
|
ppsteps |= aiProcess_Triangulate;
|
||||||
|
|
||||||
if (Con::getBoolVariable("$Assimp::OptimizeMeshes", false))
|
if (Con::getBoolVariable("$Assimp::OptimizeMeshes", false))
|
||||||
|
|
@ -276,6 +277,15 @@ bool AssimpShapeLoader::canLoadCachedDTS(const Torque::Path& path)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AssimpShapeLoader::ignoreNode(const String& name)
|
||||||
|
{
|
||||||
|
// Do not add AssimpFbx dummy nodes to the TSShape. See: Assimp::FBX::ImportSettings::preservePivots
|
||||||
|
// https://github.com/assimp/assimp/blob/master/code/FBXImportSettings.h#L116-L135
|
||||||
|
if (name.find("_$AssimpFbx$_") != String::NPos)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
/// This function is invoked by the resource manager based on file extension.
|
/// This function is invoked by the resource manager based on file extension.
|
||||||
TSShape* assimpLoadShape(const Torque::Path &path)
|
TSShape* assimpLoadShape(const Torque::Path &path)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,9 @@ class AssimpShapeLoader : public TSShapeLoader
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const struct aiScene* mScene;
|
const struct aiScene* mScene;
|
||||||
|
|
||||||
|
virtual bool ignoreNode(const String& name);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AssimpShapeLoader();
|
AssimpShapeLoader();
|
||||||
~AssimpShapeLoader();
|
~AssimpShapeLoader();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue