2019-02-08 22:25:43 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
|
|
|
//
|
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
// of this software and associated documentation files (the "Software"), to
|
|
|
|
|
// deal in the Software without restriction, including without limitation the
|
|
|
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
// furnished to do so, subject to the following conditions:
|
|
|
|
|
//
|
|
|
|
|
// The above copyright notice and this permission notice shall be included in
|
|
|
|
|
// all copies or substantial portions of the Software.
|
|
|
|
|
//
|
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
// IN THE SOFTWARE.
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
#include "platform/platform.h"
|
|
|
|
|
#include "ts/loader/appSequence.h"
|
|
|
|
|
#include "ts/assimp/assimpAppNode.h"
|
|
|
|
|
#include "ts/assimp/assimpAppMesh.h"
|
|
|
|
|
|
|
|
|
|
// assimp include files.
|
|
|
|
|
#include <assimp/cimport.h>
|
|
|
|
|
#include <assimp/scene.h>
|
|
|
|
|
#include <assimp/postprocess.h>
|
|
|
|
|
#include <assimp/types.h>
|
|
|
|
|
|
|
|
|
|
AssimpAppNode::AssimpAppNode(const struct aiScene* scene, const struct aiNode* node, AssimpAppNode* parent)
|
2019-03-24 10:18:20 +00:00
|
|
|
: mInvertMeshes(false),
|
|
|
|
|
mLastTransformTime(TSShapeLoader::DefaultTime - 1),
|
|
|
|
|
mDefaultTransformValid(false)
|
2019-02-08 22:25:43 +00:00
|
|
|
{
|
|
|
|
|
mScene = scene;
|
|
|
|
|
mNode = node;
|
|
|
|
|
appParent = parent;
|
|
|
|
|
|
|
|
|
|
mName = dStrdup(mNode->mName.C_Str());
|
|
|
|
|
if ( dStrlen(mName) == 0 )
|
|
|
|
|
{
|
|
|
|
|
const char* defaultName = "null";
|
|
|
|
|
mName = dStrdup(defaultName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mParentName = dStrdup(parent ? parent->getName() : "ROOT");
|
2019-03-24 10:18:20 +00:00
|
|
|
assimpToTorqueMat(node->mTransformation, mNodeTransform);
|
|
|
|
|
Con::printf("[ASSIMP] Node Created: %s, Parent: %s", mName, mParentName);
|
2019-02-08 22:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get all child nodes
|
|
|
|
|
void AssimpAppNode::buildChildList()
|
|
|
|
|
{
|
|
|
|
|
if (!mNode)
|
|
|
|
|
{
|
|
|
|
|
mNode = mScene->mRootNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (U32 n = 0; n < mNode->mNumChildren; ++n) {
|
|
|
|
|
mChildNodes.push_back(new AssimpAppNode(mScene, mNode->mChildren[n], this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get all geometry attached to this node
|
|
|
|
|
void AssimpAppNode::buildMeshList()
|
|
|
|
|
{
|
|
|
|
|
for (U32 n = 0; n < mNode->mNumMeshes; ++n)
|
|
|
|
|
{
|
|
|
|
|
const struct aiMesh* mesh = mScene->mMeshes[mNode->mMeshes[n]];
|
|
|
|
|
mMeshes.push_back(new AssimpAppMesh(mesh, this));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MatrixF AssimpAppNode::getTransform(F32 time)
|
|
|
|
|
{
|
2019-03-24 10:18:20 +00:00
|
|
|
// Check if we can use the last computed transform
|
|
|
|
|
if (time == mLastTransformTime)
|
|
|
|
|
return mLastTransform;
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
if (appParent) {
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
|
|
//mLastTransform.scale(ColladaUtils::getOptions().unit);
|
|
|
|
|
}
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
mLastTransform.mul(mNodeTransform);
|
|
|
|
|
mLastTransformTime = time;
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
return mLastTransform;
|
|
|
|
|
}
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
bool AssimpAppNode::animatesTransform(const AppSequence* appSeq)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Get the world transform of the node at the specified time
|
|
|
|
|
MatrixF AssimpAppNode::getNodeTransform(F32 time)
|
|
|
|
|
{
|
|
|
|
|
// Avoid re-computing the default transform if possible
|
|
|
|
|
if (mDefaultTransformValid && time == TSShapeLoader::DefaultTime)
|
2019-02-08 22:25:43 +00:00
|
|
|
{
|
2019-03-24 10:18:20 +00:00
|
|
|
return mDefaultNodeTransform;
|
|
|
|
|
}
|
|
|
|
|
else
|
2019-02-08 22:25:43 +00:00
|
|
|
{
|
2019-03-24 10:18:20 +00:00
|
|
|
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;
|
2019-02-08 22:25:43 +00:00
|
|
|
}
|
2019-03-24 10:18:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AssimpAppNode::assimpToTorqueMat(const aiMatrix4x4& inAssimpMat, MatrixF& outMat)
|
|
|
|
|
{
|
|
|
|
|
outMat.setRow(0, Point4F((F32)inAssimpMat.a1, (F32)inAssimpMat.a2,
|
|
|
|
|
(F32)inAssimpMat.a3, (F32)inAssimpMat.a4));
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
outMat.setRow(1, Point4F((F32)inAssimpMat.b1, (F32)inAssimpMat.b2,
|
|
|
|
|
(F32)inAssimpMat.b3, (F32)inAssimpMat.b4));
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
outMat.setRow(2, Point4F((F32)inAssimpMat.c1, (F32)inAssimpMat.c2,
|
|
|
|
|
(F32)inAssimpMat.c3, (F32)inAssimpMat.c4));
|
2019-02-08 22:25:43 +00:00
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
outMat.setRow(3, Point4F((F32)inAssimpMat.d1, (F32)inAssimpMat.d2,
|
|
|
|
|
(F32)inAssimpMat.d3, (F32)inAssimpMat.d4));
|
2019-02-08 22:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
void AssimpAppNode::convertMat(MatrixF& outMat)
|
2019-02-08 22:25:43 +00:00
|
|
|
{
|
2019-03-24 10:18:20 +00:00
|
|
|
if (Con::getBoolVariable("$Assimp::SwapYZ", false))
|
|
|
|
|
{
|
|
|
|
|
MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
|
|
|
|
|
Point3F pos = outMat.getPosition();
|
|
|
|
|
outMat.mulL(rotMat);
|
|
|
|
|
rotMat.mulP(pos);
|
|
|
|
|
outMat.setPosition(pos);
|
|
|
|
|
}
|
2019-02-08 22:25:43 +00:00
|
|
|
}
|
|
|
|
|
|
2019-03-24 10:18:20 +00:00
|
|
|
void AssimpAppNode::convertPoint(Point3F& outPoint)
|
2019-02-08 22:25:43 +00:00
|
|
|
{
|
2019-03-24 10:18:20 +00:00
|
|
|
if (Con::getBoolVariable("$Assimp::SwapYZ", false))
|
|
|
|
|
{
|
|
|
|
|
MatrixF rotMat(EulerF(-M_HALFPI_F, 0, 0));
|
|
|
|
|
rotMat.mulP(outPoint);
|
|
|
|
|
}
|
|
|
|
|
}
|