Files
OpenSceneGraph/src/osgPlugins/dae/daeRTransforms.cpp
2010-05-28 16:24:04 +00:00

400 lines
14 KiB
C++

/*
* Copyright 2006 Sony Computer Entertainment Inc.
*
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the License at:
* http://research.scea.com/scea_shared_source_license.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing permissions and limitations under the
* License.
*/
#include "daeReader.h"
#include <dae.h>
#include <dae/domAny.h>
#include <dom/domCOLLADA.h>
#include <osgAnimation/UpdateMatrixTransform>
#include <osgAnimation/StackedMatrixElement>
#include <osgAnimation/StackedRotateAxisElement>
#include <osgAnimation/StackedScaleElement>
#include <osgAnimation/StackedTranslateElement>
#include <osg/MatrixTransform>
#include <osgSim/DOFTransform>
using namespace osgDAE;
// Note <lookat>, <matrix>, <rotate>, <scale>, <skew> and <translate> may appear in any order
// These transformations can be combined in any number and ordering to produce the desired
// coordinate system for the parent <node> element. The COLLADA specificatin requires that the
// transformation elements are processed in order and accumulate the result as if they were
// converted to column-order matrices and concatenated using matrix post-multiplication.
osg::Transform* daeReader::processOsgMatrixTransform(domNode *node, bool isBone)
{
osg::MatrixTransform* resultNode = NULL;
if (isBone)
{
resultNode = getOrCreateBone(node);
}
else
{
resultNode = new osg::MatrixTransform;
}
osg::NodeCallback* pNodeCallback = resultNode->getUpdateCallback();
std::vector<osg::ref_ptr<osgAnimation::StackedTransformElement> > transformElements;
osg::ref_ptr<osgAnimation::StackedTransformElement> pLastStaticTransformElement;
// Process all coordinate system contributing elements in order!
size_t count = node->getContents().getCount();
for (size_t i = 0; i < count; i++ )
{
daeElement* pDaeElement = node->getContents()[i];
osg::ref_ptr<osgAnimation::StackedTransformElement> pTransformElement = NULL;
if (domRotate * pDomRotate = daeSafeCast< domRotate >( pDaeElement ))
{
const domFloat4& r = pDomRotate->getValue();
if (r.getCount() != 4 )
{
OSG_WARN << "Data is wrong size for rotate" << std::endl;
continue;
}
pTransformElement = new osgAnimation::StackedRotateAxisElement(pDomRotate->getSid() ? pDomRotate->getSid() : "", osg::Vec3(r[0], r[1], r[2]), osg::DegreesToRadians(r[3]));
}
else if (domTranslate * pDomTranslate = daeSafeCast< domTranslate >( pDaeElement ))
{
const domFloat3& t = pDomTranslate->getValue();
if (t.getCount() != 3 )
{
OSG_WARN<<"Data is wrong size for translate"<<std::endl;
continue;
}
pTransformElement = new osgAnimation::StackedTranslateElement(pDomTranslate->getSid() ? pDomTranslate->getSid() : "", osg::Vec3(t[0], t[1], t[2]));
}
else if (domScale * pDomScale = daeSafeCast< domScale >( pDaeElement ))
{
const domFloat3& s = pDomScale->getValue();
if (s.getCount() != 3 )
{
OSG_WARN<<"Data is wrong size for scale"<<std::endl;
continue;
}
pTransformElement = new osgAnimation::StackedScaleElement(pDomScale->getSid() ? pDomScale->getSid() : "", osg::Vec3(s[0], s[1], s[2]));
}
else if (domMatrix * pDomMatrix = daeSafeCast< domMatrix >( pDaeElement ))
{
if (pDomMatrix->getValue().getCount() != 16 )
{
OSG_WARN<<"Data is wrong size for matrix"<<std::endl;
continue;
}
pTransformElement = new osgAnimation::StackedMatrixElement(pDomMatrix->getSid() ? pDomMatrix->getSid() : "",
osg::Matrix( pDomMatrix->getValue()[0], pDomMatrix->getValue()[4], pDomMatrix->getValue()[8], pDomMatrix->getValue()[12],
pDomMatrix->getValue()[1], pDomMatrix->getValue()[5], pDomMatrix->getValue()[9], pDomMatrix->getValue()[13],
pDomMatrix->getValue()[2], pDomMatrix->getValue()[6], pDomMatrix->getValue()[10], pDomMatrix->getValue()[14],
pDomMatrix->getValue()[3], pDomMatrix->getValue()[7], pDomMatrix->getValue()[11], pDomMatrix->getValue()[15]));
}
else if (domLookat * pDomLookat = daeSafeCast< domLookat >( pDaeElement ))
{
if (pDomLookat->getValue().getCount() != 9 )
{
OSG_WARN<<"Data is wrong size for lookat"<<std::endl;
continue;
}
pTransformElement = new osgAnimation::StackedMatrixElement(pDomLookat->getSid() ? pDomLookat->getSid() : "",
osg::Matrix::lookAt(
osg::Vec3(pDomLookat->getValue()[0], pDomLookat->getValue()[1], pDomLookat->getValue()[2]),
osg::Vec3(pDomLookat->getValue()[3], pDomLookat->getValue()[4], pDomLookat->getValue()[5]),
osg::Vec3(pDomLookat->getValue()[6], pDomLookat->getValue()[7], pDomLookat->getValue()[8])));
}
else if (domSkew * pDomSkew = daeSafeCast< domSkew >( pDaeElement ))
{
if (pDomSkew->getValue().getCount() != 7 )
{
OSG_WARN<<"Data is wrong size for skew"<<std::endl;
continue;
}
const domFloat7& s = pDomSkew->getValue();
float shear = sin(osg::DegreesToRadians(s[0]));
// axis of rotation
osg::Vec3f around(s[1],s[2],s[3]);
// axis of translation
osg::Vec3f along(s[4],s[5],s[6]);
//This maths is untested so may be transposed or negated or just completely wrong.
osg::Vec3f normal = along ^ around;
normal.normalize();
around.normalize();
along *= shear / along.length();
pTransformElement = new osgAnimation::StackedMatrixElement(pDomSkew->getSid() ? pDomSkew->getSid() : "",
osg::Matrix(
normal.x() * along.x() + 1.0f, normal.x() * along.y(), normal.x() * along.z(), 0.0f,
normal.y() * along.x(), normal.y() * along.y() + 1.0f, normal.y() * along.z(), 0.0f,
normal.z() * along.x(), normal.z() * along.y(), normal.z() * along.z() + 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f));
}
if (pTransformElement)
{
daeElementDomChannelMap::iterator iter = _daeElementDomChannelMap.find(pDaeElement);
if (iter != _daeElementDomChannelMap.end())
{
// The element is animated
// First add single or collapsed transform element if any
if (pLastStaticTransformElement)
{
transformElements.push_back(pLastStaticTransformElement);
pLastStaticTransformElement = NULL;
}
transformElements.push_back(pTransformElement);
// Animated element so we need an AnimationUpdateCallback
if (!pNodeCallback)
{
std::string name = node->getId() ? node->getId() : node->getSid() ? node->getSid() : "";
resultNode->setDataVariance(osg::Object::DYNAMIC);
pNodeCallback = new osgAnimation::UpdateMatrixTransform(name);
resultNode->setUpdateCallback(pNodeCallback);
}
do
{
_domChannelOsgAnimationUpdateCallbackMap[iter->second] = pNodeCallback;
++iter;
} while (iter != _daeElementDomChannelMap.end() && iter->first == pDaeElement);
}
else if (pLastStaticTransformElement)
{
// Add transform element only if not identity
if (!pTransformElement->isIdentity())
{
// Collapse static transform elements
osg::Matrix matrix = pLastStaticTransformElement->getAsMatrix();
pTransformElement->applyToMatrix(matrix);
pLastStaticTransformElement = new osgAnimation::StackedMatrixElement("collapsed", matrix);
}
}
else if (!pTransformElement->isIdentity())
{
// Store single static transform element only if not identity
pLastStaticTransformElement = pTransformElement;
}
}
}
// Add final collapsed element (if any)
if (pLastStaticTransformElement)
{
transformElements.push_back(pLastStaticTransformElement);
}
// Build a matrix for the MatrixTransform and add the elements to the updateCallback
osg::Matrix matrix;
osgAnimation::UpdateMatrixTransform* pUpdateStackedTransform =
dynamic_cast<osgAnimation::UpdateMatrixTransform*>(pNodeCallback);
for (size_t i=0; i < transformElements.size(); i++)
{
transformElements[i]->applyToMatrix(matrix);
if (pUpdateStackedTransform)
{
pUpdateStackedTransform->getStackedTransforms().push_back(transformElements[i].get());
}
}
resultNode->setMatrix(matrix);
osg::Vec3 scale = matrix.getScale();
if ((scale.x() != 1) || (scale.y() != 1) || (scale.z() != 1))
{
osg::StateSet* ss = resultNode->getOrCreateStateSet();
ss->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
return resultNode;
}
osg::Group* daeReader::processOsgDOFTransform(domTechnique* teq)
{
osgSim::DOFTransform* dof = new osgSim::DOFTransform;
domAny* any = daeSafeCast< domAny >(teq->getChild("MinHPR"));
if (any)
{
dof->setMinHPR(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MinHPR' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MaxHPR"));
if (any)
{
dof->setMaxHPR(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MaxHPR' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("IncrementHPR"));
if (any)
{
dof->setIncrementHPR(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'IncrementHPR' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("CurrentHPR"));
if (any)
{
dof->setCurrentHPR(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'CurrentHPR' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MinTranslate"));
if (any)
{
dof->setMinTranslate(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MinTranslate' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MaxTranslate"));
if (any)
{
dof->setMaxTranslate(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MaxTranslate' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("IncrementTranslate"));
if (any)
{
dof->setIncrementTranslate(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'IncrementTranslate' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("CurrentTranslate"));
if (any)
{
dof->setCurrentTranslate(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'CurrentTranslate' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MinScale"));
if (any)
{
dof->setMinScale(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MinScale' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MaxScale"));
if (any)
{
dof->setMaxScale(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MaxScale' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("IncrementScale"));
if (any)
{
dof->setIncrementScale(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'IncrementScale' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("CurrentScale"));
if (any)
{
dof->setCurrentScale(parseVec3String(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'CurrentScale' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("MultOrder"));
if (any)
{
dof->setHPRMultOrder((osgSim::DOFTransform::MultOrder)parseString<int>(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'MultOrder' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("LimitationFlags"));
if (any)
{
dof->setLimitationFlags(parseString<unsigned long>(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'LimitationFlags' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("AnimationOn"));
if (any)
{
dof->setAnimationOn(parseString<bool>(any->getValue()));
}
else
{
OSG_WARN << "Expected element 'AnimationOn' not found" << std::endl;
}
any = daeSafeCast< domAny >(teq->getChild("PutMatrix"));
if (any)
{
osg::Matrix mat = parseMatrixString(any->getValue());
dof->setPutMatrix(mat);
dof->setInversePutMatrix( osg::Matrixd::inverse( mat ) );
}
else
{
OSG_WARN << "Expected element 'PutMatrix' not found" << std::endl;
}
return dof;
}