mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-13 19:53:48 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
260
Engine/source/ts/collada/colladaAppNode.cpp
Normal file
260
Engine/source/ts/collada/colladaAppNode.cpp
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4706) // disable warning about assignment within conditional
|
||||
#endif
|
||||
|
||||
#include "ts/loader/appSequence.h"
|
||||
#include "ts/collada/colladaExtensions.h"
|
||||
#include "ts/collada/colladaAppNode.h"
|
||||
#include "ts/collada/colladaAppMesh.h"
|
||||
#include "ts/collada/colladaAppMesh.h"
|
||||
|
||||
#include "core/stringTable.h"
|
||||
|
||||
// Trim leading and trailing whitespace from the first word in the string
|
||||
// Note that the string is modified.
|
||||
static char* TrimFirstWord(char* str)
|
||||
{
|
||||
char* value = str;
|
||||
|
||||
// Trim leading whitespace
|
||||
while ( value && *value && dIsspace( *value ) )
|
||||
value++;
|
||||
|
||||
// Trim trailing whitespace
|
||||
if ( value && *value )
|
||||
{
|
||||
char* end = value + 1;
|
||||
while ( *end && !dIsspace( *end ) )
|
||||
end++;
|
||||
*end = '\0';
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
ColladaAppNode::ColladaAppNode(const domNode* node, ColladaAppNode* parent)
|
||||
: p_domNode(node), appParent(parent), nodeExt(new ColladaExtension_node(node)),
|
||||
lastTransformTime(TSShapeLoader::DefaultTime-1), defaultTransformValid(false),
|
||||
invertMeshes(false)
|
||||
{
|
||||
mName = dStrdup(_GetNameOrId(node));
|
||||
mParentName = dStrdup(parent ? parent->getName() : "ROOT");
|
||||
|
||||
// Extract user properties from the <node> extension as whitespace separated
|
||||
// "name=value" pairs
|
||||
char* properties = dStrdup(nodeExt->user_properties);
|
||||
char* pos = properties;
|
||||
char* end = properties + dStrlen( properties );
|
||||
while ( pos < end )
|
||||
{
|
||||
// Find the '=' character to separate the name and value pair
|
||||
char* split = dStrchr( pos, '=' );
|
||||
if ( !split )
|
||||
break;
|
||||
|
||||
// Get the name (whitespace trimmed string up to the '=')
|
||||
// and value (whitespace trimmed string after the '=')
|
||||
*split = '\0';
|
||||
char* name = TrimFirstWord( pos );
|
||||
char* value = TrimFirstWord( split + 1 );
|
||||
|
||||
mProps.insert(StringTable->insert(name), dAtof(value));
|
||||
|
||||
pos = value + dStrlen( value ) + 1;
|
||||
}
|
||||
|
||||
dFree( properties );
|
||||
|
||||
// Create vector of transform elements
|
||||
for (int iChild = 0; iChild < node->getContents().getCount(); iChild++) {
|
||||
switch (node->getContents()[iChild]->getElementType()) {
|
||||
case COLLADA_TYPE::TRANSLATE:
|
||||
case COLLADA_TYPE::ROTATE:
|
||||
case COLLADA_TYPE::SCALE:
|
||||
case COLLADA_TYPE::SKEW:
|
||||
case COLLADA_TYPE::MATRIX:
|
||||
case COLLADA_TYPE::LOOKAT:
|
||||
nodeTransforms.increment();
|
||||
nodeTransforms.last().element = node->getContents()[iChild];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get all child nodes
|
||||
void ColladaAppNode::buildChildList()
|
||||
{
|
||||
// Process children: collect <node> and <instance_node> elements
|
||||
for (int iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) {
|
||||
|
||||
daeElement* child = p_domNode->getContents()[iChild];
|
||||
switch (child->getElementType()) {
|
||||
|
||||
case COLLADA_TYPE::NODE:
|
||||
{
|
||||
domNode* node = daeSafeCast<domNode>(child);
|
||||
mChildNodes.push_back(new ColladaAppNode(node, this));
|
||||
break;
|
||||
}
|
||||
|
||||
case COLLADA_TYPE::INSTANCE_NODE:
|
||||
{
|
||||
domInstance_node* instanceNode = daeSafeCast<domInstance_node>(child);
|
||||
domNode* node = daeSafeCast<domNode>(instanceNode->getUrl().getElement());
|
||||
if (node)
|
||||
mChildNodes.push_back(new ColladaAppNode(node, this));
|
||||
else
|
||||
Con::warnf("Failed to resolve instance_node with url=%s", instanceNode->getUrl().originalStr().c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get all geometry attached to this node
|
||||
void ColladaAppNode::buildMeshList()
|
||||
{
|
||||
// Process children: collect <instance_geometry> and <instance_controller> elements
|
||||
for (int iChild = 0; iChild < p_domNode->getContents().getCount(); iChild++) {
|
||||
|
||||
daeElement* child = p_domNode->getContents()[iChild];
|
||||
switch (child->getElementType()) {
|
||||
|
||||
case COLLADA_TYPE::INSTANCE_GEOMETRY:
|
||||
{
|
||||
// Only <geometry>.<mesh> instances are supported
|
||||
domInstance_geometry* instanceGeom = daeSafeCast<domInstance_geometry>(child);
|
||||
if (instanceGeom) {
|
||||
domGeometry* geometry = daeSafeCast<domGeometry>(instanceGeom->getUrl().getElement());
|
||||
if (geometry && geometry->getMesh())
|
||||
mMeshes.push_back(new ColladaAppMesh(instanceGeom, this));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case COLLADA_TYPE::INSTANCE_CONTROLLER:
|
||||
mMeshes.push_back(new ColladaAppMesh(daeSafeCast<domInstance_controller>(child), this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ColladaAppNode::animatesTransform(const AppSequence* appSeq)
|
||||
{
|
||||
// Check if any of this node's transform elements are animated during the
|
||||
// sequence interval
|
||||
for (int iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) {
|
||||
if (nodeTransforms[iTxfm].isAnimated(appSeq->getStart(), appSeq->getEnd()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the world transform of the node at the specified time
|
||||
MatrixF ColladaAppNode::getNodeTransform(F32 time)
|
||||
{
|
||||
// Avoid re-computing the default transform if possible
|
||||
if (defaultTransformValid && time == TSShapeLoader::DefaultTime)
|
||||
{
|
||||
return defaultNodeTransform;
|
||||
}
|
||||
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
|
||||
invertMeshes = true;
|
||||
nodeTransform.scale(Point3F(1, 1, -1));
|
||||
}
|
||||
|
||||
// Cache the default transform
|
||||
if (time == TSShapeLoader::DefaultTime)
|
||||
{
|
||||
defaultTransformValid = true;
|
||||
defaultNodeTransform = nodeTransform;
|
||||
}
|
||||
|
||||
return nodeTransform;
|
||||
}
|
||||
}
|
||||
|
||||
MatrixF ColladaAppNode::getTransform(F32 time)
|
||||
{
|
||||
// Check if we can use the last computed transform
|
||||
if (time == lastTransformTime)
|
||||
return lastTransform;
|
||||
|
||||
if (appParent) {
|
||||
// Get parent node's transform
|
||||
lastTransform = appParent->getTransform(time);
|
||||
}
|
||||
else {
|
||||
// no parent (ie. root level) => scale by global shape <unit>
|
||||
lastTransform.identity();
|
||||
lastTransform.scale(ColladaUtils::getOptions().unit);
|
||||
if (!isBounds())
|
||||
ColladaUtils::convertTransform(lastTransform); // don't convert bounds node transform (or upAxis won't work!)
|
||||
}
|
||||
|
||||
// Multiply by local node transform elements
|
||||
for (int iTxfm = 0; iTxfm < nodeTransforms.size(); iTxfm++) {
|
||||
|
||||
MatrixF mat(true);
|
||||
|
||||
// Convert the transform element to a MatrixF
|
||||
switch (nodeTransforms[iTxfm].element->getElementType()) {
|
||||
case COLLADA_TYPE::TRANSLATE: mat = vecToMatrixF<domTranslate>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
case COLLADA_TYPE::SCALE: mat = vecToMatrixF<domScale>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
case COLLADA_TYPE::ROTATE: mat = vecToMatrixF<domRotate>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
case COLLADA_TYPE::MATRIX: mat = vecToMatrixF<domMatrix>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
case COLLADA_TYPE::SKEW: mat = vecToMatrixF<domSkew>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
case COLLADA_TYPE::LOOKAT: mat = vecToMatrixF<domLookat>(nodeTransforms[iTxfm].getValue(time)); break;
|
||||
}
|
||||
|
||||
// Remove node scaling (but keep reflections) if desired
|
||||
if (ColladaUtils::getOptions().ignoreNodeScale)
|
||||
{
|
||||
Point3F invScale = mat.getScale();
|
||||
invScale.x = invScale.x ? (1.0f / invScale.x) : 0;
|
||||
invScale.y = invScale.y ? (1.0f / invScale.y) : 0;
|
||||
invScale.z = invScale.z ? (1.0f / invScale.z) : 0;
|
||||
mat.scale(invScale);
|
||||
}
|
||||
|
||||
// Post multiply the animated transform
|
||||
lastTransform.mul(mat);
|
||||
}
|
||||
|
||||
lastTransformTime = time;
|
||||
return lastTransform;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue