From Michael Platings, "Here's the all-new, all-dancing DAE plugin, with support for reading
osgAnimation. It's been tested with the majority of the samples in the COLLADA test repository and works with all of them either as well as, or better than, the version of the plugin currently in SVN. Known issue: vertex animation (AKA morphing) doesn't work at present, but that's a relatively unpopular method of animating so it's not high on my priority list." Follow up email: "I've been informed that the previous DAE submission didn't build on unix, so here's the submission again with the fixes. Thanks to Gregory Potdevin and Benjamin Bozou. Also, my apologies to Roland for not crediting his part in making DAE animation happen, my work was indeed built on top of his work. Thanks also to Marius Heise and of course Cedric Pinson." Changes by Robert Osfield, fixed compile issues when compile without C* automatic conversion enabled in ref_ptr<> and constructor initialization fixes to address some warnings under gcc.
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include <osg/Vec2b>
|
||||
#include <osg/Vec3b>
|
||||
#include <osg/Vec4b>
|
||||
#include <osg/Matrix>
|
||||
|
||||
#include <osg/BufferObject>
|
||||
|
||||
@@ -71,7 +72,8 @@ class OSG_EXPORT Array : public BufferData
|
||||
DoubleArrayType = 18,
|
||||
Vec2dArrayType = 19,
|
||||
Vec3dArrayType = 20,
|
||||
Vec4dArrayType = 21
|
||||
Vec4dArrayType = 21,
|
||||
MatrixArrayType = 22
|
||||
};
|
||||
|
||||
Array(Type arrayType=ArrayType,GLint dataSize=0,GLenum dataType=0):
|
||||
@@ -309,6 +311,8 @@ typedef TemplateArray<Vec2d,Array::Vec2dArrayType,2,GL_DOUBLE>
|
||||
typedef TemplateArray<Vec3d,Array::Vec3dArrayType,3,GL_DOUBLE> Vec3dArray;
|
||||
typedef TemplateArray<Vec4d,Array::Vec4dArrayType,4,GL_DOUBLE> Vec4dArray;
|
||||
|
||||
typedef TemplateArray<Matrixf,Array::MatrixArrayType,16,GL_FLOAT> MatrixfArray;
|
||||
|
||||
|
||||
class ArrayVisitor
|
||||
{
|
||||
@@ -343,6 +347,8 @@ class ArrayVisitor
|
||||
virtual void apply(Vec2dArray&) {}
|
||||
virtual void apply(Vec3dArray&) {}
|
||||
virtual void apply(Vec4dArray&) {}
|
||||
|
||||
virtual void apply(MatrixfArray&) {}
|
||||
};
|
||||
|
||||
class ConstArrayVisitor
|
||||
@@ -378,6 +384,8 @@ class ConstArrayVisitor
|
||||
virtual void apply(const Vec2dArray&) {}
|
||||
virtual void apply(const Vec3dArray&) {}
|
||||
virtual void apply(const Vec4dArray&) {}
|
||||
|
||||
virtual void apply(const MatrixfArray&) {}
|
||||
};
|
||||
|
||||
|
||||
@@ -414,6 +422,8 @@ class ValueVisitor
|
||||
virtual void apply(Vec2d&) {}
|
||||
virtual void apply(Vec3d&) {}
|
||||
virtual void apply(Vec4d&) {}
|
||||
|
||||
virtual void apply(Matrixf&) {}
|
||||
};
|
||||
|
||||
class ConstValueVisitor
|
||||
@@ -448,6 +458,8 @@ class ConstValueVisitor
|
||||
virtual void apply(const Vec2d&) {}
|
||||
virtual void apply(const Vec3d&) {}
|
||||
virtual void apply(const Vec4d&) {}
|
||||
|
||||
virtual void apply(const Matrixf&) {}
|
||||
};
|
||||
|
||||
template<typename T, Array::Type ARRAYTYPE, int DataSize, int DataType>
|
||||
|
||||
@@ -383,6 +383,116 @@ class OSG_EXPORT Matrixf
|
||||
return r;
|
||||
}
|
||||
|
||||
/** Multiply by scalar. */
|
||||
inline Matrixf operator * (value_type rhs) const
|
||||
{
|
||||
return Matrixf(
|
||||
_mat[0][0]*rhs, _mat[0][1]*rhs, _mat[0][2]*rhs, _mat[0][3]*rhs,
|
||||
_mat[1][0]*rhs, _mat[1][1]*rhs, _mat[1][2]*rhs, _mat[1][3]*rhs,
|
||||
_mat[2][0]*rhs, _mat[2][1]*rhs, _mat[2][2]*rhs, _mat[2][3]*rhs,
|
||||
_mat[3][0]*rhs, _mat[3][1]*rhs, _mat[3][2]*rhs, _mat[3][3]*rhs);
|
||||
}
|
||||
|
||||
/** Unary multiply by scalar. */
|
||||
inline Matrixf& operator *= (value_type rhs)
|
||||
{
|
||||
_mat[0][0]*=rhs;
|
||||
_mat[0][1]*=rhs;
|
||||
_mat[0][2]*=rhs;
|
||||
_mat[0][3]*=rhs;
|
||||
_mat[1][0]*=rhs;
|
||||
_mat[1][1]*=rhs;
|
||||
_mat[1][2]*=rhs;
|
||||
_mat[1][3]*=rhs;
|
||||
_mat[2][0]*=rhs;
|
||||
_mat[2][1]*=rhs;
|
||||
_mat[2][2]*=rhs;
|
||||
_mat[2][3]*=rhs;
|
||||
_mat[3][0]*=rhs;
|
||||
_mat[3][1]*=rhs;
|
||||
_mat[3][2]*=rhs;
|
||||
_mat[3][3]*=rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Divide by scalar. */
|
||||
inline Matrixf operator / (value_type rhs) const
|
||||
{
|
||||
return Matrixf(
|
||||
_mat[0][0]/rhs, _mat[0][1]/rhs, _mat[0][2]/rhs, _mat[0][3]/rhs,
|
||||
_mat[1][0]/rhs, _mat[1][1]/rhs, _mat[1][2]/rhs, _mat[1][3]/rhs,
|
||||
_mat[2][0]/rhs, _mat[2][1]/rhs, _mat[2][2]/rhs, _mat[2][3]/rhs,
|
||||
_mat[3][0]/rhs, _mat[3][1]/rhs, _mat[3][2]/rhs, _mat[3][3]/rhs);
|
||||
}
|
||||
|
||||
/** Unary divide by scalar. */
|
||||
inline Matrixf& operator /= (value_type rhs)
|
||||
{
|
||||
_mat[0][0]/=rhs;
|
||||
_mat[0][1]/=rhs;
|
||||
_mat[0][2]/=rhs;
|
||||
_mat[0][3]/=rhs;
|
||||
_mat[1][0]/=rhs;
|
||||
_mat[1][1]/=rhs;
|
||||
_mat[1][2]/=rhs;
|
||||
_mat[1][3]/=rhs;
|
||||
_mat[2][0]/=rhs;
|
||||
_mat[2][1]/=rhs;
|
||||
_mat[2][2]/=rhs;
|
||||
_mat[2][3]/=rhs;
|
||||
_mat[3][0]/=rhs;
|
||||
_mat[3][1]/=rhs;
|
||||
_mat[3][2]/=rhs;
|
||||
_mat[3][3]/=rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Binary vector add. */
|
||||
inline Matrixf operator + (const Matrixf& rhs) const
|
||||
{
|
||||
return Matrixf(
|
||||
_mat[0][0] + rhs._mat[0][0],
|
||||
_mat[0][1] + rhs._mat[0][1],
|
||||
_mat[0][2] + rhs._mat[0][2],
|
||||
_mat[0][3] + rhs._mat[0][3],
|
||||
_mat[1][0] + rhs._mat[1][0],
|
||||
_mat[1][1] + rhs._mat[1][1],
|
||||
_mat[1][2] + rhs._mat[1][2],
|
||||
_mat[1][3] + rhs._mat[1][3],
|
||||
_mat[2][0] + rhs._mat[2][0],
|
||||
_mat[2][1] + rhs._mat[2][1],
|
||||
_mat[2][2] + rhs._mat[2][2],
|
||||
_mat[2][3] + rhs._mat[2][3],
|
||||
_mat[3][0] + rhs._mat[3][0],
|
||||
_mat[3][1] + rhs._mat[3][1],
|
||||
_mat[3][2] + rhs._mat[3][2],
|
||||
_mat[3][3] + rhs._mat[3][3]);
|
||||
}
|
||||
|
||||
/** Unary vector add. Slightly more efficient because no temporary
|
||||
* intermediate object.
|
||||
*/
|
||||
inline Matrixf& operator += (const Matrixf& rhs)
|
||||
{
|
||||
_mat[0][0] += rhs._mat[0][0];
|
||||
_mat[0][1] += rhs._mat[0][1];
|
||||
_mat[0][2] += rhs._mat[0][2];
|
||||
_mat[0][3] += rhs._mat[0][3];
|
||||
_mat[1][0] += rhs._mat[1][0];
|
||||
_mat[1][1] += rhs._mat[1][1];
|
||||
_mat[1][2] += rhs._mat[1][2];
|
||||
_mat[1][3] += rhs._mat[1][3];
|
||||
_mat[2][0] += rhs._mat[2][0];
|
||||
_mat[2][1] += rhs._mat[2][1];
|
||||
_mat[2][2] += rhs._mat[2][2];
|
||||
_mat[2][3] += rhs._mat[2][3];
|
||||
_mat[3][0] += rhs._mat[3][0];
|
||||
_mat[3][1] += rhs._mat[3][1];
|
||||
_mat[3][2] += rhs._mat[3][2];
|
||||
_mat[3][3] += rhs._mat[3][3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
value_type _mat[4][4];
|
||||
|
||||
|
||||
@@ -2,10 +2,13 @@ INCLUDE_DIRECTORIES( ${COLLADA_INCLUDE_DIR} ${COLLADA_INCLUDE_DIR}/1.4)
|
||||
|
||||
SET(TARGET_SRC
|
||||
daeReader.cpp
|
||||
daeRAnimations.cpp
|
||||
daeRGeometry.cpp
|
||||
daeRMaterials.cpp
|
||||
daeRSceneObjects.cpp
|
||||
daeRSkinning.cpp
|
||||
daeRTransforms.cpp
|
||||
daeWAnimations.cpp
|
||||
daeWGeometry.cpp
|
||||
daeWMaterials.cpp
|
||||
daeWriter.cpp
|
||||
@@ -66,7 +69,7 @@ ELSE()
|
||||
|
||||
ENDIF()
|
||||
|
||||
SET(TARGET_ADDED_LIBRARIES osgSim )
|
||||
SET(TARGET_ADDED_LIBRARIES osgSim osgAnimation)
|
||||
|
||||
#### end var setup ###
|
||||
SETUP_PLUGIN(dae dae)
|
||||
|
||||
@@ -57,7 +57,7 @@ ReaderWriterDAE::readNode(const std::string& fname,
|
||||
pDAE = new DAE;
|
||||
}
|
||||
|
||||
osgdae::daeReader daeReader(pDAE, options && options->getOptionString().find("StrictTransparency") != std::string::npos ) ;
|
||||
osgDAE::daeReader daeReader(pDAE, options && options->getOptionString().find("StrictTransparency") != std::string::npos ) ;
|
||||
|
||||
// Convert file name to URI
|
||||
std::string fileURI = ConvertFilePathToColladaCompatibleURI(fileName);
|
||||
@@ -75,11 +75,11 @@ ReaderWriterDAE::readNode(const std::string& fname,
|
||||
*(std::string*)options->getPluginData("DAE-DocumentURI") = fileURI;
|
||||
// Return some additional information about the document
|
||||
if (options->getPluginData("DAE-AssetUnitName"))
|
||||
*(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.m_AssetUnitName;
|
||||
*(std::string*)options->getPluginData("DAE-AssetUnitName") = daeReader.getAssetUnitName();
|
||||
if (options->getPluginData("DAE-AssetUnitMeter"))
|
||||
*(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.m_AssetUnitMeter;
|
||||
*(float*)options->getPluginData("DAE-AssetUnitMeter") = daeReader.getAssetUnitMeter();
|
||||
if (options->getPluginData("DAE-AssetUp_axis"))
|
||||
*(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.m_AssetUp_axis;
|
||||
*(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis();
|
||||
}
|
||||
|
||||
if (bOwnDAE)
|
||||
@@ -141,14 +141,14 @@ ReaderWriterDAE::writeNode( const osg::Node& node,
|
||||
|
||||
osg::NodeVisitor::TraversalMode traversalMode = writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN;
|
||||
|
||||
osgdae::daeWriter daeWriter(pDAE, fileURI, usePolygon, GoogleMode, traversalMode, writeExtras);
|
||||
osgDAE::daeWriter daeWriter(pDAE, fileURI, usePolygon, GoogleMode, traversalMode, writeExtras);
|
||||
daeWriter.setRootNode( node );
|
||||
const_cast<osg::Node*>(&node)->accept( daeWriter );
|
||||
|
||||
osgDB::ReaderWriter::WriteResult retVal( WriteResult::ERROR_IN_WRITING_FILE );
|
||||
if ( daeWriter.isSuccess() )
|
||||
{
|
||||
if ( daeWriter.writeFile() )
|
||||
if (pDAE->write(fileURI))
|
||||
retVal = WriteResult::FILE_SAVED;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
// OSG reader/writer plugin for the COLLADA 1.4.x ".dae" format.
|
||||
// See http://collada.org/ and http://khronos.org/collada/
|
||||
|
||||
#define EXTENSION_NAME "dae"
|
||||
|
||||
class ReaderWriterDAE : public osgDB::ReaderWriter
|
||||
{
|
||||
public:
|
||||
ReaderWriterDAE()
|
||||
{
|
||||
supportsExtension(EXTENSION_NAME,"COLLADA 1.4.x DAE format");
|
||||
// Collada document
|
||||
supportsExtension("dae","COLLADA 1.4.x DAE format");
|
||||
// Collada zip archive (contains one or more dae files and a manifest.xml)
|
||||
supportsExtension("zae","COLLADA 1.4.x ZAE format");
|
||||
}
|
||||
|
||||
const char* className() const { return "COLLADA 1.4.x DAE reader/writer"; }
|
||||
|
||||
891
src/osgPlugins/dae/daeRAnimations.cpp
Normal file
891
src/osgPlugins/dae/daeRAnimations.cpp
Normal file
@@ -0,0 +1,891 @@
|
||||
#include "daeReader.h"
|
||||
#include "domSourceReader.h"
|
||||
#include <dae.h>
|
||||
#include <dae/domAny.h>
|
||||
#include <dom/domCOLLADA.h>
|
||||
#include <dom/domConstants.h>
|
||||
|
||||
#include <osgAnimation/Channel>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
#include <osgAnimation/StackedTransform>
|
||||
#include <osgAnimation/StackedRotateAxisElement>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
|
||||
using namespace osgDAE;
|
||||
|
||||
|
||||
// Mapping Collada animations to Osg animations
|
||||
// domAnimation -> osgAnimation::Animation
|
||||
// domSampler -> osgAnimation::Channel
|
||||
// domSource -> osgAnimation::Channel.Sampler
|
||||
// domChannel -> osgAnimation::Channel.TargetName
|
||||
osgAnimation::BasicAnimationManager* daeReader::processAnimationLibraries(domCOLLADA* document)
|
||||
{
|
||||
domLibrary_animation_clips_Array domAnimationClipsLibraries = document->getLibrary_animation_clips_array();
|
||||
|
||||
domLibrary_animations_Array domAnimationsLibraries = document->getLibrary_animations_array();
|
||||
osgAnimation::BasicAnimationManager* pOsgAnimationManager = NULL;
|
||||
|
||||
// Only create an animationmanager if we have animation clip libraries or animation libraries
|
||||
if ((domAnimationClipsLibraries.getCount() > 0) || (domAnimationsLibraries.getCount() > 0))
|
||||
{
|
||||
pOsgAnimationManager = new osgAnimation::BasicAnimationManager();
|
||||
|
||||
// Process all animation clip libraries
|
||||
for (size_t i=0; i < domAnimationClipsLibraries.getCount(); i++)
|
||||
{
|
||||
domAnimation_clip_Array domAnimationClips = domAnimationClipsLibraries[i]->getAnimation_clip_array();
|
||||
// Process all animation clips in this library
|
||||
for (size_t j=0; j < domAnimationClips.getCount(); j++)
|
||||
{
|
||||
processAnimationClip(pOsgAnimationManager, domAnimationClips[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no clips then all animations are part of the same clip
|
||||
if (domAnimationClipsLibraries.getCount() == 0 && domAnimationsLibraries.getCount())
|
||||
{
|
||||
osgAnimation::Animation* pOsgAnimation = new osgAnimation::Animation;
|
||||
pOsgAnimation->setName("Default");
|
||||
pOsgAnimationManager->registerAnimation(pOsgAnimation);
|
||||
|
||||
// Process all animation libraries
|
||||
for (size_t i=0; i < domAnimationsLibraries.getCount(); i++)
|
||||
{
|
||||
domAnimation_Array domAnimations = domAnimationsLibraries[i]->getAnimation_array();
|
||||
// Process all animations in this library
|
||||
for (size_t j=0; j < domAnimations.getCount(); j++)
|
||||
{
|
||||
processAnimation(domAnimations[j], pOsgAnimation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pOsgAnimationManager;
|
||||
}
|
||||
|
||||
// <animation_clip (id) (name) (start) (end)>
|
||||
// 0..1 <asset>
|
||||
// 1..* <instance_animation>
|
||||
// 0..* <extra>
|
||||
void daeReader::processAnimationClip(osgAnimation::BasicAnimationManager* pOsgAnimationManager, domAnimation_clip* pDomAnimationClip)
|
||||
{
|
||||
// an <animation_clip> groups animations
|
||||
osgAnimation::Animation* pOsgAnimation = new osgAnimation::Animation;
|
||||
std::string name = pDomAnimationClip->getId() ? pDomAnimationClip->getId() : "AnimationClip";
|
||||
pOsgAnimation->setName(name);
|
||||
|
||||
// We register the animation inside the scheduler
|
||||
pOsgAnimationManager->registerAnimation(pOsgAnimation);
|
||||
|
||||
double start = pDomAnimationClip->getStart();
|
||||
double end = pDomAnimationClip->getEnd();
|
||||
|
||||
pOsgAnimation->setStartTime(start);
|
||||
double duration = end - start;
|
||||
if (duration > 0)
|
||||
{
|
||||
pOsgAnimation->setDuration(duration);
|
||||
}
|
||||
|
||||
// 1..* <instance_animation>
|
||||
domInstanceWithExtra_Array domInstanceArray = pDomAnimationClip->getInstance_animation_array();
|
||||
for (size_t i=0; i < domInstanceArray.getCount(); i++)
|
||||
{
|
||||
domAnimation *pDomAnimation = daeSafeCast<domAnimation>(getElementFromURI(domInstanceArray[i]->getUrl()));
|
||||
if (pDomAnimation)
|
||||
{
|
||||
// getorcreateanimation
|
||||
processAnimation(pDomAnimation, pOsgAnimation);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Failed to locate animation " << domInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct KeyFrameComparator
|
||||
{
|
||||
bool operator () (const osgAnimation::Keyframe& a, const osgAnimation::Keyframe& b) const
|
||||
{
|
||||
return a.getTime() < b.getTime();
|
||||
}
|
||||
bool operator () (const osgAnimation::Keyframe& a, float t) const
|
||||
{
|
||||
return a.getTime() < t;
|
||||
}
|
||||
bool operator () (float t, const osgAnimation::Keyframe& b) const
|
||||
{
|
||||
return t < b.getTime();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
void deCasteljau(osgAnimation::TemplateCubicBezier<T>& l, osgAnimation::TemplateCubicBezier<T>& n, osgAnimation::TemplateCubicBezier<T>& r, float t)
|
||||
{
|
||||
T q1 = l.getPosition() + t * (l.getControlPointOut() - l.getPosition());
|
||||
T q2 = l.getControlPointOut() + t * (r.getControlPointIn() - l.getControlPointOut());
|
||||
T q3 = r.getControlPointIn() + t * (r.getPosition() - r.getControlPointIn());
|
||||
|
||||
T r1 = q1 + t * (q2 - q1);
|
||||
T r2 = q2 + t * (q3 - q2);
|
||||
|
||||
T s = r1 + t * (r2 - r1);
|
||||
|
||||
n.setControlPointIn(r1);
|
||||
|
||||
n.setPosition(s);
|
||||
|
||||
n.setControlPointOut(r2);
|
||||
|
||||
l.setControlPointOut(q1);
|
||||
|
||||
r.setControlPointIn(q3);
|
||||
}
|
||||
|
||||
void mergeKeyframeContainers(osgAnimation::Vec3CubicBezierKeyframeContainer* to,
|
||||
osgAnimation::FloatCubicBezierKeyframeContainer** from,
|
||||
daeReader::InterpolationType interpolationType)
|
||||
{
|
||||
assert(to->empty());
|
||||
|
||||
typedef std::set<float> TimeSet;
|
||||
TimeSet times;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (!from[i] || from[i]->empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (osgAnimation::FloatCubicBezierKeyframeContainer::const_iterator
|
||||
it = from[i]->begin(), end = from[i]->end(); it != end; ++it)
|
||||
{
|
||||
times.insert(it->getTime());
|
||||
}
|
||||
}
|
||||
|
||||
for (TimeSet::const_iterator it = times.begin(), end = times.end(); it != end; ++it)
|
||||
{
|
||||
const float time = *it;
|
||||
|
||||
osgAnimation::Vec3CubicBezier value;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (!from[i] || from[i]->empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
osgAnimation::FloatCubicBezierKeyframeContainer::iterator next =
|
||||
std::lower_bound(from[i]->begin(), from[i]->end(), time, KeyFrameComparator());
|
||||
if (next == from[i]->end())
|
||||
{
|
||||
--next;
|
||||
value.getPosition().ptr()[i] = next->getValue().getPosition();
|
||||
value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn();
|
||||
value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut();
|
||||
}
|
||||
else if (next == from[i]->begin() || next->getTime() == time)
|
||||
{
|
||||
value.getPosition().ptr()[i] = next->getValue().getPosition();
|
||||
value.getControlPointIn().ptr()[i] = next->getValue().getControlPointIn();
|
||||
value.getControlPointOut().ptr()[i] = next->getValue().getControlPointOut();
|
||||
}
|
||||
else
|
||||
{
|
||||
osgAnimation::FloatCubicBezierKeyframeContainer::iterator prev = next;
|
||||
--prev;
|
||||
|
||||
switch (interpolationType)
|
||||
{
|
||||
case daeReader::INTERPOLATION_STEP:
|
||||
value.getPosition().ptr()[i] = prev->getValue().getPosition();
|
||||
break;
|
||||
case daeReader::INTERPOLATION_LINEAR:
|
||||
{
|
||||
float xp = prev->getTime(), xn = next->getTime();
|
||||
float yp = prev->getValue().getPosition(), yn = next->getValue().getPosition();
|
||||
value.getPosition().ptr()[i] = yp + (yn - yp) * (time - xp) / (xn - xp);
|
||||
}
|
||||
break;
|
||||
case daeReader::INTERPOLATION_BEZIER:
|
||||
{
|
||||
float xp = prev->getTime(), xn = next->getTime();
|
||||
|
||||
osgAnimation::FloatCubicBezier l(prev->getValue()), n, r(next->getValue());
|
||||
deCasteljau(l, n, r, (time - xp) / (xn - xp));
|
||||
|
||||
value.getPosition().ptr()[i] = n.getPosition();
|
||||
value.getControlPointIn().ptr()[i] = n.getControlPointIn();
|
||||
value.getControlPointOut().ptr()[i] = n.getControlPointOut();
|
||||
|
||||
osgAnimation::Vec3CubicBezier prevValue = to->back().getValue();
|
||||
prevValue.getControlPointOut().ptr()[i] = l.getControlPointOut();
|
||||
to->back().setValue(prevValue);
|
||||
|
||||
prev->setValue(l);
|
||||
next->setValue(r);
|
||||
from[i]->insert(next, osgAnimation::FloatCubicBezierKeyframe(time, n));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
osg::notify(osg::WARN) << "Unsupported interpolation type." << std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
//todo - different types of interpolation
|
||||
}
|
||||
}
|
||||
|
||||
to->push_back(osgAnimation::Vec3CubicBezierKeyframe(time, value));
|
||||
}
|
||||
}
|
||||
|
||||
void daeReader::processAnimationChannels(
|
||||
domAnimation* pDomAnimation, TargetChannelPartMap& tcm)
|
||||
{
|
||||
// 1..* <source>
|
||||
SourceMap sources;
|
||||
domSource_Array domSources = pDomAnimation->getSource_array();
|
||||
for (size_t i=0; i < domSources.getCount(); i++)
|
||||
{
|
||||
sources.insert(std::make_pair((daeElement*)domSources[i], domSourceReader(domSources[i])));
|
||||
}
|
||||
|
||||
domChannel_Array domChannels = pDomAnimation->getChannel_array();
|
||||
for (size_t i=0; i < domChannels.getCount(); i++)
|
||||
{
|
||||
processChannel(domChannels[i], sources, tcm);
|
||||
}
|
||||
|
||||
domAnimation_Array domAnimations = pDomAnimation->getAnimation_array();
|
||||
for (size_t i=0; i < domAnimations.getCount(); i++)
|
||||
{
|
||||
// recursively call
|
||||
processAnimationChannels(domAnimations[i], tcm);
|
||||
}
|
||||
}
|
||||
|
||||
osgAnimation::Vec3KeyframeContainer* convertKeyframeContainerToLinear(osgAnimation::Vec3CubicBezierKeyframeContainer& from)
|
||||
{
|
||||
osgAnimation::Vec3KeyframeContainer* linearKeyframes = new osgAnimation::Vec3KeyframeContainer;
|
||||
for (size_t i = 0; i < from.size(); ++i)
|
||||
{
|
||||
linearKeyframes->push_back(osgAnimation::Vec3Keyframe(
|
||||
from[i].getTime(), from[i].getValue().getPosition()));
|
||||
}
|
||||
return linearKeyframes;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void convertHermiteToBezier(osgAnimation::TemplateKeyframeContainer<T>& keyframes)
|
||||
{
|
||||
for (size_t i = 0; i < keyframes.size(); ++i)
|
||||
{
|
||||
T val = keyframes[i].getValue();
|
||||
val.setControlPointIn(val.getControlPointIn() / 3.0f + val.getPosition());
|
||||
val.setControlPointOut(val.getControlPointOut() / -3.0f + val.getPosition());
|
||||
keyframes[i].setValue(val);
|
||||
}
|
||||
}
|
||||
|
||||
// osgAnimation requires control points to be in a weird order. This function
|
||||
// reorders them from the conventional order to osgAnimation order.
|
||||
template <typename T>
|
||||
void reorderControlPoints(osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >& vkfCont)
|
||||
{
|
||||
if (vkfCont.size() <= 1)
|
||||
{
|
||||
if (vkfCont.size() == 1)
|
||||
{
|
||||
osgAnimation::TemplateCubicBezier<T> tcb = vkfCont.front().getValue();
|
||||
T inCP = tcb.getControlPointIn();
|
||||
tcb.setControlPointIn(tcb.getControlPointOut());
|
||||
tcb.setControlPointOut(inCP);
|
||||
vkfCont.front().setValue(tcb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
osgAnimation::TemplateCubicBezier<T> first = vkfCont.front().getValue();
|
||||
|
||||
for (unsigned i = 0; i < vkfCont.size() - 1; ++i)
|
||||
{
|
||||
osgAnimation::TemplateCubicBezier<T> tcb = vkfCont[i].getValue();
|
||||
tcb.setControlPointIn(tcb.getControlPointOut());
|
||||
tcb.setControlPointOut(vkfCont[i + 1].getValue().getControlPointIn());
|
||||
vkfCont[i].setValue(tcb);
|
||||
}
|
||||
|
||||
osgAnimation::TemplateCubicBezier<T> last = vkfCont.back().getValue();
|
||||
last.setControlPointIn(last.getControlPointOut());
|
||||
last.setControlPointOut(first.getControlPointIn());
|
||||
vkfCont.back().setValue(last);
|
||||
}
|
||||
|
||||
// <animation (id) (name)>
|
||||
// 0..1 <asset>
|
||||
// option 1
|
||||
// 1..* <source>
|
||||
// one of (<sampler>, <channel>, <animation>) or <animation> (see below)
|
||||
// option 2
|
||||
// 1..* <source>
|
||||
// 1..* <sampler>
|
||||
// 0..* <animation>
|
||||
// option 3
|
||||
// 1..* <animation>
|
||||
// 0..* <extra>
|
||||
void daeReader::processAnimation(domAnimation* pDomAnimation, osgAnimation::Animation* pOsgAnimation)
|
||||
{
|
||||
// in an <animation>, you can have either a child <animation> and/or a <sampler> and <channel>
|
||||
domSampler_Array domSamplers = pDomAnimation->getSampler_array();
|
||||
domAnimation_Array domAnimations = pDomAnimation->getAnimation_array();
|
||||
|
||||
TargetChannelPartMap tcm;
|
||||
processAnimationChannels(pDomAnimation, tcm);
|
||||
|
||||
for (TargetChannelPartMap::iterator lb = tcm.begin(), end = tcm.end(); lb != end;)
|
||||
{
|
||||
TargetChannelPartMap::iterator ub = tcm.upper_bound(lb->first);
|
||||
|
||||
osgAnimation::Channel* pOsgAnimationChannel = NULL;
|
||||
std::string channelName, targetName, componentName;
|
||||
|
||||
if (dynamic_cast<osgAnimation::Vec3Target*>(lb->first))
|
||||
{
|
||||
osgAnimation::FloatCubicBezierKeyframeContainer* fkfConts[3] = {NULL, NULL, NULL};
|
||||
osgAnimation::Vec3CubicBezierKeyframeContainer* vkfCont = NULL;
|
||||
InterpolationType interpolationType = INTERPOLATION_DEFAULT;
|
||||
|
||||
for (TargetChannelPartMap::iterator it = lb; it != ub; ++it)
|
||||
{
|
||||
ChannelPart* channelPart = it->second.get();
|
||||
extractTargetName(channelPart->name, channelName, targetName, componentName);
|
||||
interpolationType = channelPart->interpolation;
|
||||
|
||||
if (osgAnimation::Vec3CubicBezierKeyframeContainer* v3cnt = dynamic_cast<osgAnimation::Vec3CubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
|
||||
{
|
||||
vkfCont = v3cnt;
|
||||
break;
|
||||
}
|
||||
else if (osgAnimation::FloatCubicBezierKeyframeContainer* fcnt = dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
|
||||
{
|
||||
if (strchr("xusr0", tolower(componentName[0])))
|
||||
{
|
||||
fkfConts[0] = fcnt;
|
||||
}
|
||||
else if (strchr("yvtg1", tolower(componentName[0])))
|
||||
{
|
||||
fkfConts[1] = fcnt;
|
||||
}
|
||||
else if (strchr("zpb2", tolower(componentName[0])))
|
||||
{
|
||||
fkfConts[2] = fcnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unrecognised vector component \"" << componentName << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unrecognised keyframe container \"" << channelPart->name << "\"" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pOsgAnimationChannel && (fkfConts[0] || fkfConts[1] || fkfConts[2]))
|
||||
{
|
||||
vkfCont = new osgAnimation::Vec3CubicBezierKeyframeContainer;
|
||||
mergeKeyframeContainers(vkfCont, fkfConts, interpolationType);
|
||||
}
|
||||
|
||||
if (vkfCont)
|
||||
{
|
||||
if (interpolationType == INTERPOLATION_STEP)
|
||||
{
|
||||
osgAnimation::Vec3StepChannel* channel = new osgAnimation::Vec3StepChannel;
|
||||
pOsgAnimationChannel = channel;
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(convertKeyframeContainerToLinear(*vkfCont));
|
||||
}
|
||||
else if (interpolationType == INTERPOLATION_LINEAR)
|
||||
{
|
||||
osgAnimation::Vec3LinearChannel* channel = new osgAnimation::Vec3LinearChannel;
|
||||
pOsgAnimationChannel = channel;
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(convertKeyframeContainerToLinear(*vkfCont));
|
||||
}
|
||||
else if (interpolationType == INTERPOLATION_BEZIER)
|
||||
{
|
||||
osgAnimation::Vec3CubicBezierChannel* channel = new osgAnimation::Vec3CubicBezierChannel;
|
||||
pOsgAnimationChannel = channel;
|
||||
reorderControlPoints(*vkfCont);
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(vkfCont);
|
||||
}
|
||||
else if (interpolationType == INTERPOLATION_HERMITE)
|
||||
{
|
||||
osgAnimation::Vec3CubicBezierChannel* channel = new osgAnimation::Vec3CubicBezierChannel;
|
||||
pOsgAnimationChannel = channel;
|
||||
convertHermiteToBezier(*vkfCont);
|
||||
reorderControlPoints(*vkfCont);
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(vkfCont);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unsupported interpolation type" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ChannelPart* channelPart = lb->second.get();
|
||||
extractTargetName(channelPart->name, channelName, targetName, componentName);
|
||||
|
||||
typedef osgAnimation::TemplateKeyframe<osgAnimation::TemplateCubicBezier<osg::Matrixf> > MatrixCubicBezierKeyframe;
|
||||
typedef osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<osg::Matrixf> > MatrixCubicBezierKeyframeContainer;
|
||||
|
||||
if (osgAnimation::FloatCubicBezierKeyframeContainer* kfCntr =
|
||||
dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
|
||||
{
|
||||
if (dynamic_cast<osgAnimation::MatrixTarget*>(lb->first))
|
||||
{
|
||||
osg::notify(osg::WARN) << "Animating elements of matrices not supported." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
osgAnimation::FloatCubicBezierChannel* channel = new osgAnimation::FloatCubicBezierChannel;
|
||||
reorderControlPoints(*kfCntr);
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(kfCntr);
|
||||
pOsgAnimationChannel = channel;
|
||||
}
|
||||
}
|
||||
else if (MatrixCubicBezierKeyframeContainer* cbkfCntr =
|
||||
dynamic_cast<MatrixCubicBezierKeyframeContainer*>(channelPart->keyframes.get()))
|
||||
{
|
||||
osgAnimation::MatrixKeyframeContainer* kfCntr = new osgAnimation::MatrixKeyframeContainer;
|
||||
for (size_t i = 0; i < cbkfCntr->size(); ++i)
|
||||
{
|
||||
const MatrixCubicBezierKeyframe& cbkf = cbkfCntr->at(i);
|
||||
kfCntr->push_back(osgAnimation::MatrixKeyframe(cbkf.getTime(), cbkf.getValue().getPosition()));
|
||||
}
|
||||
osgAnimation::MatrixLinearChannel* channel = new osgAnimation::MatrixLinearChannel;
|
||||
channel->getOrCreateSampler()->setKeyframeContainer(kfCntr);
|
||||
pOsgAnimationChannel = channel;
|
||||
}
|
||||
}
|
||||
|
||||
if (pOsgAnimationChannel)
|
||||
{
|
||||
pOsgAnimationChannel->setTargetName(targetName);
|
||||
pOsgAnimationChannel->setName(channelName);
|
||||
pOsgAnimation->addChannel(pOsgAnimationChannel);
|
||||
}
|
||||
lb = ub;
|
||||
}
|
||||
|
||||
pOsgAnimation->computeDuration();
|
||||
}
|
||||
|
||||
template <typename T, typename TArray>
|
||||
osgAnimation::KeyframeContainer* makeKeyframes(
|
||||
const osg::FloatArray* pOsgTimesArray,
|
||||
TArray* pOsgPointArray,
|
||||
TArray* pOsgInTanArray,
|
||||
TArray* pOsgOutTanArray,
|
||||
daeReader::InterpolationType& interpolationType)
|
||||
{
|
||||
osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >* keyframes =
|
||||
new osgAnimation::TemplateKeyframeContainer<osgAnimation::TemplateCubicBezier<T> >;
|
||||
|
||||
for (size_t i = 0; i < pOsgTimesArray->size(); i++)
|
||||
{
|
||||
T pt = (*pOsgPointArray)[i];
|
||||
T cpIn = pt, cpOut = pt;
|
||||
if (pOsgInTanArray)
|
||||
{
|
||||
if (interpolationType == daeReader::INTERPOLATION_HERMITE)
|
||||
//convert from hermite to bezier
|
||||
cpIn += (*pOsgInTanArray)[i] / 3;
|
||||
else if (interpolationType == daeReader::INTERPOLATION_BEZIER)
|
||||
cpIn = (*pOsgInTanArray)[i];
|
||||
}
|
||||
if (pOsgOutTanArray)
|
||||
{
|
||||
if (interpolationType == daeReader::INTERPOLATION_HERMITE)
|
||||
//convert from hermite to bezier
|
||||
cpOut += (*pOsgOutTanArray)[i] / 3;
|
||||
else if (interpolationType == daeReader::INTERPOLATION_BEZIER)
|
||||
cpOut = (*pOsgOutTanArray)[i];
|
||||
}
|
||||
|
||||
keyframes->push_back(
|
||||
osgAnimation::TemplateKeyframe<osgAnimation::TemplateCubicBezier<T> >(
|
||||
(*pOsgTimesArray)[i],
|
||||
osgAnimation::TemplateCubicBezier<T>(pt, cpIn, cpOut)));
|
||||
}
|
||||
|
||||
if (interpolationType == daeReader::INTERPOLATION_HERMITE)
|
||||
{
|
||||
interpolationType = daeReader::INTERPOLATION_BEZIER;
|
||||
}
|
||||
|
||||
return keyframes;
|
||||
}
|
||||
|
||||
// Sampler tells how to use the sources to generate an animated value.
|
||||
// <sampler (id)>
|
||||
// 1..* <input>
|
||||
// 1 semantic
|
||||
// 1 source
|
||||
daeReader::ChannelPart* daeReader::processSampler(domChannel* pDomChannel, SourceMap &sources)
|
||||
{
|
||||
// And we finally define our channel
|
||||
// Note osg can only create time based animations
|
||||
|
||||
//from the channel you know the target, from the target you know the type
|
||||
domSampler *pDomSampler = daeSafeCast<domSampler>(getElementFromURI(pDomChannel->getSource()));
|
||||
if (!pDomSampler)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
domInputLocal_Array domInputArray = pDomSampler->getInput_array();
|
||||
|
||||
daeElement* input_source = NULL;
|
||||
daeElement* output_source = NULL;
|
||||
daeElement* output_intangent_source = NULL;
|
||||
daeElement* output_outtangent_source = NULL;
|
||||
domInputLocal *tmp;
|
||||
|
||||
osg::FloatArray* pOsgTimesArray = NULL;
|
||||
if (findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_INPUT, input_source, &tmp))
|
||||
{
|
||||
domSource* pDomSource = daeSafeCast<domSource>(input_source);
|
||||
if (pDomSource)
|
||||
{
|
||||
domSource::domTechnique_common* pDomTechnique = pDomSource->getTechnique_common();
|
||||
if (pDomTechnique)
|
||||
{
|
||||
domAccessor* pDomAccessor = pDomTechnique->getAccessor();
|
||||
domParam_Array domParams = pDomAccessor->getParam_array();
|
||||
if (domParams.getCount() > 0)
|
||||
{
|
||||
if (!strcmp("TIME", domParams[0]->getName()))
|
||||
{
|
||||
pOsgTimesArray = sources[input_source].getFloatArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Only TIME based animations are supported" <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "No params in accessor" <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unable to find <technique_common> in <source> " << pDomSource->getName() <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not get animation 'INPUT' source"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_OUTPUT, output_source, &tmp);
|
||||
findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_IN_TANGENT, output_intangent_source, &tmp);
|
||||
findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_OUT_TANGENT, output_outtangent_source, &tmp);
|
||||
domSourceReader::ArrayType arrayType = sources[output_source].getArrayType();
|
||||
|
||||
struct InterpTypeName
|
||||
{
|
||||
InterpolationType interp;
|
||||
const char* str;
|
||||
};
|
||||
|
||||
InterpTypeName interpTypeNames[] = {
|
||||
{INTERPOLATION_STEP, "STEP"},
|
||||
{INTERPOLATION_LINEAR, "LINEAR"},
|
||||
{INTERPOLATION_BEZIER, "BEZIER"},
|
||||
{INTERPOLATION_HERMITE, "HERMITE"},
|
||||
{INTERPOLATION_CARDINAL, "CARDINAL"},
|
||||
{INTERPOLATION_BSPLINE, "BSPLINE"}
|
||||
};
|
||||
const int interpTypeCount = sizeof(interpTypeNames) / sizeof(*interpTypeNames);
|
||||
|
||||
// TODO multiple outputs may be possible?
|
||||
|
||||
InterpolationType interpolationType = INTERPOLATION_DEFAULT;
|
||||
|
||||
if (findInputSourceBySemantic(domInputArray, COMMON_PROFILE_INPUT_INTERPOLATION, input_source, &tmp))
|
||||
{
|
||||
domSource* pDomSource = daeSafeCast<domSource>(input_source);
|
||||
if (pDomSource)
|
||||
{
|
||||
domName_array* pDomNames = pDomSource->getName_array();
|
||||
if (pDomNames)
|
||||
{
|
||||
daeStringArray* stringArray = &(pDomNames->getValue());
|
||||
|
||||
// Take a look at the first element in the array to see what kind of interpolation is needed
|
||||
// multiple interpolation types inside an animation is not supported
|
||||
if (stringArray->getCount() > 0)
|
||||
{
|
||||
// Collada interpolation types
|
||||
for (int i = 0; i < interpTypeCount; ++i)
|
||||
{
|
||||
if (!strcmp(interpTypeNames[i].str, (*stringArray)[0]))
|
||||
{
|
||||
interpolationType = interpTypeNames[i].interp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "No names in <Name_array>" <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unable to find <Name_array> in <source> " << pDomSource->getName() <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not get animation 'INPUT' source"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//work around for files output by the Autodesk FBX converter.
|
||||
if (interpolationType == INTERPOLATION_BEZIER &&
|
||||
_authoringTool == FBX_CONVERTER ||
|
||||
_authoringTool == MAYA)
|
||||
{
|
||||
interpolationType = INTERPOLATION_HERMITE;
|
||||
}
|
||||
|
||||
osgAnimation::KeyframeContainer* keyframes = NULL;
|
||||
|
||||
switch (arrayType)
|
||||
{
|
||||
case domSourceReader::Float:
|
||||
keyframes = makeKeyframes<float>(pOsgTimesArray,
|
||||
sources[output_source].getFloatArray(),
|
||||
sources[output_intangent_source].getFloatArray(),
|
||||
sources[output_outtangent_source].getFloatArray(),
|
||||
interpolationType);
|
||||
break;
|
||||
case domSourceReader::Vec2:
|
||||
keyframes = makeKeyframes<osg::Vec2>(pOsgTimesArray,
|
||||
sources[output_source].getVec2Array(),
|
||||
sources[output_intangent_source].getVec2Array(),
|
||||
sources[output_outtangent_source].getVec2Array(),
|
||||
interpolationType);
|
||||
break;
|
||||
case domSourceReader::Vec3:
|
||||
keyframes = makeKeyframes<osg::Vec3>(pOsgTimesArray,
|
||||
sources[output_source].getVec3Array(),
|
||||
sources[output_intangent_source].getVec3Array(),
|
||||
sources[output_outtangent_source].getVec3Array(),
|
||||
interpolationType);
|
||||
break;
|
||||
case domSourceReader::Vec4:
|
||||
keyframes = makeKeyframes<osg::Vec4>(pOsgTimesArray,
|
||||
sources[output_source].getVec4Array(),
|
||||
sources[output_intangent_source].getVec4Array(),
|
||||
sources[output_outtangent_source].getVec4Array(),
|
||||
interpolationType);
|
||||
break;
|
||||
case domSourceReader::Matrix:
|
||||
keyframes = makeKeyframes<osg::Matrixf>(pOsgTimesArray,
|
||||
sources[output_source].getMatrixArray(),
|
||||
sources[output_intangent_source].getMatrixArray(),
|
||||
sources[output_outtangent_source].getMatrixArray(),
|
||||
interpolationType);
|
||||
break;
|
||||
}
|
||||
|
||||
if (keyframes)
|
||||
{
|
||||
ChannelPart* chanPart = new ChannelPart;
|
||||
chanPart->keyframes = keyframes;
|
||||
chanPart->interpolation = interpolationType;
|
||||
chanPart->name = pDomChannel->getTarget();
|
||||
return chanPart;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
osgAnimation::Target* findChannelTarget(osg::NodeCallback* nc, const std::string& targetName, bool& rotation)
|
||||
{
|
||||
if (osgAnimation::UpdateMatrixTransform* umt = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(nc))
|
||||
{
|
||||
for (osgAnimation::StackedTransform::const_iterator
|
||||
it = umt->getStackedTransforms().begin(), end = umt->getStackedTransforms().end(); it != end; ++it)
|
||||
{
|
||||
osgAnimation::StackedTransformElement* te = it->get();
|
||||
if (te->getName() == targetName)
|
||||
{
|
||||
rotation = dynamic_cast<osgAnimation::StackedRotateAxisElement*>(te) != NULL;
|
||||
return te->getOrCreateTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!dynamic_cast<osgAnimation::UpdateMorph*>(nc))
|
||||
{
|
||||
osg::notify(osg::WARN) << "Unrecognised AnimationUpdateCallback" << std::endl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void convertDegreesToRadians(osgAnimation::KeyframeContainer* pKeyframeContainer)
|
||||
{
|
||||
if (osgAnimation::FloatKeyframeContainer* fkc =
|
||||
dynamic_cast<osgAnimation::FloatKeyframeContainer*>(pKeyframeContainer))
|
||||
{
|
||||
for (size_t i = 0; i < fkc->size(); ++i)
|
||||
{
|
||||
osgAnimation::FloatKeyframe& fk = (*fkc)[i];
|
||||
fk.setValue(osg::DegreesToRadians(fk.getValue()));
|
||||
}
|
||||
}
|
||||
else if (osgAnimation::FloatCubicBezierKeyframeContainer* fcbkc =
|
||||
dynamic_cast<osgAnimation::FloatCubicBezierKeyframeContainer*>(pKeyframeContainer))
|
||||
{
|
||||
for (size_t i = 0; i < fcbkc->size(); ++i)
|
||||
{
|
||||
osgAnimation::FloatCubicBezierKeyframe& fcbk = (*fcbkc)[i];
|
||||
osgAnimation::FloatCubicBezier fcb = fcbk.getValue();
|
||||
fcb.setPosition(osg::DegreesToRadians(fcb.getPosition()));
|
||||
fcb.setControlPointIn(osg::DegreesToRadians(fcb.getControlPointIn()));
|
||||
fcb.setControlPointOut(osg::DegreesToRadians(fcb.getControlPointOut()));
|
||||
fcbk.setValue(fcb);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Warning: rotation keyframes not converted to radians." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Channel connects animation output to parameter to animate
|
||||
// <channel>
|
||||
// 1 source
|
||||
// 1 target
|
||||
void daeReader::processChannel(domChannel* pDomChannel, SourceMap& sources, TargetChannelPartMap& tcm)
|
||||
{
|
||||
domSampler *pDomSampler = daeSafeCast<domSampler>(getElementFromURI(pDomChannel->getSource()));
|
||||
if (pDomSampler)
|
||||
{
|
||||
ChannelPart* pChannelPart = processSampler(pDomChannel, sources);
|
||||
|
||||
if (pChannelPart)
|
||||
{
|
||||
domChannelOsgAnimationUpdateCallbackMap::iterator iter = _domChannelOsgAnimationUpdateCallbackMap.find(pDomChannel);
|
||||
if (iter != _domChannelOsgAnimationUpdateCallbackMap.end())
|
||||
{
|
||||
osg::NodeCallback* nc = iter->second.get();
|
||||
|
||||
std::string channelName, targetName, componentName;
|
||||
extractTargetName(pDomChannel->getTarget(), channelName, targetName, componentName);
|
||||
//assert(targetName == nc->getName());
|
||||
bool bRotationChannel = false;
|
||||
if (osgAnimation::Target* pTarget = findChannelTarget(nc, channelName, bRotationChannel))
|
||||
{
|
||||
if (bRotationChannel)
|
||||
{
|
||||
convertDegreesToRadians(pChannelPart->keyframes.get());
|
||||
}
|
||||
tcm.insert(TargetChannelPartMap::value_type(pTarget, pChannelPart));
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Target \"" << channelName << "\" not found." << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Could not locate UpdateCallback for <channel> target " << pDomChannel->getTarget()<< std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "<channel> source " << pDomChannel->getSource().getURI() << " has no corresponding osgAnimation::Channel" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not locate <channel> source " << pDomChannel->getSource().getURI() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void daeReader::extractTargetName(const std::string& daeTarget, std::string& channelName, std::string& targetName, std::string& component)
|
||||
{
|
||||
size_t slash = daeTarget.find_last_of("/");
|
||||
if (slash != std::string::npos)
|
||||
{
|
||||
// Handle /translation
|
||||
targetName = daeTarget.substr(0, slash);
|
||||
channelName = daeTarget.substr(slash+1, std::string::npos);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t parenthesis = daeTarget.find_last_of("(");
|
||||
size_t endpos = daeTarget.find_last_of(")");
|
||||
if (parenthesis != std::string::npos && endpos != std::string::npos)
|
||||
{
|
||||
// Handle (1)
|
||||
targetName = daeTarget.substr(0, parenthesis);
|
||||
channelName = daeTarget.substr(parenthesis+1, endpos - parenthesis - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "Couldn't extract a proper name for <channel> target " << daeTarget << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
size_t period = channelName.find_last_of(".");
|
||||
if (period != std::string::npos)
|
||||
{
|
||||
component = channelName.substr(period+1, std::string::npos);
|
||||
channelName = channelName.substr(0, period);
|
||||
}
|
||||
else
|
||||
{
|
||||
component.clear();
|
||||
|
||||
size_t first_parenthesis = channelName.find_first_of("(");
|
||||
if (first_parenthesis != std::string::npos)
|
||||
{
|
||||
size_t open_parenthesis = first_parenthesis;
|
||||
|
||||
do
|
||||
{
|
||||
if (open_parenthesis != first_parenthesis) component += ",";
|
||||
|
||||
size_t close_parenthesis = channelName.find_first_of(")", open_parenthesis);
|
||||
component += channelName.substr(open_parenthesis+1, close_parenthesis-open_parenthesis-1);
|
||||
open_parenthesis = channelName.find_first_of("(", close_parenthesis);
|
||||
}
|
||||
while (open_parenthesis != std::string::npos);
|
||||
|
||||
channelName = channelName.substr(0, first_parenthesis);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -27,9 +27,9 @@
|
||||
#include <osg/CameraView>
|
||||
#include <osg/LightModel>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
osg::Node* daeReader::processOsgMultiSwitch(domTechnique* teq)
|
||||
osg::Group* daeReader::processOsgMultiSwitch(domTechnique* teq)
|
||||
{
|
||||
osgSim::MultiSwitch* msw = new osgSim::MultiSwitch;
|
||||
|
||||
@@ -86,7 +86,7 @@ osg::Node* daeReader::processOsgMultiSwitch(domTechnique* teq)
|
||||
return msw;
|
||||
}
|
||||
|
||||
osg::Node* daeReader::processOsgSwitch(domTechnique* teq)
|
||||
osg::Group* daeReader::processOsgSwitch(domTechnique* teq)
|
||||
{
|
||||
osg::Switch* sw = new osg::Switch;
|
||||
|
||||
@@ -112,7 +112,7 @@ osg::Node* daeReader::processOsgSwitch(domTechnique* teq)
|
||||
return sw;
|
||||
}
|
||||
|
||||
osg::Node* daeReader::processOsgSequence(domTechnique* teq)
|
||||
osg::Group* daeReader::processOsgSequence(domTechnique* teq)
|
||||
{
|
||||
osg::Sequence* sq = new osg::Sequence;
|
||||
|
||||
@@ -219,7 +219,7 @@ osg::Node* daeReader::processOsgSequence(domTechnique* teq)
|
||||
}
|
||||
|
||||
|
||||
osg::Node* daeReader::processOsgLOD(domTechnique* teq)
|
||||
osg::Group* daeReader::processOsgLOD(domTechnique* teq)
|
||||
{
|
||||
osg::LOD* lod = new osg::LOD;
|
||||
|
||||
@@ -323,7 +323,7 @@ osg::Node* daeReader::processOsgLOD(domTechnique* teq)
|
||||
// 0..* <extra>
|
||||
osg::Node* daeReader::processLight( domLight *dlight )
|
||||
{
|
||||
if (m_numlights >= 7)
|
||||
if (_numlights >= 7)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "More than 8 lights may not be supported by OpenGL driver." << std::endl;
|
||||
}
|
||||
@@ -343,12 +343,12 @@ osg::Node* daeReader::processLight( domLight *dlight )
|
||||
|
||||
osg::Light* light = new osg::Light();
|
||||
light->setPosition(osg::Vec4(0,0,0,1));
|
||||
light->setLightNum(m_numlights);
|
||||
light->setLightNum(_numlights);
|
||||
|
||||
// Enable OpenGL lighting
|
||||
_rootStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
|
||||
// Enable this OpenGL light
|
||||
_rootStateSet->setMode(GL_LIGHT0 + m_numlights++, osg::StateAttribute::ON);
|
||||
_rootStateSet->setMode(GL_LIGHT0 + _numlights++, osg::StateAttribute::ON);
|
||||
|
||||
// Set ambient of lightmodel to zero
|
||||
// Ambient lights are added as separate lights with only an ambient term
|
||||
|
||||
533
src/osgPlugins/dae/daeRSkinning.cpp
Normal file
533
src/osgPlugins/dae/daeRSkinning.cpp
Normal file
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* 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 <dom/domInstanceWithExtra.h>
|
||||
#include <dom/domConstants.h>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
|
||||
using namespace osgDAE;
|
||||
|
||||
domNode* daeReader::getRootJoint(domNode* joint) const
|
||||
{
|
||||
int depth = 0;
|
||||
while (domNode* parent = daeSafeCast<domNode>(joint->getParent()))
|
||||
{
|
||||
if (isJoint(parent))
|
||||
{
|
||||
joint = parent;
|
||||
++depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return joint;
|
||||
}
|
||||
|
||||
domNode* daeReader::findJointNode(daeElement* searchFrom, domInstance_controller* pDomInstanceController) const
|
||||
{
|
||||
domController *pDomController = daeSafeCast<domController>(getElementFromURI(pDomInstanceController->getUrl()));
|
||||
domSkin::domJoints* pDomSkinJoints = pDomController->getSkin()->getJoints();
|
||||
|
||||
domInputLocal_Array domInputs = pDomSkinJoints->getInput_array();
|
||||
|
||||
domSource* pDomJointsSource = NULL;
|
||||
for (size_t i=0; i < domInputs.getCount(); i++)
|
||||
{
|
||||
if (!strcmp(domInputs[i]->getSemantic(), COMMON_PROFILE_INPUT_JOINT))
|
||||
{
|
||||
pDomJointsSource = daeSafeCast<domSource>(getElementFromURI(domInputs[i]->getSource()));
|
||||
if (!pDomJointsSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin joints source '" << domInputs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (domIDREF_array* pDomIDREFs = pDomJointsSource->getIDREF_array())
|
||||
{
|
||||
if (pDomIDREFs->getCount())
|
||||
{
|
||||
return daeSafeCast< domNode >(getElementFromIDRef(pDomIDREFs->getValue().get(0)));
|
||||
}
|
||||
}
|
||||
else if (domName_array* pDomNames = pDomJointsSource->getName_array())
|
||||
{
|
||||
if (pDomNames->getCount())
|
||||
{
|
||||
daeString target = pDomNames->getValue().get(0);
|
||||
daeSIDResolver resolver(searchFrom, target);
|
||||
return daeSafeCast<domNode>(resolver.getElement());
|
||||
}
|
||||
}
|
||||
|
||||
osg::notify( osg::WARN ) << "No valid names or IDREFS array in <skin>" <<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
domNode* daeReader::findSkeletonNode(daeElement* searchFrom, domInstance_controller* pDomInstanceController) const
|
||||
{
|
||||
domNode* pDomNode = findJointNode(searchFrom, pDomInstanceController);
|
||||
|
||||
if (!pDomNode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return getRootJoint(pDomNode);
|
||||
}
|
||||
|
||||
void daeReader::processSkins()
|
||||
{
|
||||
if (_skinInstanceControllers.empty() || _skeletonMap.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
typedef std::map<domNode* /*Skeleton root*/, domInstance_controllerList> SkelSkinMap;
|
||||
SkelSkinMap skelSkinMap;
|
||||
|
||||
//group the skins according to which group of joints they're attached to.
|
||||
for (size_t i = 0; i < _skinInstanceControllers.size(); ++i)
|
||||
{
|
||||
domInstance_controller* pDomInstanceController = _skinInstanceControllers[i];
|
||||
|
||||
const domInstance_controller::domSkeleton_Array& pDomSkeletons =
|
||||
pDomInstanceController->getSkeleton_array();
|
||||
|
||||
if (pDomSkeletons.getCount() == 0)
|
||||
{
|
||||
domNode* skelNode = _skeletonMap.begin()->first;
|
||||
if (skelNode = findSkeletonNode(skelNode, pDomInstanceController))
|
||||
{
|
||||
skelSkinMap[skelNode].push_back(pDomInstanceController);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (daeElement* pDaeElement = pDomSkeletons.get(0)->getValue().getElement())
|
||||
{
|
||||
if (domNode* skelNode = findSkeletonNode(pDaeElement, pDomInstanceController))
|
||||
{
|
||||
skelSkinMap[skelNode].push_back(pDomInstanceController);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (SkelSkinMap::iterator it = skelSkinMap.begin(); it != skelSkinMap.end(); ++it)
|
||||
{
|
||||
processSkeletonSkins(it->first, it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void getJointsAndInverseObjectspaceBindMatrices(domInstance_controller* pDomInstanceController,
|
||||
domNode* pDomSkeletonNode,
|
||||
std::vector<std::pair<domNode*, osg::Matrix> >& jointsAndBindMatrices)
|
||||
{
|
||||
domController* pDomController = daeSafeCast< domController >(getElementFromURI(pDomInstanceController->getUrl()));
|
||||
|
||||
domSkin* pDomSkin = pDomController->getSkin();
|
||||
|
||||
domSkin::domJoints* pDomSkinJoints = pDomSkin->getJoints();
|
||||
domInputLocal_Array domInputs = pDomSkinJoints->getInput_array();
|
||||
|
||||
if (domInputs.getCount() > 2)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Only a single pair of skin joints inputs is supported." << std::endl;
|
||||
}
|
||||
|
||||
domSource* pDomJointsSource = NULL;
|
||||
domSource* pDomInvBindMatricesSource = NULL;
|
||||
for (size_t i=0; i < domInputs.getCount(); i++)
|
||||
{
|
||||
if (!strcmp(domInputs[i]->getSemantic(), COMMON_PROFILE_INPUT_JOINT))
|
||||
{
|
||||
pDomJointsSource = daeSafeCast<domSource>(getElementFromURI(domInputs[i]->getSource()));
|
||||
if (!pDomJointsSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin joints source '" << domInputs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(domInputs[i]->getSemantic(), COMMON_PROFILE_INPUT_INV_BIND_MATRIX))
|
||||
{
|
||||
pDomInvBindMatricesSource = daeSafeCast<domSource>(getElementFromURI(domInputs[i]->getSource()));
|
||||
if (!pDomInvBindMatricesSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin inverse bind matrices source '" << domInputs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
domFloat_array* pDomFloatArray = pDomInvBindMatricesSource->getFloat_array();
|
||||
domListOfFloats matrices = pDomFloatArray->getValue();
|
||||
|
||||
osg::Matrix parentInverseSkeletonBindMatrix;
|
||||
|
||||
if (domIDREF_array* pDomIDREFs = pDomJointsSource->getIDREF_array())
|
||||
{
|
||||
// IDREFS refer to an absolute joint and therefore do not allow a different skeleton
|
||||
xsIDREFS* pIDREFS = &(pDomIDREFs->getValue());
|
||||
for (size_t i=0; i < pIDREFS->getCount(); i++)
|
||||
{
|
||||
domNode* pDomNode = daeSafeCast< domNode >(getElementFromIDRef(pIDREFS->get(i)));
|
||||
|
||||
if (pDomNode)
|
||||
{
|
||||
jointsAndBindMatrices.push_back(std::pair<domNode*, osg::Matrix>(pDomNode, osg::Matrix()));
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Failed to locate joint '" << pIDREFS->get(i).getID() << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (domName_array* pDomNames = pDomJointsSource->getName_array())
|
||||
{
|
||||
// Using a list of names is the preferred way of referring to joints, because
|
||||
// this refers to a joint relative to the given skeletons
|
||||
domListOfNames* pNames = &(pDomNames->getValue());
|
||||
for (size_t i=0; i < pNames->getCount(); i++)
|
||||
{
|
||||
daeSIDResolver resolver(pDomSkeletonNode, pNames->get(i));
|
||||
domNode* pDomNode = daeSafeCast< domNode >(resolver.getElement());
|
||||
|
||||
if (pDomNode)
|
||||
{
|
||||
jointsAndBindMatrices.push_back(std::pair<domNode*, osg::Matrix>(pDomNode, osg::Matrix()));
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Failed to locate joint '" << pNames->get(i) << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "No valid names or IDREFS array in <skin>" <<std::endl;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < jointsAndBindMatrices.size(); ++i)
|
||||
{
|
||||
osg::Matrix invMat(
|
||||
matrices.get(i*16 + 0), matrices.get(i*16 + 4), matrices.get(i*16 + 8), matrices.get(i*16 + 12),
|
||||
matrices.get(i*16 + 1), matrices.get(i*16 + 5), matrices.get(i*16 + 9), matrices.get(i*16 + 13),
|
||||
matrices.get(i*16 + 2), matrices.get(i*16 + 6), matrices.get(i*16 + 10), matrices.get(i*16 + 14),
|
||||
matrices.get(i*16 + 3), matrices.get(i*16 + 7), matrices.get(i*16 + 11), matrices.get(i*16 + 15));
|
||||
jointsAndBindMatrices[i].second = invMat;
|
||||
}
|
||||
}
|
||||
|
||||
void daeReader::processSkeletonSkins(domNode* skeletonRoot, const domInstance_controllerList& instanceControllers)
|
||||
{
|
||||
for (size_t i = 0; i < instanceControllers.size(); ++i)
|
||||
{
|
||||
domInstance_controller* instanceController = instanceControllers[i];
|
||||
|
||||
std::vector<std::pair<domNode*, osg::Matrix> > jointsAndInverseBindMatrices;
|
||||
getJointsAndInverseObjectspaceBindMatrices(instanceController, skeletonRoot, jointsAndInverseBindMatrices);
|
||||
|
||||
for (size_t j = 0; j < jointsAndInverseBindMatrices.size(); ++j)
|
||||
{
|
||||
osgAnimation::Bone* pOsgBone = getOrCreateBone(jointsAndInverseBindMatrices[j].first);
|
||||
pOsgBone->setInvBindMatrixInSkeletonSpace(jointsAndInverseBindMatrices[j].second);
|
||||
}
|
||||
}
|
||||
|
||||
osgAnimation::Skeleton* skeleton = getOrCreateSkeleton(skeletonRoot);
|
||||
|
||||
for (size_t i = 0; i < instanceControllers.size(); ++i)
|
||||
{
|
||||
domInstance_controller *pDomInstanceController = instanceControllers[i];
|
||||
domController *pDomController = daeSafeCast< domController >(getElementFromURI(pDomInstanceController->getUrl()));
|
||||
processSkin(pDomController->getSkin(), skeletonRoot, skeleton, pDomInstanceController->getBind_material());
|
||||
}
|
||||
}
|
||||
|
||||
osgAnimation::VertexInfluence& getVertexInfluence(
|
||||
osgAnimation::VertexInfluenceMap& vim, const std::string& name)
|
||||
{
|
||||
osgAnimation::VertexInfluenceMap::iterator it = vim.lower_bound(name);
|
||||
if (it == vim.end() || name != it->first)
|
||||
{
|
||||
it = vim.insert(it, osgAnimation::VertexInfluenceMap::value_type(
|
||||
name, osgAnimation::VertexInfluence()));
|
||||
it->second.setName(name);
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
// <skin source>
|
||||
// 0..1 <bind_shape_matrix>
|
||||
// 3..* <source>
|
||||
// 1 <joints>
|
||||
// 2..* <input semantic source>
|
||||
// 0..* <extra>
|
||||
// 1 <vertex_weights count>
|
||||
// 2..* <input semantic source>
|
||||
// 0..1 <vcount>
|
||||
// 0..1 <v>
|
||||
// 0.* <extra>
|
||||
// 0..* <extra>
|
||||
void daeReader::processSkin(domSkin* pDomSkin, domNode* skeletonRoot, osgAnimation::Skeleton* pOsgSkeleton, domBind_material* pDomBindMaterial)
|
||||
{
|
||||
daeElement* pDaeSkinSource = getElementFromURI( pDomSkin->getSource());
|
||||
|
||||
if (!pDaeSkinSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Failed to locate geometry " << pDomSkin->getSource().getURI() << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
domGeometry* pDomGeometry = daeSafeCast< domGeometry >(pDaeSkinSource);
|
||||
|
||||
if (!pDomGeometry)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Skin source is of type " << pDaeSkinSource->getTypeName() << " which is not supported." << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Base mesh
|
||||
const osg::Geode* pOriginalGeode = NULL;
|
||||
osg::Geode* pOsgGeode = getOrCreateGeometry(pDomGeometry, pDomBindMaterial, &pOriginalGeode);
|
||||
if (!pOsgGeode)
|
||||
return;
|
||||
|
||||
domMesh* pDomMesh = pDomGeometry->getMesh();
|
||||
|
||||
osg::Geode* pOsgRigGeode = new osg::Geode;
|
||||
pOsgRigGeode->setDataVariance(osg::Object::DYNAMIC);
|
||||
|
||||
typedef std::map<const osg::Geometry*, osgAnimation::RigGeometry*> GeometryRigGeometryMap;
|
||||
GeometryRigGeometryMap old2newGeometryMap;
|
||||
|
||||
for (unsigned i = 0; i < pOsgGeode->getNumDrawables(); ++i)
|
||||
{
|
||||
if (osg::Geometry* pOsgGeometry = dynamic_cast<osg::Geometry*>(pOsgGeode->getDrawable(i)))
|
||||
{
|
||||
const osg::Geometry* pOriginalGeometry = dynamic_cast<const osg::Geometry*>(pOriginalGeode->getDrawable(i));
|
||||
|
||||
osgAnimation::RigGeometry* pOsgRigGeometry = new osgAnimation::RigGeometry();
|
||||
pOsgRigGeometry->setSourceGeometry(pOsgGeometry);
|
||||
pOsgRigGeometry->copyFrom(*pOsgGeometry);
|
||||
old2newGeometryMap.insert(GeometryRigGeometryMap::value_type(pOriginalGeometry, pOsgRigGeometry));
|
||||
pOsgRigGeometry->setDataVariance(osg::Object::DYNAMIC);
|
||||
pOsgRigGeometry->setUseDisplayList( false );
|
||||
pOsgRigGeode->addDrawable(pOsgRigGeometry);
|
||||
}
|
||||
else
|
||||
{
|
||||
pOsgRigGeode->addDrawable(pOsgGeode->getDrawable(i));
|
||||
}
|
||||
}
|
||||
|
||||
pOsgSkeleton->addChild(pOsgRigGeode);
|
||||
|
||||
// <bind_shape_matrix>
|
||||
if (domSkin::domBind_shape_matrix* pDomBindShapeMatrix = pDomSkin->getBind_shape_matrix())
|
||||
{
|
||||
domFloat4x4 matrix = pDomBindShapeMatrix->getValue();
|
||||
osg::Matrix bindMatrix(
|
||||
matrix.get(0), matrix.get(4), matrix.get(8), matrix.get(12),
|
||||
matrix.get(1), matrix.get(5), matrix.get(9), matrix.get(13),
|
||||
matrix.get(2), matrix.get(6), matrix.get(10), matrix.get(14),
|
||||
matrix.get(3), matrix.get(7), matrix.get(11), matrix.get(15));
|
||||
|
||||
for (unsigned d = 0; d < pOsgRigGeode->getNumDrawables(); ++d)
|
||||
{
|
||||
osgAnimation::RigGeometry* pOsgRigGeometry = dynamic_cast<osgAnimation::RigGeometry*>(pOsgRigGeode->getDrawable(d));
|
||||
if (!pOsgRigGeometry)
|
||||
continue;
|
||||
|
||||
osg::Vec3Array& vertices = *static_cast<osg::Vec3Array*>(pOsgRigGeometry->getVertexArray());
|
||||
|
||||
for (size_t i = 0; i < vertices.size(); ++i)
|
||||
{
|
||||
vertices[i] = vertices[i] * bindMatrix;
|
||||
}
|
||||
|
||||
if (osg::Vec3Array* normals = static_cast<osg::Vec3Array*>(pOsgRigGeometry->getNormalArray()))
|
||||
{
|
||||
for (size_t i = 0; i < normals->size(); ++i)
|
||||
{
|
||||
(*normals)[i] = osg::Matrix::transform3x3((*normals)[i], bindMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 1 <vertex_weights count>
|
||||
|
||||
domSkin::domVertex_weights* pDomVertexWeights = pDomSkin->getVertex_weights();
|
||||
domInputLocalOffset_Array domInputs = pDomVertexWeights->getInput_array();
|
||||
|
||||
if (domInputs.getCount() > 2)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Only a single pair of skin vertex weights inputs is supported." << std::endl;
|
||||
}
|
||||
|
||||
domSource* pDomJointsSource = NULL;
|
||||
domSource* pDomWeightsSource = NULL;
|
||||
for (size_t i=0; i < 2; i++)
|
||||
{
|
||||
if (!strcmp(domInputs[i]->getSemantic(), COMMON_PROFILE_INPUT_JOINT))
|
||||
{
|
||||
pDomJointsSource = daeSafeCast<domSource>(getElementFromURI(domInputs[i]->getSource()));
|
||||
if (!pDomJointsSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin joints source '" << domInputs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(domInputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT))
|
||||
{
|
||||
pDomWeightsSource = daeSafeCast<domSource>(getElementFromURI(domInputs[i]->getSource()));
|
||||
if (!pDomWeightsSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin weights source '" << domInputs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
domFloat_array* pDomFloatArray = pDomWeightsSource->getFloat_array();
|
||||
domListOfFloats weights = pDomFloatArray->getValue();
|
||||
|
||||
domSkin::domVertex_weights::domVcount* pDomVcount = pDomVertexWeights->getVcount();
|
||||
domListOfUInts influenceCounts = pDomVcount->getValue();
|
||||
|
||||
domSkin::domVertex_weights::domV* pDomV= pDomVertexWeights->getV();
|
||||
domListOfInts jointWeightIndices = pDomV->getValue();
|
||||
|
||||
std::vector<std::string> jointNames;
|
||||
|
||||
if (domName_array* pDomNames = pDomJointsSource->getName_array())
|
||||
{
|
||||
domListOfNames* pNames = &(pDomNames->getValue());
|
||||
|
||||
jointNames.reserve(pNames->getCount());
|
||||
|
||||
for (size_t i = 0; i < pNames->getCount(); ++i)
|
||||
{
|
||||
const char* szName = pNames->get(i);
|
||||
daeSIDResolver resolver(skeletonRoot, szName);
|
||||
osgAnimation::Bone* pOsgBone = _jointMap[daeSafeCast<domNode>(resolver.getElement())].get();
|
||||
if (pOsgBone)
|
||||
{
|
||||
jointNames.push_back(pOsgBone->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
jointNames.push_back(szName);
|
||||
osg::notify(osg::WARN) << "Cannot find bone " << szName << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (domIDREF_array* pDomIDREFs = pDomJointsSource->getIDREF_array())
|
||||
{
|
||||
xsIDREFS* pIDREFs = &(pDomIDREFs->getValue());
|
||||
|
||||
jointNames.reserve(pIDREFs->getCount());
|
||||
|
||||
for (size_t i = 0; i < pIDREFs->getCount(); ++i)
|
||||
{
|
||||
osgAnimation::Bone* pOsgBone = _jointMap[daeSafeCast<domNode>(pIDREFs->get(i).getElement())].get();
|
||||
if (pOsgBone)
|
||||
{
|
||||
jointNames.push_back(pOsgBone->getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
jointNames.push_back(pIDREFs->get(i).getID());
|
||||
osg::notify(osg::WARN) << "Cannot find bone " << pIDREFs->get(i).getID() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "No valid names or IDREFS array in <skin>" <<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0, vIndex = 0; i < influenceCounts.getCount(); i++)
|
||||
{
|
||||
OldToNewIndexMap::key_type indexID(pDomMesh, i);
|
||||
const OldToNewIndexMap::const_iterator start = _oldToNewIndexMap.find(indexID);
|
||||
|
||||
const size_t nInfluences = influenceCounts[i];
|
||||
|
||||
if (start == _oldToNewIndexMap.end())
|
||||
{
|
||||
vIndex += nInfluences * 2;
|
||||
//this vertex isn't used
|
||||
continue;
|
||||
}
|
||||
|
||||
const OldToNewIndexMap::const_iterator end = _oldToNewIndexMap.upper_bound(indexID);
|
||||
|
||||
for (size_t j = 0; j < nInfluences; ++j)
|
||||
{
|
||||
if (vIndex + 2 > jointWeightIndices.getCount())
|
||||
{
|
||||
osg::notify( osg::WARN ) << "vIndex is larger than number of v values" <<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t jointIndex = jointWeightIndices[vIndex++];
|
||||
size_t weightIndex = jointWeightIndices[vIndex++];
|
||||
|
||||
if (jointIndex >= jointNames.size())
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Joint index is larger the number of joints" <<std::endl;
|
||||
break;
|
||||
}
|
||||
if (weightIndex >= weights.getCount())
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Weight index is larger the number of weights" <<std::endl;
|
||||
break;
|
||||
}
|
||||
|
||||
float weight = weights[weightIndex];
|
||||
if (weight > 0.0f)
|
||||
{
|
||||
const std::string& name = jointNames[jointIndex];
|
||||
|
||||
for (OldToNewIndexMap::const_iterator it = start; it != end; ++it)
|
||||
{
|
||||
osgAnimation::RigGeometry* pRigGeometry = old2newGeometryMap[it->second.first.get()];
|
||||
|
||||
osgAnimation::VertexInfluenceMap* vim = pRigGeometry->getInfluenceMap();
|
||||
if (!vim)
|
||||
{
|
||||
pRigGeometry->setInfluenceMap(vim = new osgAnimation::VertexInfluenceMap);
|
||||
}
|
||||
|
||||
getVertexInfluence(*vim, name).push_back(
|
||||
osgAnimation::VertexIndexWeight(it->second.second, weight));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Copyright 2006 Sony Computer Entertainment Inc.
|
||||
*
|
||||
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
|
||||
* 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.
|
||||
* 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"
|
||||
@@ -16,131 +16,115 @@
|
||||
#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;
|
||||
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 systemfor the parent <node> element. The COLLADA specificatin requires that the
|
||||
// transformation elements are processed in order and accumulate the result as if they were
|
||||
// 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::Node* daeReader::processOsgMatrixTransform( domNode *node )
|
||||
osg::Transform* daeReader::processOsgMatrixTransform(domNode *node, bool isBone)
|
||||
{
|
||||
osg::MatrixTransform* matNode = new osg::MatrixTransform;
|
||||
osg::Matrix matrix;
|
||||
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++ )
|
||||
for (size_t i = 0; i < count; i++ )
|
||||
{
|
||||
domRotate * rot = daeSafeCast< domRotate >( node->getContents()[i] );
|
||||
if (rot)
|
||||
daeElement* pDaeElement = node->getContents()[i];
|
||||
osg::ref_ptr<osgAnimation::StackedTransformElement> pTransformElement = NULL;
|
||||
|
||||
if (domRotate * pDomRotate = daeSafeCast< domRotate >( pDaeElement ))
|
||||
{
|
||||
domFloat4& r = rot->getValue();
|
||||
if (r.getCount() != 4 )
|
||||
const domFloat4& r = pDomRotate->getValue();
|
||||
if (r.getCount() != 4 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for rotate"<<std::endl;
|
||||
osg::notify(osg::WARN) << "Data is wrong size for rotate" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build rotation matrix
|
||||
osg::Matrix rotMat;
|
||||
rotMat.makeRotate(osg::DegreesToRadians(r[3]), r[0], r[1], r[2]);
|
||||
|
||||
matrix = rotMat * matrix;
|
||||
continue;
|
||||
pTransformElement = new osgAnimation::StackedRotateAxisElement(pDomRotate->getSid() ? pDomRotate->getSid() : "", osg::Vec3(r[0], r[1], r[2]), osg::DegreesToRadians(r[3]));
|
||||
}
|
||||
|
||||
domTranslate * trans = daeSafeCast< domTranslate >( node->getContents()[i] );
|
||||
if (trans != NULL)
|
||||
else if (domTranslate * pDomTranslate = daeSafeCast< domTranslate >( pDaeElement ))
|
||||
{
|
||||
domFloat3& t = trans->getValue();
|
||||
if (t.getCount() != 3 )
|
||||
const domFloat3& t = pDomTranslate->getValue();
|
||||
if (t.getCount() != 3 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for translate"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build translation matrix
|
||||
osg::Matrix transMat;
|
||||
transMat.makeTranslate(t[0], t[1], t[2]);
|
||||
|
||||
matrix = transMat * matrix;
|
||||
continue;
|
||||
pTransformElement = new osgAnimation::StackedTranslateElement(pDomTranslate->getSid() ? pDomTranslate->getSid() : "", osg::Vec3(t[0], t[1], t[2]));
|
||||
}
|
||||
|
||||
domScale * scale = daeSafeCast< domScale >( node->getContents()[i] );
|
||||
if (scale != NULL)
|
||||
else if (domScale * pDomScale = daeSafeCast< domScale >( pDaeElement ))
|
||||
{
|
||||
domFloat3& s = scale->getValue();
|
||||
if (s.getCount() != 3 )
|
||||
const domFloat3& s = pDomScale->getValue();
|
||||
if (s.getCount() != 3 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for scale"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build scale matrix
|
||||
osg::Matrix scaleMat;
|
||||
scaleMat.makeScale(s[0], s[1], s[2]);
|
||||
|
||||
matrix = scaleMat * matrix;
|
||||
continue;
|
||||
pTransformElement = new osgAnimation::StackedScaleElement(pDomScale->getSid() ? pDomScale->getSid() : "", osg::Vec3(s[0], s[1], s[2]));
|
||||
}
|
||||
|
||||
domMatrix * mat = daeSafeCast< domMatrix >( node->getContents()[i] );
|
||||
if (mat != NULL)
|
||||
else if (domMatrix * pDomMatrix = daeSafeCast< domMatrix >( pDaeElement ))
|
||||
{
|
||||
if (mat->getValue().getCount() != 16 )
|
||||
if (pDomMatrix->getValue().getCount() != 16 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for matrix"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build matrix
|
||||
osg::Matrix mMat( mat->getValue()[0], mat->getValue()[4], mat->getValue()[8], mat->getValue()[12],
|
||||
mat->getValue()[1], mat->getValue()[5], mat->getValue()[9], mat->getValue()[13],
|
||||
mat->getValue()[2], mat->getValue()[6], mat->getValue()[10], mat->getValue()[14],
|
||||
mat->getValue()[3], mat->getValue()[7], mat->getValue()[11], mat->getValue()[15] );
|
||||
|
||||
matrix = mMat * matrix;
|
||||
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]));
|
||||
}
|
||||
|
||||
domLookat * la = daeSafeCast< domLookat >( node->getContents()[i] );
|
||||
if (la != NULL)
|
||||
else if (domLookat * pDomLookat = daeSafeCast< domLookat >( pDaeElement ))
|
||||
{
|
||||
if (la->getValue().getCount() != 9 )
|
||||
if (pDomLookat->getValue().getCount() != 9 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for lookat"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Build lookat matrix
|
||||
osg::Matrix lookatMat;
|
||||
osg::Vec3 eye(la->getValue()[0], la->getValue()[1], la->getValue()[2]);
|
||||
osg::Vec3 center(la->getValue()[3], la->getValue()[4], la->getValue()[5] );
|
||||
osg::Vec3 up( la->getValue()[6], la->getValue()[7], la->getValue()[8] );
|
||||
lookatMat.makeLookAt( eye, center, up );
|
||||
|
||||
matrix = lookatMat * matrix;
|
||||
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])));
|
||||
}
|
||||
|
||||
domSkew * skew = daeSafeCast< domSkew >( node->getContents()[i] );
|
||||
if (skew != NULL)
|
||||
else if (domSkew * pDomSkew = daeSafeCast< domSkew >( pDaeElement ))
|
||||
{
|
||||
if (skew->getValue().getCount() != 7 )
|
||||
if (pDomSkew->getValue().getCount() != 7 )
|
||||
{
|
||||
osg::notify(osg::WARN)<<"Data is wrong size for skew"<<std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skew matrix building derived from GNURealistic ShaderMan GMANMatrix4 (LGPL) matrix class
|
||||
|
||||
// Build skew matrix
|
||||
domFloat7& s = skew->getValue();
|
||||
const domFloat7& s = pDomSkew->getValue();
|
||||
|
||||
float shear = sin(osg::DegreesToRadians(s[0]));
|
||||
// axis of rotation
|
||||
@@ -148,58 +132,104 @@ osg::Node* daeReader::processOsgMatrixTransform( domNode *node )
|
||||
// axis of translation
|
||||
osg::Vec3f along(s[4],s[5],s[6]);
|
||||
|
||||
along.normalize();
|
||||
osg::Vec3f a = around - (along * (around * along));
|
||||
a.normalize();
|
||||
|
||||
float an1 = around * a;
|
||||
float an2 = around * along;
|
||||
|
||||
float rx = an1 * cos(shear) - an2 * sin(shear);
|
||||
float ry = an1 * sin(shear) + an2 * cos(shear);
|
||||
//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();
|
||||
|
||||
if (rx <= 0.0)
|
||||
pTransformElement = new osgAnimation::StackedMatrixElement(pDomLookat->getSid() ? pDomLookat->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())
|
||||
{
|
||||
osg::notify(osg::WARN)<<"skew angle too large"<<std::endl;
|
||||
continue;
|
||||
// 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);
|
||||
}
|
||||
|
||||
float alpha;
|
||||
// A parallel to B??
|
||||
if (an1==0)
|
||||
else if (pLastStaticTransformElement)
|
||||
{
|
||||
alpha=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha=ry/rx-an2/an1;
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
osg::Matrix skewMat(a.x()*along.x()*alpha+1.0, a.x()*along.y()*alpha, a.x()*along.z()*alpha, 0,
|
||||
a.y()*along.x()*alpha, a.y()*along.y()*alpha+1.0, a.y()*along.z()*alpha, 0,
|
||||
a.z()*along.x()*alpha, a.z()*along.y()*alpha, a.z()*along.z()*alpha+1.0, 0,
|
||||
0, 0, 0, 1);
|
||||
|
||||
|
||||
matrix = skewMat * matrix;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
matNode->setMatrix(matrix);
|
||||
// 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 = matNode->getOrCreateStateSet();
|
||||
osg::StateSet* ss = resultNode->getOrCreateStateSet();
|
||||
ss->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
}
|
||||
|
||||
return matNode;
|
||||
return resultNode;
|
||||
}
|
||||
|
||||
osg::Node* daeReader::processOsgDOFTransform(domTechnique* teq)
|
||||
osg::Group* daeReader::processOsgDOFTransform(domTechnique* teq)
|
||||
{
|
||||
osgSim::DOFTransform* dof = new osgSim::DOFTransform;
|
||||
|
||||
|
||||
@@ -18,20 +18,23 @@
|
||||
#include <dom/domInstanceWithExtra.h>
|
||||
#include <dom/domConstants.h>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
daeReader::daeReader(DAE *dae_, bool strictTransparency) :
|
||||
m_AssetUnitName("meter"),
|
||||
m_AssetUnitMeter(1.0),
|
||||
m_AssetUp_axis(UPAXISTYPE_Y_UP),
|
||||
dae(dae_),
|
||||
rootNode(NULL),
|
||||
m_numlights(0),
|
||||
currentInstance_effect(NULL),
|
||||
currentEffect(NULL),
|
||||
m_AuthoringTool(UNKNOWN),
|
||||
m_StrictTransparency(strictTransparency)
|
||||
daeReader::daeReader(DAE *dae_, bool strictTransparency) :
|
||||
_dae(dae_),
|
||||
_rootNode(NULL),
|
||||
_visualScene(NULL),
|
||||
_numlights(0),
|
||||
_currentInstance_effect(NULL),
|
||||
_currentEffect(NULL),
|
||||
_authoringTool(UNKNOWN),
|
||||
_strictTransparency(strictTransparency),
|
||||
_invertTransparency(false),
|
||||
_assetUnitName("meter"),
|
||||
_assetUnitMeter(1.0),
|
||||
_assetUp_axis(UPAXISTYPE_Y_UP)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -41,69 +44,97 @@ daeReader::~daeReader()
|
||||
|
||||
bool daeReader::convert( const std::string &fileURI )
|
||||
{
|
||||
// Clear caches
|
||||
_geometryMap.clear();
|
||||
_materialMap.clear();
|
||||
_materialMap2.clear();
|
||||
|
||||
daeElement *colladaElement;
|
||||
domInstance_rigid_body *irb;
|
||||
|
||||
|
||||
daeInt count, result;
|
||||
|
||||
daeInt res = dae->load( fileURI.c_str() );
|
||||
_document = _dae->open(fileURI);
|
||||
|
||||
if( res != DAE_OK && res != DAE_ERR_COLLECTION_ALREADY_EXISTS)
|
||||
if (!_document)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Load failed in COLLADA DOM" << std::endl;
|
||||
return false;
|
||||
}
|
||||
osg::notify( osg::INFO ) << "URI loaded: " << fileURI << std::endl;
|
||||
|
||||
domCOLLADA* document = dae->getDom( fileURI.c_str() );
|
||||
|
||||
if ( !document->getScene() || !document->getScene()->getInstance_visual_scene() )
|
||||
if ( !_document->getScene() || !_document->getScene()->getInstance_visual_scene() )
|
||||
{
|
||||
osg::notify( osg::WARN ) << "No scene found!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (document->getAsset())
|
||||
if (_document->getAsset())
|
||||
{
|
||||
const domAsset::domContributor_Array& ContributorArray = document->getAsset()->getContributor_array();
|
||||
const domAsset::domContributor_Array& ContributorArray = _document->getAsset()->getContributor_array();
|
||||
size_t NumberOfContributors = ContributorArray.getCount();
|
||||
size_t CurrentContributor;
|
||||
for (CurrentContributor = 0; CurrentContributor < NumberOfContributors; CurrentContributor++)
|
||||
{
|
||||
if (ContributorArray[CurrentContributor]->getAuthoring_tool())
|
||||
{
|
||||
const char szBlender[] = "Blender";
|
||||
const char szDazStudio[] = "DAZ|Studio";
|
||||
const char szSketchup[] = "Google SketchUp";
|
||||
const char szFbx[] = "FBX";
|
||||
const char szMaya[] = "Maya";
|
||||
|
||||
xsString Tool = ContributorArray[CurrentContributor]->getAuthoring_tool()->getValue();
|
||||
if (strncmp(Tool, "Google SketchUp", 15) == 0)
|
||||
m_AuthoringTool = GOOGLE_SKETCHUP;
|
||||
|
||||
if (strncmp(Tool, szBlender, strlen(szBlender)) == 0)
|
||||
_authoringTool = BLENDER;
|
||||
else if (strncmp(Tool, szDazStudio, strlen(szDazStudio)) == 0)
|
||||
_authoringTool = DAZ_STUDIO;
|
||||
else if (strncmp(Tool, szFbx, strlen(szFbx)) == 0)
|
||||
_authoringTool = FBX_CONVERTER;
|
||||
else if (strncmp(Tool, szSketchup, strlen(szSketchup)) == 0)
|
||||
_authoringTool = GOOGLE_SKETCHUP;
|
||||
else if (strncmp(Tool, szMaya, strlen(szMaya)) == 0)
|
||||
_authoringTool = MAYA;
|
||||
}
|
||||
}
|
||||
if (document->getAsset()->getUnit())
|
||||
if (_document->getAsset()->getUnit())
|
||||
{
|
||||
if (NULL != document->getAsset()->getUnit()->getName())
|
||||
m_AssetUnitName = std::string(document->getAsset()->getUnit()->getName());
|
||||
if (0 != document->getAsset()->getUnit()->getMeter())
|
||||
m_AssetUnitMeter = document->getAsset()->getUnit()->getMeter();
|
||||
if (NULL != _document->getAsset()->getUnit()->getName())
|
||||
_assetUnitName = std::string(_document->getAsset()->getUnit()->getName());
|
||||
if (0 != _document->getAsset()->getUnit()->getMeter())
|
||||
_assetUnitMeter = _document->getAsset()->getUnit()->getMeter();
|
||||
}
|
||||
if (document->getAsset()->getUp_axis())
|
||||
m_AssetUp_axis = document->getAsset()->getUp_axis()->getValue();
|
||||
if (_document->getAsset()->getUp_axis())
|
||||
_assetUp_axis = _document->getAsset()->getUp_axis()->getValue();
|
||||
}
|
||||
|
||||
if (dae->getDatabase())
|
||||
domInstanceWithExtra *ivs = _document->getScene()->getInstance_visual_scene();
|
||||
_visualScene = daeSafeCast< domVisual_scene >( getElementFromURI( ivs->getUrl() ) );
|
||||
if ( _visualScene == NULL )
|
||||
{
|
||||
count = dae->getDatabase()->getElementCount(NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY, NULL);
|
||||
osg::notify( osg::WARN ) << "Unable to locate visual scene!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (daeDatabase* database = _dae->getDatabase())
|
||||
{
|
||||
_invertTransparency = findInvertTransparency(database);
|
||||
|
||||
// build a std::map for lookup if Group or PositionAttitudeTransform should be created,
|
||||
// i.e, make it easy to check if a instance_rigid_body targets a visual node
|
||||
domInstance_rigid_body *pDomInstanceRigidBody;
|
||||
count = database->getElementCount(NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY, NULL);
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
result = dae->getDatabase()->getElement(&colladaElement, i, NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY);
|
||||
result = database->getElement(&colladaElement, i, NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY);
|
||||
|
||||
if (result == DAE_OK)
|
||||
{
|
||||
irb = daeSafeCast<domInstance_rigid_body>(colladaElement);
|
||||
if (irb)
|
||||
pDomInstanceRigidBody = daeSafeCast<domInstance_rigid_body>(colladaElement);
|
||||
if (pDomInstanceRigidBody)
|
||||
{
|
||||
domNode *node = daeSafeCast<domNode>(irb->getTarget().getElement());
|
||||
domNode *node = daeSafeCast<domNode>(pDomInstanceRigidBody->getTarget().getElement());
|
||||
if (node && node->getId())
|
||||
{
|
||||
_targetMap[ std::string(node->getId()) ] = true;
|
||||
@@ -111,23 +142,176 @@ bool daeReader::convert( const std::string &fileURI )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a map of elements that are targetted by animations
|
||||
count = database->getElementCount(NULL, COLLADA_TYPE_CHANNEL, NULL);
|
||||
for (int i=0; i<count; i++)
|
||||
{
|
||||
result = database->getElement(&colladaElement, i, NULL, COLLADA_TYPE_CHANNEL);
|
||||
|
||||
if (result == DAE_OK)
|
||||
{
|
||||
domChannel* pDomChannel = daeSafeCast<domChannel>(colladaElement);
|
||||
if (pDomChannel)
|
||||
{
|
||||
std::string target = pDomChannel->getTarget();
|
||||
size_t openparenthesis = target.find_first_of('(');
|
||||
if (openparenthesis != std::string::npos) target.erase(openparenthesis);
|
||||
daeSIDResolver resolver(pDomChannel, target.c_str());
|
||||
daeElement *pDaeElement = resolver.getElement();
|
||||
if (pDaeElement)
|
||||
{
|
||||
_daeElementDomChannelMap.insert(daeElementDomChannelMap::value_type(pDaeElement, pDomChannel));
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not locate <channel> target " << pDomChannel->getTarget()<< std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find all nodes that are used as bones. Note that while many files
|
||||
// identify nodes with type="JOINT", some don't do this, while others
|
||||
// identify every node as a joint, making it meaningless.
|
||||
std::vector<domInstance_controller*> instanceControllers;
|
||||
database->typeLookup(instanceControllers);
|
||||
for (size_t i = 0; i < instanceControllers.size(); ++i)
|
||||
{
|
||||
domInstance_controller* pInstanceController = instanceControllers[i];
|
||||
|
||||
domController *pDomController = daeSafeCast<domController>(getElementFromURI(pInstanceController->getUrl()));
|
||||
if (!pDomController)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Failed to locate controller " << pInstanceController->getUrl().getURI() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
const domInstance_controller::domSkeleton_Array& domSkeletonURIs = pInstanceController->getSkeleton_array();
|
||||
std::vector<daeElement*> searchIn;
|
||||
|
||||
for (size_t i = 0; i < domSkeletonURIs.getCount(); ++i)
|
||||
{
|
||||
if (daeElement* el = getElementFromURI(domSkeletonURIs[i]->getValue()))
|
||||
{
|
||||
searchIn.push_back(el);
|
||||
if (domNode* pJoint = daeSafeCast<domNode>(el))
|
||||
{
|
||||
_jointSet.insert(pJoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchIn.empty())
|
||||
{
|
||||
searchIn.push_back(_visualScene);
|
||||
}
|
||||
|
||||
const domSkin* pSkin = pDomController->getSkin();
|
||||
if (!pSkin) continue;
|
||||
const domSkin::domJoints* pJoints = pSkin->getJoints();
|
||||
if (!pJoints) continue;
|
||||
const domInputLocal_Array& inputURIs = pJoints->getInput_array();
|
||||
|
||||
domSource* pDomJointsSource = NULL;
|
||||
for (size_t i=0; i < inputURIs.getCount(); i++)
|
||||
{
|
||||
if (!strcmp(inputURIs[i]->getSemantic(), COMMON_PROFILE_INPUT_JOINT))
|
||||
{
|
||||
pDomJointsSource = daeSafeCast<domSource>(getElementFromURI(inputURIs[i]->getSource()));
|
||||
if (!pDomJointsSource)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find skin joints source '" << inputURIs[i]->getSource().getURI() << "'" <<std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pDomJointsSource)
|
||||
{
|
||||
}
|
||||
else if (domIDREF_array* pDomIDREFs = pDomJointsSource->getIDREF_array())
|
||||
{
|
||||
for (size_t i = 0; i < pDomIDREFs->getCount(); ++i)
|
||||
{
|
||||
if (domNode* pJoint = daeSafeCast<domNode>(getElementFromIDRef(pDomIDREFs->getValue().get(i))))
|
||||
{
|
||||
_jointSet.insert(pJoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (domName_array* pDomNames = pDomJointsSource->getName_array())
|
||||
{
|
||||
for (size_t i = 0; i < pDomNames->getCount(); ++i)
|
||||
{
|
||||
daeString target = pDomNames->getValue().get(i);
|
||||
for (size_t j = 0; j < searchIn.size(); ++j)
|
||||
{
|
||||
daeSIDResolver resolver(searchIn[j], target);
|
||||
if (domNode* pJoint = daeSafeCast<domNode>(resolver.getElement()))
|
||||
{
|
||||
_jointSet.insert(pJoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
domInstanceWithExtra *ivs = document->getScene()->getInstance_visual_scene();
|
||||
domVisual_scene *vs = daeSafeCast< domVisual_scene >( getElementFromURI( ivs->getUrl() ) );
|
||||
if ( vs == NULL )
|
||||
// Build the actual scene graph based on the visual scene
|
||||
_rootNode = processVisualScene( _visualScene );
|
||||
|
||||
osgAnimation::BasicAnimationManager* pOsgAnimationManager = processAnimationLibraries(_document);
|
||||
if (pOsgAnimationManager)
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Unable to locate visual scene!" << std::endl;
|
||||
return false;
|
||||
_rootNode->addUpdateCallback(pOsgAnimationManager);
|
||||
}
|
||||
rootNode = processVisualScene( vs );
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
osg::Node* daeReader::processVisualScene( domVisual_scene *scene )
|
||||
void daeReader::addChild(osg::Group* group, osg::Node* node)
|
||||
{
|
||||
osg::Node *retVal;
|
||||
if (dynamic_cast<osgAnimation::Bone*>(node))
|
||||
{
|
||||
unsigned index = 0;
|
||||
while (index < group->getNumChildren() &&
|
||||
dynamic_cast<osgAnimation::Bone*>(group->getChild(index)))
|
||||
{
|
||||
++index;
|
||||
}
|
||||
group->insertChild(index, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
group->addChild(node);
|
||||
}
|
||||
}
|
||||
|
||||
osg::Group* daeReader::turnZUp()
|
||||
{
|
||||
osg::PositionAttitudeTransform* pat = NULL;
|
||||
|
||||
// If not Z axis up we need to rotate scene to bring the Z axis up
|
||||
if (_assetUp_axis != UPAXISTYPE_Z_UP)
|
||||
{
|
||||
pat = new osg::PositionAttitudeTransform();
|
||||
if (_assetUp_axis == UPAXISTYPE_Y_UP)
|
||||
{
|
||||
pat->setAttitude(osg::Quat(osg::inDegrees(90.0f), osg::Vec3(1.0f,0.0f,0.0f)));
|
||||
}
|
||||
else //(m_AssetUp_axis == UPAXISTYPE_X_UP)
|
||||
{
|
||||
pat->setAttitude(osg::Quat(osg::inDegrees(90.0f), osg::Vec3(0.0f,1.0f,0.0f)));
|
||||
}
|
||||
}
|
||||
|
||||
_assetUp_axis = UPAXISTYPE_Z_UP;
|
||||
return pat;
|
||||
}
|
||||
|
||||
osg::Group* daeReader::processVisualScene( domVisual_scene *scene )
|
||||
{
|
||||
osg::Group *retVal;
|
||||
_rootStateSet = new osg::StateSet();
|
||||
|
||||
unsigned int nbVisualSceneGroup=scene->getNode_array().getCount();
|
||||
@@ -137,36 +321,48 @@ osg::Node* daeReader::processVisualScene( domVisual_scene *scene )
|
||||
retVal = new osg::Group();
|
||||
retVal->setName("Empty Collada scene");
|
||||
}
|
||||
else if (nbVisualSceneGroup==1)
|
||||
{
|
||||
osg::Node *node = processNode( scene->getNode_array()[0] );
|
||||
if ( node != NULL )
|
||||
retVal = node;
|
||||
else
|
||||
{
|
||||
retVal = new osg::Group();
|
||||
retVal->setName("Empty Collada scene (import failure)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal = new osg::Group();
|
||||
retVal->setName("Collada visual scene group");
|
||||
for ( size_t i = 0; i < scene->getNode_array().getCount(); i++ )
|
||||
{
|
||||
osg::Node *node = processNode( scene->getNode_array()[i] );
|
||||
if ( node != NULL )
|
||||
{
|
||||
retVal->asGroup()->addChild( node );
|
||||
}
|
||||
}
|
||||
{
|
||||
retVal = turnZUp();
|
||||
|
||||
if (!retVal)
|
||||
{
|
||||
retVal = new osg::Group;
|
||||
}
|
||||
|
||||
_skinInstanceControllers.clear();
|
||||
|
||||
const domNode_Array& node_array = scene->getNode_array();
|
||||
for (size_t i = 0; i < node_array.getCount(); i++)
|
||||
{
|
||||
if (osg::Node* node = processNode(node_array[i], false))
|
||||
{
|
||||
addChild(retVal, node);
|
||||
}
|
||||
}
|
||||
|
||||
processSkins();
|
||||
|
||||
if (retVal->getName().empty())
|
||||
{
|
||||
if (retVal->getNumChildren())
|
||||
{
|
||||
retVal->setName("Collada visual scene group");
|
||||
}
|
||||
else
|
||||
{
|
||||
retVal->setName("Empty Collada scene (import failure)");
|
||||
}
|
||||
}
|
||||
}
|
||||
retVal->setStateSet(_rootStateSet.get());
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
osg::Node* daeReader::processExtras(domNode *node)
|
||||
|
||||
|
||||
osg::Group* daeReader::processExtras(domNode *node)
|
||||
{
|
||||
// See if one of the extras contains OpenSceneGraph specific information
|
||||
unsigned int numExtras = node->getExtra_array().getCount();
|
||||
@@ -303,7 +499,7 @@ domTechnique* daeReader::getOpenSceneGraphProfile(domExtra* extra)
|
||||
// 0..* <instance_node>
|
||||
// 0..* <node>
|
||||
// 0..* <extra>
|
||||
osg::Node* daeReader::processNode( domNode *node )
|
||||
osg::Node* daeReader::processNode( domNode *node, bool skeleton)
|
||||
{
|
||||
// First we need to determine what kind of OSG node we need
|
||||
// If there exist any of the <lookat>, <matrix>, <rotate>, <scale>, <skew>, <translate> elements
|
||||
@@ -315,17 +511,26 @@ osg::Node* daeReader::processNode( domNode *node )
|
||||
node->getMatrix_array().getCount() +
|
||||
node->getSkew_array().getCount();
|
||||
|
||||
// See if it is targeted
|
||||
// See if it is targeted by an animation
|
||||
bool targeted = false;
|
||||
if (node->getId())
|
||||
{
|
||||
targeted = _targetMap[std::string(node->getId())];
|
||||
}
|
||||
|
||||
osg::Node *resultNode;
|
||||
if (coordcount > 0 || targeted )
|
||||
|
||||
osg::Group *resultNode = NULL;
|
||||
|
||||
bool isBone = skeleton || isJoint(node);
|
||||
|
||||
if (coordcount > 0 || targeted || isBone)
|
||||
{
|
||||
resultNode = processOsgMatrixTransform(node);
|
||||
// TODO
|
||||
// single matrix -> MatrixTransform
|
||||
// scale, euler, translate -> PositionAttitudeTransform
|
||||
// if targeted -> StackedTransform
|
||||
// otherwise a flattened -> MatrixTransform
|
||||
resultNode = processOsgMatrixTransform(node, isBone);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -336,73 +541,89 @@ osg::Node* daeReader::processNode( domNode *node )
|
||||
// See if there is generic node info attached as extra
|
||||
processNodeExtra(resultNode, node);
|
||||
|
||||
resultNode->setName( node->getId() ? node->getId() : "" );
|
||||
|
||||
osg::Group* groupNode = resultNode->asGroup();
|
||||
|
||||
if (groupNode)
|
||||
if (resultNode->getName().empty())
|
||||
{
|
||||
// 0..* <instance_camera>
|
||||
domInstance_camera_Array cameraInstanceArray = node->getInstance_camera_array();
|
||||
for ( size_t i = 0; i < cameraInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( cameraInstanceArray[i]->getUrl());
|
||||
domCamera *c = daeSafeCast< domCamera >( el );
|
||||
resultNode->setName( node->getId() ? node->getId() : "" );
|
||||
}
|
||||
|
||||
if (c)
|
||||
groupNode->addChild( processCamera( c ));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate camera " << cameraInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
osg::Group* attachTo = resultNode;
|
||||
|
||||
if (!skeleton && isJoint(node))
|
||||
{
|
||||
skeleton = true;
|
||||
osgAnimation::Skeleton* pOsgSkeleton = getOrCreateSkeleton(node);
|
||||
pOsgSkeleton->addChild(resultNode);
|
||||
attachTo = resultNode;
|
||||
resultNode = pOsgSkeleton;
|
||||
}
|
||||
|
||||
// 0..* <instance_camera>
|
||||
const domInstance_camera_Array& cameraInstanceArray = node->getInstance_camera_array();
|
||||
for ( size_t i = 0; i < cameraInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( cameraInstanceArray[i]->getUrl());
|
||||
domCamera *c = daeSafeCast< domCamera >( el );
|
||||
|
||||
if (c)
|
||||
addChild(attachTo, processCamera( c ));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate camera " << cameraInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
|
||||
// 0..* <instance_controller>
|
||||
const domInstance_controller_Array& controllerInstanceArray = node->getInstance_controller_array();
|
||||
for ( size_t i = 0; i < controllerInstanceArray.getCount(); i++ )
|
||||
{
|
||||
osg::Node* pOsgNode = processInstanceController( controllerInstanceArray[i]);
|
||||
|
||||
// A skin controller may return NULL, since the RigGeometry is added as
|
||||
// child of the skeleton and the skeleton already is added to the scenegraph
|
||||
if (pOsgNode)
|
||||
{
|
||||
addChild(attachTo, pOsgNode);
|
||||
}
|
||||
}
|
||||
|
||||
// 0..* <instance_controller>
|
||||
domInstance_controller_Array controllerInstanceArray = node->getInstance_controller_array();
|
||||
for ( size_t i = 0; i < controllerInstanceArray.getCount(); i++ )
|
||||
{
|
||||
groupNode->addChild( processInstanceController( controllerInstanceArray[i] ));
|
||||
}
|
||||
// 0..* <instance_geometry>
|
||||
const domInstance_geometry_Array& geometryInstanceArray = node->getInstance_geometry_array();
|
||||
for ( size_t i = 0; i < geometryInstanceArray.getCount(); i++ )
|
||||
{
|
||||
addChild(attachTo, processInstanceGeometry( geometryInstanceArray[i] ));
|
||||
}
|
||||
|
||||
// 0..* <instance_geometry>
|
||||
domInstance_geometry_Array geometryInstanceArray = node->getInstance_geometry_array();
|
||||
for ( size_t i = 0; i < geometryInstanceArray.getCount(); i++ )
|
||||
{
|
||||
groupNode->addChild( processInstanceGeometry( geometryInstanceArray[i] ));
|
||||
}
|
||||
// 0..* <instance_light>
|
||||
const domInstance_light_Array& lightInstanceArray = node->getInstance_light_array();
|
||||
for ( size_t i = 0; i < lightInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( lightInstanceArray[i]->getUrl());
|
||||
domLight *pDomLight = daeSafeCast< domLight >( el );
|
||||
|
||||
if (pDomLight)
|
||||
addChild(attachTo, processLight(pDomLight));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate light " << lightInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
|
||||
// 0..* <instance_light>
|
||||
domInstance_light_Array lightInstanceArray = node->getInstance_light_array();
|
||||
for ( size_t i = 0; i < lightInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( lightInstanceArray[i]->getUrl());
|
||||
domLight *l = daeSafeCast< domLight >( el );
|
||||
|
||||
if (l)
|
||||
groupNode->addChild( processLight( l ));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate light " << lightInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
// 0..* <instance_node>
|
||||
const domInstance_node_Array& nodeInstanceArray = node->getInstance_node_array();
|
||||
for ( size_t i = 0; i < nodeInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( nodeInstanceArray[i]->getUrl());
|
||||
domNode *n = daeSafeCast< domNode >( el );
|
||||
|
||||
// 0..* <instance_node>
|
||||
domInstance_node_Array nodeInstanceArray = node->getInstance_node_array();
|
||||
for ( size_t i = 0; i < nodeInstanceArray.getCount(); i++ )
|
||||
{
|
||||
daeElement *el = getElementFromURI( nodeInstanceArray[i]->getUrl());
|
||||
domNode *n = daeSafeCast< domNode >( el );
|
||||
|
||||
if (n)
|
||||
// Recursive call
|
||||
groupNode->addChild( processNode( n ));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate node " << nodeInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
|
||||
// 0..* <node>
|
||||
domNode_Array nodeArray = node->getNode_array();
|
||||
for ( size_t i = 0; i < nodeArray.getCount(); i++ )
|
||||
{
|
||||
if (n)
|
||||
// Recursive call
|
||||
groupNode->addChild( processNode( nodeArray[i] ));
|
||||
}
|
||||
addChild(attachTo, processNode( n, skeleton ));
|
||||
else
|
||||
osg::notify( osg::WARN ) << "Failed to locate node " << nodeInstanceArray[i]->getUrl().getURI() << std::endl;
|
||||
}
|
||||
|
||||
// 0..* <node>
|
||||
const domNode_Array& nodeArray = node->getNode_array();
|
||||
for ( size_t i = 0; i < nodeArray.getCount(); i++ )
|
||||
{
|
||||
// Recursive call
|
||||
addChild(attachTo, processNode( nodeArray[i], skeleton ));
|
||||
}
|
||||
|
||||
return resultNode;
|
||||
|
||||
@@ -20,17 +20,20 @@
|
||||
#include <dae/daeURI.h>
|
||||
#include <dae/daeElement.h>
|
||||
#include <dom/domCommon_color_or_texture_type.h>
|
||||
#include <dom/domInputLocalOffset.h>
|
||||
#include <dom/domInstance_controller.h>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/Transform>
|
||||
#include <osg/Notify>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/Registry>
|
||||
#include <osg/Material>
|
||||
|
||||
#include <osg/Texture2D>
|
||||
#include <osgAnimation/BasicAnimationManager>
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgAnimation/Skeleton>
|
||||
|
||||
class domBind_material;
|
||||
class domCamera;
|
||||
@@ -52,9 +55,8 @@ class domTranslate;
|
||||
class domRotate;
|
||||
class domVisual_scene;
|
||||
|
||||
#include <dom/domInputLocalOffset.h>
|
||||
|
||||
namespace osgdae {
|
||||
namespace osgDAE
|
||||
{
|
||||
|
||||
class domSourceReader;
|
||||
|
||||
@@ -136,121 +138,266 @@ public:
|
||||
|
||||
bool convert( const std::string &fileURI );
|
||||
|
||||
osg::Node* getRootNode() { return rootNode; }
|
||||
osg::Node* getRootNode() { return _rootNode; }
|
||||
|
||||
// Additional Information
|
||||
std::string m_AssetUnitName;
|
||||
float m_AssetUnitMeter;
|
||||
domUpAxisType m_AssetUp_axis;
|
||||
const std::string& getAssetUnitName() const {return _assetUnitName;}
|
||||
float getAssetUnitMeter() const {return _assetUnitMeter;}
|
||||
domUpAxisType getAssetUpAxis() const {return _assetUp_axis;}
|
||||
|
||||
// Texture unit useage
|
||||
enum
|
||||
enum TextureUnitUsage
|
||||
{
|
||||
AMBIENT_OCCLUSION_UNIT = 0,
|
||||
MAIN_TEXTURE_UNIT,
|
||||
TRANSPARENCY_MAP_UNIT
|
||||
};
|
||||
|
||||
protected:
|
||||
//scene processing
|
||||
osg::Node* processVisualScene( domVisual_scene *scene );
|
||||
osg::Node* processNode( domNode *node );
|
||||
osg::Node* processOsgMatrixTransform( domNode *node );
|
||||
//osg::Node* processInstance( domInstanceWithExtra *iwe );
|
||||
enum InterpolationType
|
||||
{
|
||||
INTERPOLATION_UNKNOWN,
|
||||
INTERPOLATION_STEP,
|
||||
INTERPOLATION_LINEAR,
|
||||
INTERPOLATION_BEZIER,
|
||||
INTERPOLATION_HERMITE,
|
||||
INTERPOLATION_CARDINAL,
|
||||
INTERPOLATION_BSPLINE,
|
||||
|
||||
//COLLADA spec states that if interpolation is not specified then
|
||||
//interpolation is application defined. Linear is a sensible default.
|
||||
INTERPOLATION_DEFAULT = INTERPOLATION_LINEAR
|
||||
};
|
||||
|
||||
enum AuthoringTool
|
||||
{
|
||||
UNKNOWN,
|
||||
BLENDER,
|
||||
DAZ_STUDIO,
|
||||
FBX_CONVERTER,
|
||||
AUTODESK_3DS_MAX = FBX_CONVERTER,//3ds Max exports to DAE via Autodesk's FBX converter
|
||||
GOOGLE_SKETCHUP,
|
||||
MAYA
|
||||
};
|
||||
|
||||
class TextureParameters
|
||||
{
|
||||
public:
|
||||
TextureParameters()
|
||||
: wrap_s(osg::Texture::REPEAT), wrap_t(osg::Texture::REPEAT),
|
||||
filter_min(osg::Texture::LINEAR_MIPMAP_LINEAR), filter_mag(osg::Texture::LINEAR),
|
||||
transparent(false), opaque(FX_OPAQUE_ENUM_A_ONE), transparency(1.0f)
|
||||
{}
|
||||
|
||||
bool operator < (const TextureParameters& rhs) const
|
||||
{
|
||||
int diffStr = filename.compare(rhs.filename);
|
||||
if (diffStr) return diffStr < 0;
|
||||
if (wrap_s != rhs.wrap_s) return wrap_s < rhs.wrap_s;
|
||||
if (wrap_t != rhs.wrap_t) return wrap_t < rhs.wrap_t;
|
||||
if (filter_min != rhs.filter_min) return filter_min < rhs.filter_min;
|
||||
if (filter_mag != rhs.filter_mag) return filter_mag < rhs.filter_mag;
|
||||
if (transparency != rhs.transparency) return transparency < rhs.transparency;
|
||||
if (opaque != rhs.opaque) return opaque < rhs.opaque;
|
||||
if (transparent != rhs.transparent) return transparent < rhs.transparent;
|
||||
return border < rhs.border;
|
||||
}
|
||||
|
||||
std::string filename;
|
||||
osg::Texture::WrapMode wrap_s, wrap_t;
|
||||
osg::Texture::FilterMode filter_min, filter_mag;
|
||||
osg::Vec4 border;
|
||||
|
||||
//The following parameters are for transparency textures, to handle
|
||||
//COLLADA's horrible transparency spec.
|
||||
bool transparent;
|
||||
domFx_opaque_enum opaque;
|
||||
float transparency;
|
||||
};
|
||||
|
||||
class ChannelPart : public osg::Referenced
|
||||
{
|
||||
public:
|
||||
std::string name;
|
||||
osg::ref_ptr<osgAnimation::KeyframeContainer> keyframes;
|
||||
InterpolationType interpolation;
|
||||
};
|
||||
|
||||
typedef std::map<domGeometry*, osg::ref_ptr<osg::Geode> > domGeometryGeodeMap;
|
||||
typedef std::map<domMaterial*, osg::ref_ptr<osg::StateSet> > domMaterialStateSetMap;
|
||||
typedef std::map<std::string, osg::ref_ptr<osg::StateSet> > MaterialStateSetMap;
|
||||
typedef std::multimap< daeElement*, domChannel*> daeElementDomChannelMap;
|
||||
typedef std::map<domChannel*, osg::ref_ptr<osg::NodeCallback> > domChannelOsgAnimationUpdateCallbackMap;
|
||||
typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Bone> > domNodeOsgBoneMap;
|
||||
typedef std::map<domNode*, osg::ref_ptr<osgAnimation::Skeleton> > domNodeOsgSkeletonMap;
|
||||
typedef std::map<TextureParameters, osg::ref_ptr<osg::Texture2D> > TextureParametersMap;
|
||||
typedef std::map<std::pair<const osg::StateSet*, TextureUnitUsage>, std::string> TextureToCoordSetMap;
|
||||
|
||||
typedef std::map< daeElement*, domSourceReader > SourceMap;
|
||||
typedef std::map< int, osg::IntArray*, std::less<int> > IndexMap;
|
||||
typedef std::map< int, osg::Array*, std::less<int> > ArrayMap;
|
||||
|
||||
typedef std::multimap< osgAnimation::Target*, osg::ref_ptr<ChannelPart> > TargetChannelPartMap;
|
||||
typedef std::multimap<std::pair<const domMesh*, unsigned>, std::pair<osg::ref_ptr<osg::Geometry>, GLuint> > OldToNewIndexMap;
|
||||
|
||||
private:
|
||||
// If the node is a bone then it should be added before any other types of
|
||||
// node, this function makes that happen.
|
||||
static void addChild(osg::Group*, osg::Node*);
|
||||
|
||||
//scene processing
|
||||
osg::Group* turnZUp();
|
||||
osg::Group* processVisualScene( domVisual_scene *scene );
|
||||
osg::Node* processNode( domNode *node, bool skeleton );
|
||||
osg::Transform* processOsgMatrixTransform( domNode *node, bool isBone);
|
||||
|
||||
template <typename T>
|
||||
inline void getTransparencyCounts(daeDatabase*, int& zero, int& one) const;
|
||||
|
||||
/** Earlier versions of the COLLADA 1.4 spec state that transparency values
|
||||
of 0 mean 100% opacity, but this has been changed in later versions to state
|
||||
that transparency values of 1 mean 100% opacity. Documents created by
|
||||
different tools at different times adhere to different versions of the
|
||||
standard. This function looks at all transparency values in the database and
|
||||
heuristically decides which way the values should be interpreted.*/
|
||||
bool findInvertTransparency(daeDatabase*) const;
|
||||
|
||||
osgAnimation::BasicAnimationManager* processAnimationLibraries(domCOLLADA* document);
|
||||
void processAnimationClip(osgAnimation::BasicAnimationManager* pOsgAnimationManager, domAnimation_clip* pDomAnimationClip);
|
||||
void processAnimation(domAnimation* pDomAnimation, osgAnimation::Animation* pOsgAnimation);
|
||||
ChannelPart* processSampler(domChannel* pDomChannel, SourceMap &sources);
|
||||
void processAnimationChannels(domAnimation* pDomAnimation, TargetChannelPartMap& tcm);
|
||||
void processChannel(domChannel* pDomChannel, SourceMap &sources, TargetChannelPartMap& tcm);
|
||||
void extractTargetName(const std::string&, std::string&, std::string&, std::string&);
|
||||
|
||||
// Processing of OSG specific info stored in node extras
|
||||
osg::Node* processExtras(domNode *node);
|
||||
osg::Group* processExtras(domNode *node);
|
||||
void processNodeExtra(osg::Node* osgNode, domNode *node);
|
||||
domTechnique* getOpenSceneGraphProfile(domExtra* extra);
|
||||
void processAsset( domAsset *node );
|
||||
|
||||
osg::Node* processOsgSwitch(domTechnique* teq);
|
||||
osg::Node* processOsgMultiSwitch(domTechnique* teq);
|
||||
osg::Node* processOsgLOD(domTechnique* teq);
|
||||
osg::Node* processOsgDOFTransform(domTechnique* teq);
|
||||
osg::Node* processOsgSequence(domTechnique* teq);
|
||||
osg::Group* processOsgSwitch(domTechnique* teq);
|
||||
osg::Group* processOsgMultiSwitch(domTechnique* teq);
|
||||
osg::Group* processOsgLOD(domTechnique* teq);
|
||||
osg::Group* processOsgDOFTransform(domTechnique* teq);
|
||||
osg::Group* processOsgSequence(domTechnique* teq);
|
||||
|
||||
//geometry processing
|
||||
class ReaderGeometry : public osg::Geometry
|
||||
{
|
||||
public:
|
||||
std::map<int, int> _TexcoordSetMap;
|
||||
};
|
||||
// geometry processing
|
||||
osg::Geode* getOrCreateGeometry(domGeometry *geom, domBind_material* pDomBindMaterial, const osg::Geode** ppOriginalGeode = NULL);
|
||||
osgAnimation::Bone* getOrCreateBone(domNode *pDomNode);
|
||||
osgAnimation::Skeleton* getOrCreateSkeleton(domNode *pDomNode);
|
||||
osg::Geode* processInstanceGeometry( domInstance_geometry *ig );
|
||||
osg::Geode* processGeometry( domGeometry *geo );
|
||||
osg::Geode* processInstanceController( domInstance_controller *ictrl );
|
||||
|
||||
typedef std::map< daeElement*, domSourceReader > SourceMap;
|
||||
typedef std::map< int, osg::IntArray*, std::less<int> > IndexMap;
|
||||
osg::Geode* processMesh(domMesh* pDomMesh);
|
||||
osg::Geode* processConvexMesh(domConvex_mesh* pDomConvexMesh);
|
||||
osg::Geode* processSpline(domSpline* pDomSpline);
|
||||
osg::Geode* processGeometry(domGeometry *pDomGeometry);
|
||||
|
||||
typedef std::vector<domInstance_controller*> domInstance_controllerList;
|
||||
|
||||
void processSkins();
|
||||
//Process skins attached to one skeleton
|
||||
void processSkeletonSkins(domNode* skeletonRoot, const domInstance_controllerList&);
|
||||
void processSkin(domSkin* pDomSkin, domNode* skeletonRoot, osgAnimation::Skeleton*, domBind_material* pDomBindMaterial);
|
||||
osg::Node* processMorph(domMorph* pDomMorph, domBind_material* pDomBindMaterial);
|
||||
osg::Node* processInstanceController( domInstance_controller *ictrl );
|
||||
|
||||
template< typename T >
|
||||
void processSinglePPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode );
|
||||
void processSinglePPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
|
||||
|
||||
template< typename T >
|
||||
void processMultiPPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode );
|
||||
void processMultiPPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode);
|
||||
|
||||
void processPolylist(osg::Geode* geode, domPolylist *group, SourceMap &sources );
|
||||
template <typename T>
|
||||
void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const T *group, SourceMap& sources);
|
||||
|
||||
void resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry *geom,
|
||||
SourceMap &sources, IndexMap &index_map );
|
||||
void processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources);
|
||||
void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const domPolygons *group, SourceMap &sources);
|
||||
|
||||
void processP( domP *p, osg::Geometry *&geom, IndexMap &index_map, osg::DrawArrayLengths* dal/*GLenum mode*/ );
|
||||
void resolveMeshArrays(const domP_Array&,
|
||||
const domInputLocalOffset_Array& inputs, const domMesh* pDomMesh,
|
||||
osg::Geometry* geometry, SourceMap &sources,
|
||||
std::vector<std::vector<GLuint> >& vertexLists);
|
||||
|
||||
//material/effect processing
|
||||
void processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode, osg::Geode *cachedGeode );
|
||||
void processMaterial(osg::StateSet *ss, domMaterial *mat );
|
||||
void processEffect(osg::StateSet *ss, domEffect *effect );
|
||||
void processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc );
|
||||
bool processColorOrTextureType( domCommon_color_or_texture_type *cot,
|
||||
bool processColorOrTextureType(const osg::StateSet*,
|
||||
domCommon_color_or_texture_type *cot,
|
||||
osg::Material::ColorMode channel,
|
||||
osg::Material *mat,
|
||||
domCommon_float_or_param_type *fop = NULL,
|
||||
osg::StateAttribute **sa = NULL,
|
||||
osg::Texture2D **sa = NULL,
|
||||
bool normalizeShininess=false);
|
||||
void processTransparencySettings( domCommon_transparent_type *ctt,
|
||||
domCommon_float_or_param_type *pTransparency,
|
||||
osg::StateSet *ss,
|
||||
osg::StateSet*,
|
||||
osg::Material *material,
|
||||
xsNCName diffuseTextureName );
|
||||
bool GetFloat4Param(xsNCName Reference, domFloat4 &f4);
|
||||
bool GetFloatParam(xsNCName Reference, domFloat &f);
|
||||
bool GetFloat4Param(xsNCName Reference, domFloat4 &f4) const;
|
||||
bool GetFloatParam(xsNCName Reference, domFloat &f) const;
|
||||
|
||||
osg::StateAttribute *processTexture( domCommon_color_or_texture_type_complexType::domTexture *tex );
|
||||
std::string processImagePath(const domImage*) const;
|
||||
osg::Image* processImageTransparency(const osg::Image*, domFx_opaque_enum, float transparency) const;
|
||||
osg::Texture2D* processTexture( domCommon_color_or_texture_type_complexType::domTexture *tex, const osg::StateSet*, TextureUnitUsage, domFx_opaque_enum = FX_OPAQUE_ENUM_A_ONE, float transparency = 1.0f);
|
||||
void copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage);
|
||||
|
||||
//scene objects
|
||||
osg::Node* processLight( domLight *dlight );
|
||||
osg::Node* processCamera( domCamera *dcamera );
|
||||
|
||||
protected:
|
||||
DAE *dae;
|
||||
osg::Node* rootNode;
|
||||
domNode* getRootJoint(domNode*) const;
|
||||
domNode* findJointNode(daeElement* searchFrom, domInstance_controller*) const;
|
||||
domNode* findSkeletonNode(daeElement* searchFrom, domInstance_controller*) const;
|
||||
|
||||
/// Return whether the node is used as a bone. Note that while many files
|
||||
/// identify joints with type="JOINT", some don't do this, while others
|
||||
/// incorrectly identify every node as a joint.
|
||||
bool isJoint(const domNode* node) const {return _jointSet.find(node) != _jointSet.end();}
|
||||
|
||||
private:
|
||||
|
||||
DAE *_dae;
|
||||
osg::Node* _rootNode;
|
||||
osg::ref_ptr<osg::StateSet> _rootStateSet;
|
||||
domCOLLADA* _document;
|
||||
domVisual_scene* _visualScene;
|
||||
|
||||
std::map<std::string,bool> _targetMap;
|
||||
|
||||
int m_numlights;
|
||||
int _numlights;
|
||||
|
||||
domInstance_effect *currentInstance_effect;
|
||||
domEffect *currentEffect;
|
||||
|
||||
typedef std::map< domGeometry*, osg::ref_ptr<osg::Geode> > domGeometryGeodeMap;
|
||||
typedef std::map< domMaterial*, osg::ref_ptr<osg::StateSet> > domMaterialStateSetMap;
|
||||
typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialStateSetMap;
|
||||
domInstance_effect *_currentInstance_effect;
|
||||
domEffect *_currentEffect;
|
||||
|
||||
/// Maps an animated element to a domchannel to quickly find which animation influence this element
|
||||
// TODO a single element can be animated by multiple channels (with different members like translate.x or morphweights(2) )
|
||||
daeElementDomChannelMap _daeElementDomChannelMap;
|
||||
/// Maps a domchannel to an animationupdatecallback
|
||||
domChannelOsgAnimationUpdateCallbackMap _domChannelOsgAnimationUpdateCallbackMap;
|
||||
/// Maps geometry to a Geode
|
||||
domGeometryGeodeMap geometryMap;
|
||||
domGeometryGeodeMap _geometryMap;
|
||||
/// All nodes in the document that are used as joints.
|
||||
std::set<const domNode*> _jointSet;
|
||||
/// Maps a node (of type joint) to a osgAnimation::Bone
|
||||
domNodeOsgBoneMap _jointMap;
|
||||
/// Maps a node (of type joint) to a osgAnimation::Skeleton
|
||||
domNodeOsgSkeletonMap _skeletonMap;
|
||||
// Maps material target to stateset
|
||||
domMaterialStateSetMap materialMap;
|
||||
domMaterialStateSetMap _materialMap;
|
||||
// Maps material symbol to stateset
|
||||
MaterialStateSetMap materialMap2;
|
||||
MaterialStateSetMap _materialMap2;
|
||||
TextureParametersMap _textureParamMap;
|
||||
TextureToCoordSetMap _texCoordSetMap;
|
||||
domInstance_controllerList _skinInstanceControllers;
|
||||
OldToNewIndexMap _oldToNewIndexMap;
|
||||
|
||||
enum AuthoringTool
|
||||
{
|
||||
UNKNOWN,
|
||||
GOOGLE_SKETCHUP
|
||||
};
|
||||
AuthoringTool m_AuthoringTool;
|
||||
bool m_StrictTransparency;
|
||||
AuthoringTool _authoringTool;
|
||||
bool _strictTransparency, _invertTransparency;
|
||||
|
||||
// Additional Information
|
||||
std::string _assetUnitName;
|
||||
float _assetUnitMeter;
|
||||
domUpAxisType _assetUp_axis;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
483
src/osgPlugins/dae/daeWAnimations.cpp
Normal file
483
src/osgPlugins/dae/daeWAnimations.cpp
Normal file
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* 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 "daeWriter.h"
|
||||
|
||||
#include <dom/domCOLLADA.h>
|
||||
|
||||
#include <dom/domNode.h>
|
||||
#include <dom/domConstants.h>
|
||||
#include <dom/domLibrary_cameras.h>
|
||||
#include <dom/domLibrary_lights.h>
|
||||
#include <dae/domAny.h>
|
||||
//#include <dom/domVisual_scene.h>
|
||||
//#include <dom/domLibrary_visual_scenes.h>
|
||||
|
||||
#include <osgSim/MultiSwitch>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/UpdateMatrixTransform>
|
||||
#include <osg/Sequence>
|
||||
#include <osg/Billboard>
|
||||
#include <osg/CameraView>
|
||||
|
||||
using namespace osgDAE;
|
||||
|
||||
|
||||
void daeWriter::writeAnimations( osg::Node &node )
|
||||
{
|
||||
osg::NodeCallback* ncb = node.getUpdateCallback();
|
||||
if (ncb)
|
||||
{
|
||||
osgAnimation::AnimationManagerBase* am = dynamic_cast<osgAnimation::AnimationManagerBase*>(ncb);
|
||||
if (am)
|
||||
{
|
||||
// Create library of animations if not existing yet
|
||||
if (!_domLibraryAnimations)
|
||||
{
|
||||
_domLibraryAnimations = daeSafeCast<domLibrary_animations>( dom->add( COLLADA_ELEMENT_LIBRARY_ANIMATIONS ) );
|
||||
}
|
||||
|
||||
osgAnimation::AnimationList animationList = am->getAnimationList();
|
||||
for (size_t i = 0; i < animationList.size(); i++)
|
||||
{
|
||||
domAnimation* pDomAnimation = daeSafeCast< domAnimation >( _domLibraryAnimations->add( COLLADA_ELEMENT_ANIMATION ) );
|
||||
domAnimation* pMainDomAnimation = pDomAnimation;
|
||||
|
||||
osg::ref_ptr<osgAnimation::Animation> animation = animationList[i];
|
||||
std::string animationName = animation->getName();
|
||||
if (animationName.empty())
|
||||
animationName = "animation";
|
||||
animationName = uniquify( animationName );
|
||||
pDomAnimation->setId(animationName.c_str());
|
||||
|
||||
// Handle multiple channels within an animation
|
||||
osgAnimation::ChannelList animationChannels = animation->getChannels();
|
||||
for (size_t j=0; j < animationChannels.size(); j++)
|
||||
{
|
||||
osgAnimation::Channel* channel = animationChannels[j].get();
|
||||
std::string channelName = channel->getName();
|
||||
|
||||
// Wrap each animation channel into it's own child <animation> when more than 1 channel
|
||||
if (animationChannels.size() > 1)
|
||||
{
|
||||
pDomAnimation = daeSafeCast< domAnimation >( pMainDomAnimation->add( COLLADA_ELEMENT_ANIMATION ) );
|
||||
|
||||
if (channelName.empty())
|
||||
channelName = "channel";
|
||||
animationName = uniquify( channelName );
|
||||
pDomAnimation->setId(channelName.c_str());
|
||||
}
|
||||
|
||||
std::string sourceName = channelName + "_sampler";
|
||||
std::string inputSourceName = channelName + "_input";
|
||||
std::string outputSourceName = channelName + "_output";
|
||||
std::string interpolationSourceName = channelName + "_interpolation";
|
||||
|
||||
// Fill dom sources based on sampler
|
||||
osgAnimation::Sampler* animationSampler = channel->getSampler();
|
||||
osgAnimation::KeyframeContainer* kfc = animationSampler->getKeyframeContainer();
|
||||
int size = kfc->size();
|
||||
|
||||
float valueStride = 1;
|
||||
|
||||
domListOfFloats timeValues;
|
||||
domListOfFloats frameValues;
|
||||
domListOfNames interpolationValues;
|
||||
|
||||
osgAnimation::Vec3KeyframeContainer* v3kc = dynamic_cast<osgAnimation::Vec3KeyframeContainer*>(kfc);
|
||||
if (v3kc)
|
||||
{
|
||||
valueStride = 3;
|
||||
for (size_t i=0; i < v3kc->size(); i++)
|
||||
{
|
||||
timeValues.append((*v3kc)[i].getTime());
|
||||
osg::Vec3 vec = (*v3kc)[i].getValue();
|
||||
|
||||
// This needs some serious cleanup
|
||||
if (channelName.find("euler") != std::string::npos)
|
||||
{
|
||||
frameValues.append(osg::RadiansToDegrees(vec.x()));
|
||||
frameValues.append(osg::RadiansToDegrees(vec.y()));
|
||||
frameValues.append(osg::RadiansToDegrees(vec.z()));
|
||||
}
|
||||
else
|
||||
{
|
||||
frameValues.append(vec.x());
|
||||
frameValues.append(vec.y());
|
||||
frameValues.append(vec.z());
|
||||
}
|
||||
interpolationValues.append("LINEAR");
|
||||
}
|
||||
}
|
||||
osgAnimation::FloatKeyframeContainer* fkc = dynamic_cast<osgAnimation::FloatKeyframeContainer*>(kfc);
|
||||
if (fkc)
|
||||
{
|
||||
valueStride = 1;
|
||||
for (size_t i=0; i < fkc->size(); i++)
|
||||
{
|
||||
timeValues.append((*fkc)[i].getTime());
|
||||
frameValues.append((*fkc)[i].getValue());
|
||||
interpolationValues.append("LINEAR");
|
||||
}
|
||||
}
|
||||
|
||||
// time values
|
||||
domSource* pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
pDomSource->setId(inputSourceName.c_str());
|
||||
|
||||
domFloat_array* pDomFloatArray = daeSafeCast< domFloat_array >(pDomSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string inputArrayName = inputSourceName + "_array";
|
||||
pDomFloatArray->setId(inputArrayName.c_str());
|
||||
pDomFloatArray->setCount(size);
|
||||
pDomFloatArray->setValue(timeValues);
|
||||
|
||||
domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
std::string url = "#" + inputArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(1);
|
||||
|
||||
domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("TIME");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
|
||||
// <source> interpolator type
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
pDomSource->setId(interpolationSourceName.c_str());
|
||||
|
||||
domName_array* pDomNameArray = daeSafeCast< domName_array >(pDomSource->add(COLLADA_ELEMENT_NAME_ARRAY));
|
||||
std::string interpolationArrayName = interpolationSourceName + "_array";
|
||||
pDomNameArray->setId(interpolationArrayName.c_str());
|
||||
pDomNameArray->setCount(size);
|
||||
pDomNameArray->setValue(interpolationValues);
|
||||
|
||||
// <technique_common>
|
||||
pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
// <accessor count=size stride="1">
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
url = "#" + interpolationArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(1);
|
||||
|
||||
// <param name="INTERPOLATION" type="name"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("INTERPOLATION");
|
||||
pDomParam->setType(COLLADA_TYPE_NAME);
|
||||
|
||||
// Split up access to the euler float array into three sources, because we need to target three separate transforms
|
||||
if (channelName.find("euler") != std::string::npos)
|
||||
{
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
std::string outputSourceNameX = outputSourceName + "_X";
|
||||
pDomSource->setId(outputSourceNameX.c_str());
|
||||
|
||||
pDomFloatArray = daeSafeCast< domFloat_array >(pDomSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string outputArrayNameX = outputSourceNameX + "_array";
|
||||
pDomFloatArray->setId(outputArrayNameX.c_str());
|
||||
|
||||
// TODO, flexible handling of different keyframe types, see osg exporter for inspiration
|
||||
pDomFloatArray->setCount(size * valueStride);
|
||||
pDomFloatArray->setValue(frameValues);
|
||||
|
||||
pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
url = "#" + outputArrayNameX;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(valueStride);
|
||||
pDomAccessor->setOffset(0);
|
||||
// <param name="ANGLE" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("ANGLE");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
std::string outputSourceNameY = outputSourceName + "_Y";
|
||||
pDomSource->setId(outputSourceNameY.c_str());
|
||||
|
||||
pDomFloatArray = daeSafeCast< domFloat_array >(pDomSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string outputArrayNameY = outputSourceNameY + "_array";
|
||||
pDomFloatArray->setId(outputArrayNameY.c_str());
|
||||
|
||||
pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
url = "#" + outputArrayNameY;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(valueStride);
|
||||
pDomAccessor->setOffset(1);
|
||||
// <param name="ANGLE" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("ANGLE");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
std::string outputSourceNameZ = outputSourceName + "_Z";
|
||||
pDomSource->setId(outputSourceNameZ.c_str());
|
||||
|
||||
pDomFloatArray = daeSafeCast< domFloat_array >(pDomSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string outputArrayNameZ = outputSourceNameZ + "_array";
|
||||
pDomFloatArray->setId(outputArrayNameZ.c_str());
|
||||
|
||||
pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
url = "#" + outputArrayNameZ;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(valueStride);
|
||||
pDomAccessor->setOffset(2);
|
||||
// <param name="ANGLE" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("ANGLE");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
|
||||
{
|
||||
domSampler* pDomSampler = daeSafeCast< domSampler >(pDomAnimation->add(COLLADA_ELEMENT_SAMPLER));
|
||||
std::string sourceNameX = sourceName + "_X";
|
||||
pDomSampler->setId(sourceNameX.c_str());
|
||||
|
||||
// Fill dom sampler based on common semantics
|
||||
{
|
||||
domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INPUT);
|
||||
std::string url = "#" + inputSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_OUTPUT);
|
||||
url = "#" + outputSourceNameX;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INTERPOLATION);
|
||||
url = "#" + interpolationSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
}
|
||||
|
||||
// Set sampler as source
|
||||
domChannel* pDomChannel = daeSafeCast< domChannel >(pDomAnimation->add(COLLADA_ELEMENT_CHANNEL));
|
||||
std::string url = "#" + sourceNameX;
|
||||
pDomChannel->setSource(url.c_str());
|
||||
|
||||
// targetName contains the name of the updateCallback
|
||||
std::string targetName = channel->getTargetName();
|
||||
|
||||
// based on the type of updateCallback we can determine the transform element to target eg. "nodeName/translation"
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateX.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find animation target '" << targetName << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
domSampler* pDomSampler = daeSafeCast< domSampler >(pDomAnimation->add(COLLADA_ELEMENT_SAMPLER));
|
||||
std::string sourceNameY = sourceName + "_Y";
|
||||
pDomSampler->setId(sourceNameY.c_str());
|
||||
|
||||
// Fill dom sampler based on common semantics
|
||||
{
|
||||
domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INPUT);
|
||||
std::string url = "#" + inputSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_OUTPUT);
|
||||
url = "#" + outputSourceNameY;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INTERPOLATION);
|
||||
url = "#" + interpolationSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
}
|
||||
|
||||
// Set sampler as source
|
||||
domChannel* pDomChannel = daeSafeCast< domChannel >(pDomAnimation->add(COLLADA_ELEMENT_CHANNEL));
|
||||
std::string url = "#" + sourceNameY;
|
||||
pDomChannel->setSource(url.c_str());
|
||||
|
||||
// targetName contains the name of the updateCallback
|
||||
std::string targetName = channel->getTargetName();
|
||||
|
||||
// based on the type of updateCallback we can determine the transform element to target eg. "nodeName/translation"
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateY.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find animation target '" << targetName << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
domSampler* pDomSampler = daeSafeCast< domSampler >(pDomAnimation->add(COLLADA_ELEMENT_SAMPLER));
|
||||
std::string sourceNameZ = sourceName + "_Z";
|
||||
pDomSampler->setId(sourceNameZ.c_str());
|
||||
|
||||
// Fill dom sampler based on common semantics
|
||||
{
|
||||
domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INPUT);
|
||||
std::string url = "#" + inputSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_OUTPUT);
|
||||
url = "#" + outputSourceNameZ;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INTERPOLATION);
|
||||
url = "#" + interpolationSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
}
|
||||
|
||||
// Set sampler as source
|
||||
domChannel* pDomChannel = daeSafeCast< domChannel >(pDomAnimation->add(COLLADA_ELEMENT_CHANNEL));
|
||||
std::string url = "#" + sourceNameZ;
|
||||
pDomChannel->setSource(url.c_str());
|
||||
|
||||
// targetName contains the name of the updateCallback
|
||||
std::string targetName = channel->getTargetName();
|
||||
|
||||
// based on the type of updateCallback we can determine the transform element to target eg. "nodeName/translation"
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName() + "/rotateZ.ANGLE";
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find animation target '" << targetName << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// values in keyframecontainer
|
||||
pDomSource = daeSafeCast< domSource >(pDomAnimation->add(COLLADA_ELEMENT_SOURCE));
|
||||
pDomSource->setId(outputSourceName.c_str());
|
||||
|
||||
pDomFloatArray = daeSafeCast< domFloat_array >(pDomSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string outputArrayName = outputSourceName + "_array";
|
||||
pDomFloatArray->setId(outputArrayName.c_str());
|
||||
|
||||
// TODO, flexible handling of different keyframe types, see osg exporter for inspiration
|
||||
pDomFloatArray->setCount(size * valueStride);
|
||||
pDomFloatArray->setValue(frameValues);
|
||||
|
||||
pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
url = "#" + outputArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(valueStride);
|
||||
|
||||
if (v3kc)
|
||||
{
|
||||
// <param name="X" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("X");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
// <param name="Y" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("Y");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
// <param name="Z" type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName("Z");
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
}
|
||||
if (fkc)
|
||||
{
|
||||
// <param type="float"/>
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
domSampler* pDomSampler = daeSafeCast< domSampler >(pDomAnimation->add(COLLADA_ELEMENT_SAMPLER));
|
||||
pDomSampler->setId(sourceName.c_str());
|
||||
|
||||
// Fill dom sampler based on common semantics
|
||||
{
|
||||
domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INPUT);
|
||||
std::string url = "#" + inputSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_OUTPUT);
|
||||
url = "#" + outputSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomSampler->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INTERPOLATION);
|
||||
url = "#" + interpolationSourceName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
}
|
||||
|
||||
// Set sampler as source
|
||||
domChannel* pDomChannel = daeSafeCast< domChannel >(pDomAnimation->add(COLLADA_ELEMENT_CHANNEL));
|
||||
std::string url = "#" + sourceName;
|
||||
pDomChannel->setSource(url.c_str());
|
||||
|
||||
// targetName contains the name of the updateCallback
|
||||
std::string targetName = channel->getTargetName();
|
||||
|
||||
// based on the type of updateCallback we can determine the transform element to target eg. "nodeName/translation"
|
||||
osg::Node* node = _animatedNodeCollector.getTargetNode(targetName);
|
||||
if (node)
|
||||
{
|
||||
std::string domChannelTargetName = node->getName();
|
||||
|
||||
if (channelName.find("position") != std::string::npos)
|
||||
{
|
||||
domChannelTargetName += "/translate";
|
||||
}
|
||||
else if (channelName.find("scale") != std::string::npos)
|
||||
{
|
||||
domChannelTargetName += "/scale";
|
||||
}
|
||||
|
||||
pDomChannel->setTarget(domChannelTargetName.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Could not find animation target '" << targetName << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "daeWriter.h"
|
||||
#include <osgAnimation/RigGeometry>
|
||||
|
||||
#include <dom/domCOLLADA.h>
|
||||
#include <dom/domNode.h>
|
||||
@@ -19,10 +20,347 @@
|
||||
#include <dom/domSource.h>
|
||||
#include <dom/domGeometry.h>
|
||||
#include <dom/domConstants.h>
|
||||
//#include <dom/domSkin.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
domGeometry* daeWriter::getOrCreateDomGeometry(osg::Geometry* pOsgGeometry)
|
||||
{
|
||||
// See if geometry exists in cache
|
||||
OsgGeometryDomGeometryMap::iterator iter = geometryMap.find( pOsgGeometry );
|
||||
if ( iter != geometryMap.end() )
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!lib_geoms)
|
||||
{
|
||||
lib_geoms = daeSafeCast< domLibrary_geometries >( dom->add( COLLADA_ELEMENT_LIBRARY_GEOMETRIES ) );
|
||||
}
|
||||
domGeometry* pDomGeometry = daeSafeCast< domGeometry >( lib_geoms->add( COLLADA_ELEMENT_GEOMETRY ) );
|
||||
|
||||
std::string name = pOsgGeometry->getName();
|
||||
if (name.empty())
|
||||
name = uniquify("geometry");
|
||||
else
|
||||
name = uniquify(name);
|
||||
pDomGeometry->setId( name.c_str() );
|
||||
#ifndef EARTH_GEO
|
||||
geometryMap.insert( std::make_pair( pOsgGeometry, pDomGeometry ) );
|
||||
#endif
|
||||
|
||||
if ( !processGeometry( pOsgGeometry, pDomGeometry, name ) )
|
||||
{
|
||||
daeElement::removeFromParent( pDomGeometry );
|
||||
return NULL;
|
||||
}
|
||||
return pDomGeometry;
|
||||
}
|
||||
}
|
||||
|
||||
void daeWriter::writeRigGeometry(osgAnimation::RigGeometry *pOsgRigGeometry)
|
||||
{
|
||||
// See if controller exists in cache
|
||||
OsgRigGeometryDomControllerMap::iterator iter = _osgRigGeometryDomControllerMap.find(pOsgRigGeometry);
|
||||
domController* pDomController = NULL;
|
||||
if ( iter != _osgRigGeometryDomControllerMap.end() )
|
||||
{
|
||||
pDomController = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
domGeometry* pDomGeometry = getOrCreateDomGeometry(pOsgRigGeometry);
|
||||
if (pDomGeometry)
|
||||
{
|
||||
if (!lib_controllers)
|
||||
{
|
||||
lib_controllers = daeSafeCast< domLibrary_controllers >( dom->add( COLLADA_ELEMENT_LIBRARY_CONTROLLERS ) );
|
||||
}
|
||||
|
||||
// <controller>
|
||||
// 1 <skin>
|
||||
// source
|
||||
// 0..1 <bind_shape_matrix>
|
||||
// 3..* <source>
|
||||
// 1 <joints>
|
||||
// 1 <vertex_weights>
|
||||
// 0..1 <extra>
|
||||
pDomController = daeSafeCast< domController >( lib_controllers->add( COLLADA_ELEMENT_CONTROLLER) );
|
||||
std::string name = pOsgRigGeometry->getName();
|
||||
if (name.empty())
|
||||
name = uniquify("skincontroller");
|
||||
else
|
||||
name = uniquify(name);
|
||||
pDomController->setId( name.c_str() );
|
||||
_osgRigGeometryDomControllerMap.insert( std::make_pair( pOsgRigGeometry, pDomController ) );
|
||||
|
||||
// Link <skin> to cache hit or created <geometry>
|
||||
domSkin* pDomSkin = daeSafeCast< domSkin >(pDomController->add( COLLADA_ELEMENT_SKIN ));
|
||||
std::string url = "#" + std::string(pDomGeometry->getId());
|
||||
pDomSkin->setSource(url.c_str());
|
||||
|
||||
domSkin::domBind_shape_matrix* pDomBindShapeMatrix = daeSafeCast< domSkin::domBind_shape_matrix >(pDomSkin->add( COLLADA_ELEMENT_BIND_SHAPE_MATRIX ));
|
||||
|
||||
domSource* pDomJointsSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE ));
|
||||
std::string skinJointsName = name + "_skin_joints";
|
||||
pDomJointsSource->setId(skinJointsName.c_str());
|
||||
|
||||
domListOfNames jointNames; // TODO fill with joint ids
|
||||
int size = 0; // TODO number of animated joints
|
||||
|
||||
osgAnimation::VertexInfluenceMap* vim = pOsgRigGeometry->getInfluenceMap();
|
||||
osgAnimation::VertexInfluenceMap::iterator iter = vim->begin();
|
||||
while (iter != vim->end())
|
||||
{
|
||||
jointNames.append(iter->first.c_str());
|
||||
//iter->second.getn
|
||||
++iter;
|
||||
}
|
||||
|
||||
domName_array* pDomJointsNameArray = daeSafeCast< domName_array >(pDomJointsSource->add(COLLADA_ELEMENT_NAME_ARRAY));
|
||||
std::string jointsNameArrayName = name + "_joints_array";
|
||||
pDomJointsNameArray->setId(jointsNameArrayName.c_str());
|
||||
pDomJointsNameArray->setCount(size);
|
||||
pDomJointsNameArray->setValue(jointNames);
|
||||
{
|
||||
domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomJointsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
std::string url = "#" + jointsNameArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
|
||||
domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setType(COLLADA_TYPE_NAME);
|
||||
}
|
||||
|
||||
domSource* pDomSkinBindPoseSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE ));
|
||||
std::string skinBindPoseName = name + "_skin_bind_pose";
|
||||
pDomSkinBindPoseSource->setId(skinBindPoseName.c_str());
|
||||
|
||||
domListOfFloats matrices; // TODO fill with bind matrices
|
||||
int numMatrices = 0; // TODO number of bind matrices
|
||||
domFloat_array* pDomMatricesArray = daeSafeCast< domFloat_array >(pDomSkinBindPoseSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string matricesArrayName = name + "_matrices_array";
|
||||
pDomMatricesArray->setId(matricesArrayName.c_str());
|
||||
pDomMatricesArray->setCount(numMatrices);
|
||||
pDomMatricesArray->setValue(matrices);
|
||||
{
|
||||
domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSkinBindPoseSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
std::string url = "#" + matricesArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
pDomAccessor->setStride(16);
|
||||
|
||||
domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT4X4);
|
||||
}
|
||||
|
||||
domSource* pDomSkinWeightsSource = daeSafeCast< domSource >(pDomSkin->add( COLLADA_ELEMENT_SOURCE ));
|
||||
std::string skinWeightsName = name + "_skin_weights";
|
||||
pDomSkinWeightsSource->setId(skinWeightsName.c_str());
|
||||
|
||||
domListOfFloats weights; // TODO fill with vertex weights
|
||||
int numWeights = 0; // TODO number of vertices vertex weights
|
||||
domFloat_array* pDomWeightsArray = daeSafeCast< domFloat_array >(pDomSkinWeightsSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
std::string weightsArrayName = name + "_weights_array";
|
||||
pDomWeightsArray->setId(weightsArrayName.c_str());
|
||||
pDomWeightsArray->setCount(numWeights);
|
||||
pDomWeightsArray->setValue(weights);
|
||||
{
|
||||
domSource::domTechnique_common* pDomSourceTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomSkinWeightsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
|
||||
domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomSourceTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
std::string url = "#" + weightsArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
pDomAccessor->setCount(size);
|
||||
|
||||
domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
domSkin::domJoints* pDomJoints = daeSafeCast< domSkin::domJoints >(pDomSkin->add( COLLADA_ELEMENT_JOINTS ));
|
||||
|
||||
domInputLocal* pDomInput = daeSafeCast< domInputLocal >(pDomJoints->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_JOINT);
|
||||
url = "#" + skinJointsName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
pDomInput = daeSafeCast< domInputLocal >(pDomJoints->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInput->setSemantic(COMMON_PROFILE_INPUT_INV_BIND_MATRIX);
|
||||
url = "#" + skinBindPoseName;
|
||||
pDomInput->setSource(url.c_str());
|
||||
|
||||
domSkin::domVertex_weights* pDomVertexWeights = daeSafeCast< domSkin::domVertex_weights >(pDomSkin->add( COLLADA_ELEMENT_VERTEX_WEIGHTS ));
|
||||
pDomVertexWeights->setCount(0);// TODO set number of vertex weights
|
||||
|
||||
domInputLocalOffset* pDomInputLocalOffset = daeSafeCast< domInputLocalOffset >(pDomVertexWeights->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInputLocalOffset->setSemantic(COMMON_PROFILE_INPUT_JOINT);
|
||||
url = "#" + skinJointsName;
|
||||
pDomInputLocalOffset->setSource(url.c_str());
|
||||
pDomInputLocalOffset->setOffset(0);
|
||||
|
||||
pDomInputLocalOffset = daeSafeCast< domInputLocalOffset >(pDomVertexWeights->add(COLLADA_ELEMENT_INPUT));
|
||||
pDomInputLocalOffset->setSemantic(COMMON_PROFILE_INPUT_WEIGHT);
|
||||
url = "#" + weightsArrayName;
|
||||
pDomInputLocalOffset->setSource(url.c_str());
|
||||
pDomInputLocalOffset->setOffset(1);
|
||||
|
||||
domSkin::domVertex_weights::domVcount* pDomVcount = daeSafeCast< domSkin::domVertex_weights::domVcount >(pDomVertexWeights->add(COLLADA_ELEMENT_VCOUNT));
|
||||
domListOfUInts valueCounts;
|
||||
// TODO
|
||||
pDomVcount->setValue(valueCounts);
|
||||
domSkin::domVertex_weights::domV* pDomV = daeSafeCast< domSkin::domVertex_weights::domV >(pDomVertexWeights->add(COLLADA_ELEMENT_V));
|
||||
domListOfInts values;
|
||||
//TODO
|
||||
pDomV->setValue(values);
|
||||
}
|
||||
}
|
||||
|
||||
if (pDomController)
|
||||
{
|
||||
// Link <instance_controller> to cache hit or created <controller>
|
||||
domInstance_controller* pDomInstanceController = daeSafeCast< domInstance_controller >( currentNode->add( COLLADA_ELEMENT_INSTANCE_CONTROLLER ) );
|
||||
std::string url = "#" + std::string(pDomController->getId());
|
||||
pDomInstanceController->setUrl( url.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
void daeWriter::writeMorphGeometry(osgAnimation::MorphGeometry *pOsgMorphGeometry)
|
||||
{
|
||||
// See if controller exists in cache
|
||||
OsgMorphGeometryDomControllerMap::iterator iter = _osgMorphGeometryDomControllerMap.find(pOsgMorphGeometry);
|
||||
domController* pDomController = NULL;
|
||||
if ( iter != _osgMorphGeometryDomControllerMap.end() )
|
||||
{
|
||||
pDomController = iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
domGeometry* pDomGeometry = getOrCreateDomGeometry(pOsgMorphGeometry);
|
||||
if (pDomGeometry)
|
||||
{
|
||||
if (!lib_controllers)
|
||||
{
|
||||
lib_controllers = daeSafeCast< domLibrary_controllers >( dom->add( COLLADA_ELEMENT_LIBRARY_CONTROLLERS ) );
|
||||
}
|
||||
|
||||
// <controller>
|
||||
// 1 <morph source (method)>
|
||||
// 2..* <source>
|
||||
// 1 <targets>
|
||||
// 2..* <input semantic source>
|
||||
// 0..* <extra>
|
||||
// 0..* <extra>
|
||||
pDomController = daeSafeCast< domController >( lib_controllers->add( COLLADA_ELEMENT_CONTROLLER) );
|
||||
std::string name = pOsgMorphGeometry->getName();
|
||||
if (name.empty())
|
||||
name = uniquify("morphcontroller");
|
||||
else
|
||||
name = uniquify(name);
|
||||
pDomController->setId( name.c_str() );
|
||||
_osgMorphGeometryDomControllerMap.insert( std::make_pair( pOsgMorphGeometry, pDomController ) );
|
||||
|
||||
// Link <morph> to cache hit or created <geometry>
|
||||
domMorph* pDomMorph = daeSafeCast< domMorph >(pDomController->add( COLLADA_ELEMENT_MORPH ));
|
||||
std::string url = "#" + std::string(pDomGeometry->getId());
|
||||
pDomMorph->setSource(url.c_str());
|
||||
pDomMorph->setMethod(MORPHMETHODTYPE_NORMALIZED);
|
||||
//pDomMorph->setMethod(MORPHMETHODTYPE_RELATIVE);
|
||||
|
||||
domSource* pDomTargetsSource = daeSafeCast< domSource >(pDomMorph->add( COLLADA_ELEMENT_SOURCE ));
|
||||
std::string targetsName = name + "_morph_targets";
|
||||
pDomTargetsSource->setId(targetsName.c_str());
|
||||
|
||||
domIDREF_array* pDomIDREFArray = daeSafeCast< domIDREF_array >(pDomTargetsSource->add(COLLADA_ELEMENT_IDREF_ARRAY));
|
||||
xsIDREFS idrefs;
|
||||
osgAnimation::MorphGeometry::MorphTargetList morphTargetList = pOsgMorphGeometry->getMorphTargetList();
|
||||
for (unsigned int i=0; i < morphTargetList.size(); i++)
|
||||
{
|
||||
domGeometry* pDomGeometry = getOrCreateDomGeometry(morphTargetList[i].getGeometry());
|
||||
idrefs.append(pDomGeometry->getId());
|
||||
}
|
||||
pDomIDREFArray->setValue(idrefs);
|
||||
std::string targetsArrayName = targetsName + "_array";
|
||||
pDomIDREFArray->setId(targetsArrayName.c_str());
|
||||
pDomIDREFArray->setCount(morphTargetList.size());
|
||||
|
||||
domSource::domTechnique_common* pDomTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomTargetsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
domAccessor* pDomAccessor = daeSafeCast< domAccessor >(pDomTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
pDomAccessor->setCount(morphTargetList.size());
|
||||
url = "#" + targetsArrayName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
|
||||
domParam* pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName(COMMON_PROFILE_INPUT_MORPH_TARGET);
|
||||
pDomParam->setType("IDREF"); // COLLADA_TYPE_IDREF does not exist
|
||||
|
||||
domSource* pDomWeightsSource = daeSafeCast< domSource >(pDomMorph->add( COLLADA_ELEMENT_SOURCE ));
|
||||
std::string weightsName = name + "_morph_weights";
|
||||
pDomWeightsSource->setId(weightsName.c_str());
|
||||
|
||||
domFloat_array* pDomFloatArray = daeSafeCast< domFloat_array >(pDomWeightsSource->add(COLLADA_ELEMENT_FLOAT_ARRAY));
|
||||
domListOfFloats weights;
|
||||
for (unsigned int i=0; i < morphTargetList.size(); i++)
|
||||
{
|
||||
weights.append(morphTargetList[i].getWeight());
|
||||
}
|
||||
pDomFloatArray->setValue(weights);
|
||||
std::string weigthsArrayName = weightsName + "_array";
|
||||
pDomFloatArray->setId(weigthsArrayName.c_str());
|
||||
pDomFloatArray->setCount(morphTargetList.size());
|
||||
|
||||
pDomTechniqueCommon = daeSafeCast< domSource::domTechnique_common >(pDomWeightsSource->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
pDomAccessor = daeSafeCast< domAccessor >(pDomTechniqueCommon->add(COLLADA_ELEMENT_ACCESSOR));
|
||||
pDomAccessor->setCount(morphTargetList.size());
|
||||
url = "#" + weightsName;
|
||||
pDomAccessor->setSource(url.c_str());
|
||||
|
||||
pDomParam = daeSafeCast< domParam >(pDomAccessor->add(COLLADA_ELEMENT_PARAM));
|
||||
pDomParam->setName(COMMON_PROFILE_INPUT_MORPH_WEIGHT);
|
||||
pDomParam->setType(COLLADA_TYPE_FLOAT);
|
||||
|
||||
domMorph::domTargets* pDomTargets = daeSafeCast< domMorph::domTargets >(pDomMorph->add( COLLADA_ELEMENT_TARGETS ));
|
||||
|
||||
domInputLocal* pDomTargetsInput = daeSafeCast< domInputLocal >(pDomTargets->add( COLLADA_ELEMENT_INPUT ));
|
||||
pDomTargetsInput->setSemantic(COMMON_PROFILE_INPUT_MORPH_TARGET);
|
||||
url = "#" + targetsName;
|
||||
pDomTargetsInput->setSource(url.c_str());
|
||||
|
||||
domInputLocal* pDomWeightsInput = daeSafeCast< domInputLocal >(pDomTargets->add( COLLADA_ELEMENT_INPUT ));
|
||||
pDomWeightsInput->setSemantic(COMMON_PROFILE_INPUT_MORPH_WEIGHT);
|
||||
url = "#" + weightsName;
|
||||
pDomWeightsInput->setSource(url.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (pDomController)
|
||||
{
|
||||
// Transparency at drawable level
|
||||
if (pOsgMorphGeometry->getStateSet())
|
||||
m_CurrentRenderingHint = pOsgMorphGeometry->getStateSet()->getRenderingHint();
|
||||
|
||||
pushStateSet(pOsgMorphGeometry->getStateSet());
|
||||
|
||||
// Link <instance_controller> to cache hit or created <controller>
|
||||
domInstance_controller* pDomInstanceController = daeSafeCast< domInstance_controller >( currentNode->add( COLLADA_ELEMENT_INSTANCE_CONTROLLER ) );
|
||||
std::string url = "#" + std::string(pDomController->getId());
|
||||
pDomInstanceController->setUrl( url.c_str() );
|
||||
|
||||
if (!stateSetStack.empty())
|
||||
{
|
||||
domBind_material *pDomBindMaterial = daeSafeCast< domBind_material >( pDomInstanceController->add( COLLADA_ELEMENT_BIND_MATERIAL ) );
|
||||
processMaterial( currentStateSet.get(), pDomBindMaterial, pOsgMorphGeometry->getName() );
|
||||
}
|
||||
|
||||
popStateSet(pOsgMorphGeometry->getStateSet());
|
||||
}
|
||||
}
|
||||
|
||||
void daeWriter::apply( osg::Geode &node )
|
||||
{
|
||||
@@ -42,53 +380,50 @@ void daeWriter::apply( osg::Geode &node )
|
||||
|
||||
if ( g != NULL )
|
||||
{
|
||||
// Transparency at drawable level
|
||||
if (NULL != g->getStateSet())
|
||||
m_CurrentRenderingHint = g->getStateSet()->getRenderingHint();
|
||||
|
||||
pushStateSet(g->getStateSet());
|
||||
std::map< osg::Geometry*, domGeometry *>::iterator iter = geometryMap.find( g );
|
||||
if ( iter != geometryMap.end() )
|
||||
osgAnimation::RigGeometry *pOsgRigGeometry = dynamic_cast<osgAnimation::RigGeometry*>(g);
|
||||
if (pOsgRigGeometry)
|
||||
{
|
||||
domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->add( COLLADA_ELEMENT_INSTANCE_GEOMETRY ) );
|
||||
|
||||
std::string url = "#" + std::string( iter->second->getId() );
|
||||
ig->setUrl( url.c_str() );
|
||||
if (!stateSetStack.empty())
|
||||
processMaterial( currentStateSet.get(), ig, iter->second->getId() );
|
||||
writeRigGeometry(pOsgRigGeometry);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lib_geoms == NULL )
|
||||
osgAnimation::MorphGeometry *pOsgMorphGeometry = dynamic_cast<osgAnimation::MorphGeometry*>(g);
|
||||
if (pOsgMorphGeometry)
|
||||
{
|
||||
lib_geoms = daeSafeCast< domLibrary_geometries >( dom->add( COLLADA_ELEMENT_LIBRARY_GEOMETRIES ) );
|
||||
writeMorphGeometry(pOsgMorphGeometry);
|
||||
}
|
||||
std::string name = node.getName();
|
||||
if ( name.empty() ) name = "geometry";
|
||||
name = uniquify( name );
|
||||
|
||||
domGeometryRef geo = daeSafeCast< domGeometry >( lib_geoms->add( COLLADA_ELEMENT_GEOMETRY ) );
|
||||
geo->setId( name.c_str() );
|
||||
|
||||
if ( !processGeometry( g, geo, name ) )
|
||||
else
|
||||
{
|
||||
daeElement::removeFromParent( geo );
|
||||
continue;
|
||||
}
|
||||
// Write a default osg::Geometry
|
||||
|
||||
domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->add( COLLADA_ELEMENT_INSTANCE_GEOMETRY ) );
|
||||
// Transparency at drawable level
|
||||
if (NULL != g->getStateSet())
|
||||
m_CurrentRenderingHint = g->getStateSet()->getRenderingHint();
|
||||
|
||||
pushStateSet(g->getStateSet());
|
||||
|
||||
std::string url = "#" + name;
|
||||
ig->setUrl( url.c_str() );
|
||||
domGeometry* pDomGeometry = getOrCreateDomGeometry(g);
|
||||
if (pDomGeometry)
|
||||
{
|
||||
// Link <instance_geometry> to cache hit or created <geometry>
|
||||
domInstance_geometry *pDomInstanceGeometry = daeSafeCast< domInstance_geometry >( currentNode->add( COLLADA_ELEMENT_INSTANCE_GEOMETRY ) );
|
||||
std::string url = "#" + std::string(pDomGeometry->getId());
|
||||
pDomInstanceGeometry->setUrl( url.c_str() );
|
||||
|
||||
#ifndef EARTH_GEO
|
||||
geometryMap.insert( std::make_pair( g, geo ) );
|
||||
#endif
|
||||
if (!stateSetStack.empty())
|
||||
{
|
||||
domBind_material *pDomBindMaterial = daeSafeCast< domBind_material >( pDomInstanceGeometry->add( COLLADA_ELEMENT_BIND_MATERIAL ) );
|
||||
processMaterial( currentStateSet.get(), pDomBindMaterial, pDomGeometry->getId() );
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateSetStack.empty())
|
||||
processMaterial( currentStateSet.get(), ig, name );
|
||||
popStateSet(g->getStateSet());
|
||||
}
|
||||
}
|
||||
popStateSet(g->getStateSet());
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Non-geometry drawables are not supported" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,36 +477,40 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
domSource *norm = NULL;
|
||||
domSource *color = NULL;
|
||||
std::vector< domSource * >texcoord;
|
||||
std::vector< domSource * > vertexAttribute;
|
||||
domLines *lines = NULL;
|
||||
domLinestrips *linestrips = NULL;
|
||||
domTriangles *tris = NULL;
|
||||
domTristrips *tristrips = NULL;
|
||||
domTrifans *trifans = NULL;
|
||||
domPolygons *polys = NULL;
|
||||
domPolylist *polylist = NULL;
|
||||
domPolylist *polylist = NULL;
|
||||
|
||||
//TODO: Make sure the assumptions about arrays is correct.
|
||||
// Probably not so I should make each thing more flexible so arrays can be different sizes.
|
||||
|
||||
/*osg::Vec3Array *verts = (osg::Vec3Array *)geom->getVertexArray();
|
||||
osg::IndexArray *vertInds = geom->getVertexIndices();
|
||||
|
||||
osg::Vec3Array *normals = (osg::Vec3Array *)geom->getNormalArray();
|
||||
osg::IndexArray *normalInds = geom->getNormalIndices();
|
||||
|
||||
osg::Vec4Array *colors = (osg::Vec4Array *)geom->getColorArray();
|
||||
osg::IndexArray *colorInds = geom->getColorIndices();*/
|
||||
|
||||
ArrayNIndices verts( geom->getVertexArray(), geom->getVertexIndices() );
|
||||
ArrayNIndices normals( geom->getNormalArray(), geom->getNormalIndices() );
|
||||
ArrayNIndices colors( geom->getColorArray(), geom->getColorIndices() );
|
||||
|
||||
// RS BUG
|
||||
// getNumTexCoordArrays may return larger number
|
||||
// where getTexCoordArray(0) may have a BIND_OFF and an empty arrat
|
||||
std::vector<ArrayNIndices> texcoords;
|
||||
for ( unsigned int i = 0; i < geom->getNumTexCoordArrays(); i++ )
|
||||
{
|
||||
texcoords.push_back( ArrayNIndices( geom->getTexCoordArray( i ), geom->getTexCoordIndices( i ) ) );
|
||||
if (geom->getTexCoordArray(i))
|
||||
{
|
||||
texcoords.push_back( ArrayNIndices( geom->getTexCoordArray( i ), geom->getTexCoordIndices( i ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
//process POSITION
|
||||
std::vector<ArrayNIndices> vertexAttributes;
|
||||
for ( unsigned int i = 0; i < geom->getNumVertexAttribArrays(); i++ )
|
||||
{
|
||||
if (geom->getVertexAttribArray(i))
|
||||
{
|
||||
vertexAttributes.push_back(ArrayNIndices( geom->getVertexAttribArray( i ), geom->getVertexAttribIndices(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// process POSITION
|
||||
std::string sName = name + "-positions";
|
||||
pos = createSource( mesh, sName, verts.mode );
|
||||
|
||||
@@ -218,8 +557,8 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
vertices->setId( vName.c_str() );
|
||||
|
||||
//make a POSITION input in it
|
||||
domInputLocal *il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT) );
|
||||
il->setSemantic(COMMON_PROFILE_INPUT_POSITION);
|
||||
domInputLocal *il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT ) );
|
||||
il->setSemantic( COMMON_PROFILE_INPUT_POSITION );
|
||||
std::string url = "#" + std::string( pos->getId() );
|
||||
il->setSource( url.c_str() );
|
||||
|
||||
@@ -272,8 +611,8 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
|
||||
//if NORMAL shares same indices as POSITION put it in the vertices
|
||||
/*if ( normalInds == vertInds && vertInds != NULL ) {
|
||||
il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT) );
|
||||
il->setSemantic(COMMON_PROFILE_INPUT_NORMAL);
|
||||
il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT ) );
|
||||
il->setSemantic( COMMON_PROFILE_INPUT_NORMAL );
|
||||
url = "#" + std::string(md->norm->getId());
|
||||
il->setSource( url.c_str() );
|
||||
}*/
|
||||
@@ -323,8 +662,8 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
}
|
||||
//if COLOR shares same indices as POSITION put it in the vertices
|
||||
/*if ( colorInds == vertInds && vertInds != NULL ) {
|
||||
il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT) );
|
||||
il->setSemantic(COMMON_PROFILE_INPUT_COLOR);
|
||||
il = daeSafeCast< domInputLocal >( vertices->add( COLLADA_ELEMENT_INPUT ) );
|
||||
il->setSemantic( COMMON_PROFILE_INPUT_COLOR );
|
||||
url = "#" + std::string(md->color->getId());
|
||||
il->setSource( url.c_str() );
|
||||
}*/
|
||||
@@ -365,10 +704,10 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
t->getTechnique_common()->getAccessor()->setCount( texcoords[ti].vec4->size() );
|
||||
for ( unsigned int i = 0; i < texcoords[ti].vec4->size(); i++ )
|
||||
{
|
||||
t->getFloat_array()->getValue().append( (*texcoords[i].vec4)[ti].x() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[i].vec4)[ti].y() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[i].vec4)[ti].z() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[i].vec4)[ti].w() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].x() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].y() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].z() );
|
||||
t->getFloat_array()->getValue().append( (*texcoords[ti].vec4)[i].w() );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -379,6 +718,63 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st
|
||||
texcoord.push_back( t );
|
||||
}
|
||||
|
||||
//RS
|
||||
//process TEXCOORD
|
||||
//TODO: Do the same as normal and colors for texcoods. But in a loop since you can have many
|
||||
for ( unsigned int ti = 0; ti < vertexAttributes.size(); ti++ )
|
||||
{
|
||||
if (vertexAttributes[ti].mode != ArrayNIndices::NONE)
|
||||
{
|
||||
std::ostringstream intstr;
|
||||
intstr << std::dec << ti;
|
||||
sName = name + "-vertexAttribute_" + intstr.str();
|
||||
|
||||
domSource *t = createSource( mesh, sName, vertexAttributes[ti].mode, false, true );
|
||||
switch( vertexAttributes[ti].mode )
|
||||
{
|
||||
case ArrayNIndices::VEC2:
|
||||
t->getFloat_array()->setCount( vertexAttributes[ti].vec2->size() *2 );
|
||||
t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec2->size() );
|
||||
for ( unsigned int i = 0; i < vertexAttributes[ti].vec2->size(); i++ )
|
||||
{
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec2)[i].x() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec2)[i].y() );
|
||||
}
|
||||
break;
|
||||
case ArrayNIndices::VEC3:
|
||||
t->getFloat_array()->setCount( vertexAttributes[ti].vec3->size() *3 );
|
||||
t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec3->size() );
|
||||
for ( unsigned int i = 0; i < vertexAttributes[ti].vec3->size(); i++ )
|
||||
{
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].x() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].y() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec3)[i].z() );
|
||||
}
|
||||
break;
|
||||
case ArrayNIndices::VEC4:
|
||||
t->getFloat_array()->setCount( vertexAttributes[ti].vec4->size() *4 );
|
||||
t->getTechnique_common()->getAccessor()->setCount( vertexAttributes[ti].vec4->size() );
|
||||
for ( unsigned int i = 0; i < vertexAttributes[ti].vec4->size(); i++ )
|
||||
{
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].x() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].y() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].z() );
|
||||
t->getFloat_array()->getValue().append( (*vertexAttributes[ti].vec4)[i].w() );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//##ti and not i
|
||||
osg::notify( osg::WARN ) << "Invalid array type for vertex attribute" << ti << std::endl;
|
||||
break;
|
||||
}
|
||||
vertexAttribute.push_back( t );
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify( osg::WARN ) << "Invalid array type for vertex attribute" << ti << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//process each primitive group
|
||||
unsigned int ncount = 0; //Normal index counter
|
||||
unsigned int ccount = 0; //Color index counter
|
||||
@@ -1135,32 +1531,32 @@ Ty *daeWriter::createPrimGroup( daeString type, domMesh *mesh, domSource *norm,
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
Ty *retVal = daeSafeCast< Ty >( mesh->add( type ) );
|
||||
domInputLocalOffset *ilo = daeSafeCast< domInputLocalOffset >(retVal->add( COLLADA_ELEMENT_INPUT));
|
||||
domInputLocalOffset *ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) );
|
||||
ilo->setOffset( offset++ );
|
||||
ilo->setSemantic(COMMON_PROFILE_INPUT_VERTEX);
|
||||
ilo->setSemantic( COMMON_PROFILE_INPUT_VERTEX );
|
||||
std::string url = "#" + std::string(mesh->getVertices()->getId());
|
||||
ilo->setSource( url.c_str() );
|
||||
if ( norm != NULL )
|
||||
{
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add(COLLADA_ELEMENT_INPUT));
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) );
|
||||
ilo->setOffset( offset++ );
|
||||
ilo->setSemantic( COMMON_PROFILE_INPUT_NORMAL);
|
||||
ilo->setSemantic( COMMON_PROFILE_INPUT_NORMAL );
|
||||
url = "#" + std::string( norm->getId() );
|
||||
ilo->setSource( url.c_str() );
|
||||
}
|
||||
if ( color != NULL )
|
||||
{
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add(COLLADA_ELEMENT_INPUT));
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) );
|
||||
ilo->setOffset( offset++ );
|
||||
ilo->setSemantic(COMMON_PROFILE_INPUT_COLOR);
|
||||
ilo->setSemantic( COMMON_PROFILE_INPUT_COLOR );
|
||||
url = "#" + std::string( color->getId() );
|
||||
ilo->setSource( url.c_str() );
|
||||
}
|
||||
for ( unsigned int i = 0; i < texcoord.size(); i++ )
|
||||
{
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add(COLLADA_ELEMENT_INPUT));
|
||||
ilo = daeSafeCast< domInputLocalOffset >( retVal->add( COLLADA_ELEMENT_INPUT ) );
|
||||
ilo->setOffset( offset++ );
|
||||
ilo->setSemantic(COMMON_PROFILE_INPUT_TEXCOORD);
|
||||
ilo->setSemantic( COMMON_PROFILE_INPUT_TEXCOORD );
|
||||
ilo->setSet( i );
|
||||
url = "#" + std::string( texcoord[i]->getId() );
|
||||
ilo->setSource( url.c_str() );
|
||||
|
||||
@@ -28,22 +28,22 @@
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, const std::string &geoName )
|
||||
void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMaterial, const std::string &geoName )
|
||||
{
|
||||
osg::ref_ptr<osg::StateSet> ssClean = CleanStateSet(ss); // Need to hold a ref to this or the materialMap.find() will delete it
|
||||
domBind_material *bm = daeSafeCast< domBind_material >( ig->add( COLLADA_ELEMENT_BIND_MATERIAL ) );
|
||||
domBind_material::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( bm->add(COLLADA_ELEMENT_TECHNIQUE_COMMON));
|
||||
domInstance_material *im = daeSafeCast< domInstance_material >( tc->add( COLLADA_ELEMENT_INSTANCE_MATERIAL ) );
|
||||
domBind_material::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( pDomBindMaterial->add( COLLADA_ELEMENT_TECHNIQUE_COMMON ) );
|
||||
domInstance_material *pDomInstanceMaterial = daeSafeCast< domInstance_material >( tc->add( COLLADA_ELEMENT_INSTANCE_MATERIAL ) );
|
||||
std::string symbol = geoName + "_material";
|
||||
im->setSymbol( symbol.c_str() );
|
||||
pDomInstanceMaterial->setSymbol( symbol.c_str() );
|
||||
|
||||
// See if material already exists in cache
|
||||
MaterialMap::iterator iter = materialMap.find( ssClean );
|
||||
if ( iter != materialMap.end() )
|
||||
{
|
||||
std::string url = "#" + std::string( iter->second->getId() );
|
||||
im->setTarget( url.c_str() );
|
||||
pDomInstanceMaterial->setTarget( url.c_str() );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
mat->setId( name.c_str() );
|
||||
|
||||
std::string url = "#" + name;
|
||||
im->setTarget( url.c_str() );
|
||||
pDomInstanceMaterial->setTarget( url.c_str() );
|
||||
|
||||
domInstance_effect *ie = daeSafeCast<domInstance_effect>( mat->add( COLLADA_ELEMENT_INSTANCE_EFFECT ) );
|
||||
|
||||
@@ -82,7 +82,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
domProfile_COMMON *pc = daeSafeCast< domProfile_COMMON >( effect->add( COLLADA_ELEMENT_PROFILE_COMMON ) );
|
||||
domProfile_COMMON::domTechnique *pc_teq = daeSafeCast< domProfile_COMMON::domTechnique >( pc->add( COLLADA_ELEMENT_TECHNIQUE ) );
|
||||
pc_teq->setSid( "t0" );
|
||||
domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< domProfile_COMMON::domTechnique::domPhong >( pc_teq->add(COLLADA_ELEMENT_PHONG));
|
||||
domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< domProfile_COMMON::domTechnique::domPhong >( pc_teq->add( COLLADA_ELEMENT_PHONG ) );
|
||||
|
||||
osg::Texture *tex = static_cast<osg::Texture*>(ssClean->getTextureAttribute( 0, osg::StateAttribute::TEXTURE ));
|
||||
if ( ssClean->getTextureAttribute( 1, osg::StateAttribute::TEXTURE ) != NULL )
|
||||
@@ -97,31 +97,33 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
img->setId( iName.c_str() );
|
||||
|
||||
osg::Image *osgimg = tex->getImage( 0 );
|
||||
domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->add(COLLADA_ELEMENT_INIT_FROM));
|
||||
|
||||
domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->add( COLLADA_ELEMENT_INIT_FROM ) );
|
||||
std::string fileURI = ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(osgDB::findDataFile(osgimg->getFileName()));
|
||||
daeURI dd(*dae, fileURI);//fileURI.c_str() );
|
||||
daeURI dd(*dae, fileURI);
|
||||
imgif->setValue( dd );
|
||||
// The document URI should contain the canonical path it was created with
|
||||
imgif->getValue().makeRelativeTo(doc->getDocumentURI());
|
||||
|
||||
|
||||
#ifndef EARTH_TEX
|
||||
domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >(pc->add(COLLADA_ELEMENT_NEWPARAM));
|
||||
domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >( pc->add(COLLADA_ELEMENT_NEWPARAM) );
|
||||
std::string surfName = efName + "-surface";
|
||||
np->setSid( surfName.c_str() );
|
||||
domFx_surface_common *surface = daeSafeCast< domFx_surface_common >(np->add(COLLADA_ELEMENT_SURFACE));
|
||||
domFx_surface_init_from_common *sif = daeSafeCast< domFx_surface_init_from_common >( surface->add(COLLADA_ELEMENT_INIT_FROM));
|
||||
domFx_surface_common *surface = daeSafeCast< domFx_surface_common >( np->add(COLLADA_ELEMENT_SURFACE) );
|
||||
domFx_surface_init_from_common *sif = daeSafeCast< domFx_surface_init_from_common >( surface->add(COLLADA_ELEMENT_INIT_FROM) );
|
||||
sif->setValue( iName.c_str() );
|
||||
surface->setType( FX_SURFACE_TYPE_ENUM_2D );
|
||||
|
||||
np = daeSafeCast< domCommon_newparam_type >( pc->add(COLLADA_ELEMENT_NEWPARAM));
|
||||
np = daeSafeCast< domCommon_newparam_type >( pc->add( COLLADA_ELEMENT_NEWPARAM ) );
|
||||
std::string sampName = efName + "-sampler";
|
||||
np->setSid( sampName.c_str() );
|
||||
domFx_sampler2D_common *sampler = daeSafeCast< domFx_sampler2D_common >( np->add(COLLADA_ELEMENT_SAMPLER2D) );
|
||||
domFx_sampler2D_common_complexType::domSource *source = daeSafeCast< domFx_sampler2D_common_complexType::domSource >(sampler->add(COLLADA_ELEMENT_SOURCE));
|
||||
domFx_sampler2D_common *sampler = daeSafeCast< domFx_sampler2D_common >( np->add( COLLADA_ELEMENT_SAMPLER2D ) );
|
||||
domFx_sampler2D_common_complexType::domSource *source = daeSafeCast< domFx_sampler2D_common_complexType::domSource >( sampler->add( COLLADA_ELEMENT_SOURCE ) );
|
||||
source->setValue( surfName.c_str() );
|
||||
|
||||
//set sampler state
|
||||
domFx_sampler2D_common_complexType::domWrap_s *wrap_s = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_s >(sampler->add(COLLADA_ELEMENT_WRAP_S));
|
||||
domFx_sampler2D_common_complexType::domWrap_s *wrap_s = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_s >( sampler->add( COLLADA_ELEMENT_WRAP_S ) );
|
||||
osg::Texture::WrapMode wrap = tex->getWrap( osg::Texture::WRAP_S );
|
||||
switch( wrap )
|
||||
{
|
||||
@@ -143,7 +145,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
break;
|
||||
}
|
||||
|
||||
domFx_sampler2D_common_complexType::domWrap_t *wrap_t = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_t >(sampler->add( COLLADA_ELEMENT_WRAP_T));
|
||||
domFx_sampler2D_common_complexType::domWrap_t *wrap_t = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_t >( sampler->add( COLLADA_ELEMENT_WRAP_T ) );
|
||||
wrap = tex->getWrap( osg::Texture::WRAP_T );
|
||||
switch( wrap )
|
||||
{
|
||||
@@ -166,13 +168,13 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
}
|
||||
|
||||
const osg::Vec4 &bcol = tex->getBorderColor();
|
||||
domFx_sampler2D_common_complexType::domBorder_color *dbcol = daeSafeCast< domFx_sampler2D_common_complexType::domBorder_color >(sampler->add(COLLADA_ELEMENT_BORDER_COLOR));
|
||||
domFx_sampler2D_common_complexType::domBorder_color *dbcol = daeSafeCast< domFx_sampler2D_common_complexType::domBorder_color >( sampler->add( COLLADA_ELEMENT_BORDER_COLOR ) );
|
||||
dbcol->getValue().append( bcol.r() );
|
||||
dbcol->getValue().append( bcol.g() );
|
||||
dbcol->getValue().append( bcol.b() );
|
||||
dbcol->getValue().append( bcol.a() );
|
||||
|
||||
domFx_sampler2D_common_complexType::domMinfilter *minfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMinfilter >(sampler->add(COLLADA_ELEMENT_MINFILTER));
|
||||
domFx_sampler2D_common_complexType::domMinfilter *minfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMinfilter >( sampler->add( COLLADA_ELEMENT_MINFILTER ) );
|
||||
osg::Texture::FilterMode mode = tex->getFilter( osg::Texture::MIN_FILTER );
|
||||
switch( mode )
|
||||
{
|
||||
@@ -196,7 +198,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
break;
|
||||
}
|
||||
|
||||
domFx_sampler2D_common_complexType::domMagfilter *magfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMagfilter >(sampler->add(COLLADA_ELEMENT_MAGFILTER));
|
||||
domFx_sampler2D_common_complexType::domMagfilter *magfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMagfilter >( sampler->add( COLLADA_ELEMENT_MAGFILTER ) );
|
||||
mode = tex->getFilter( osg::Texture::MAG_FILTER );
|
||||
switch( mode )
|
||||
{
|
||||
@@ -221,20 +223,20 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
}
|
||||
|
||||
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_DIFFUSE) );
|
||||
domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >(cot->add(COLLADA_ELEMENT_TEXTURE));
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_DIFFUSE ) );
|
||||
domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->add( COLLADA_ELEMENT_TEXTURE ) );
|
||||
dtex->setTexture( sampName.c_str() );
|
||||
dtex->setTexcoord( "texcoord0" );
|
||||
#else
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_DIFFUSE) );
|
||||
domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->add(COLLADA_ELEMENT_TEXTURE));
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_DIFFUSE ) );
|
||||
domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->add( COLLADA_ELEMENT_TEXTURE ) );
|
||||
dtex->setTexture( iName.c_str() );
|
||||
dtex->setTexcoord( "texcoord0" );
|
||||
#endif
|
||||
|
||||
domInstance_material::domBind_vertex_input *bvi = daeSafeCast< domInstance_material::domBind_vertex_input >(im->add(COLLADA_ELEMENT_BIND_VERTEX_INPUT));
|
||||
domInstance_material::domBind_vertex_input *bvi = daeSafeCast< domInstance_material::domBind_vertex_input >( pDomInstanceMaterial->add( COLLADA_ELEMENT_BIND_VERTEX_INPUT ) );
|
||||
bvi->setSemantic( "texcoord0" );
|
||||
bvi->setInput_semantic( "TEXCOORD" );
|
||||
bvi->setInput_semantic( COMMON_PROFILE_INPUT_TEXCOORD );
|
||||
bvi->setInput_set( 0 );
|
||||
}
|
||||
osg::Material *osgmat = static_cast<osg::Material*>(ssClean->getAttribute( osg::StateAttribute::MATERIAL ));
|
||||
@@ -246,15 +248,15 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
const osg::Vec4 &sCol = osgmat->getSpecularFrontAndBack()?osgmat->getSpecular( osg::Material::FRONT_AND_BACK ):osgmat->getSpecular( osg::Material::FRONT );
|
||||
float shininess = osgmat->getShininessFrontAndBack()?osgmat->getShininess( osg::Material::FRONT_AND_BACK ):osgmat->getShininess( osg::Material::FRONT );
|
||||
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_EMISSION));
|
||||
domCommon_color_or_texture_type_complexType::domColor *col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add(COLLADA_ELEMENT_COLOR));
|
||||
domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_EMISSION ) );
|
||||
domCommon_color_or_texture_type_complexType::domColor *col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( COLLADA_ELEMENT_COLOR ) );
|
||||
col->getValue().append( eCol.r() );
|
||||
col->getValue().append( eCol.g() );
|
||||
col->getValue().append( eCol.b() );
|
||||
col->getValue().append( eCol.a() );
|
||||
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_AMBIENT));
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >(cot->add(COLLADA_ELEMENT_COLOR));
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_AMBIENT ) );
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( COLLADA_ELEMENT_COLOR ) );
|
||||
col->getValue().append( aCol.r() );
|
||||
col->getValue().append( aCol.g() );
|
||||
col->getValue().append( aCol.b() );
|
||||
@@ -264,8 +266,8 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
//### check if we really have a texture
|
||||
if ( phong->getDiffuse() == NULL )
|
||||
{
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_DIFFUSE));
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add(COLLADA_ELEMENT_COLOR));
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_DIFFUSE ) );
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( COLLADA_ELEMENT_COLOR ) );
|
||||
col->getValue().append( dCol.r() );
|
||||
col->getValue().append( dCol.g() );
|
||||
col->getValue().append( dCol.b() );
|
||||
@@ -290,7 +292,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
extra->setType( "color" );
|
||||
domTechnique *teq = daeSafeCast< domTechnique >( extra->add( COLLADA_ELEMENT_TECHNIQUE ) );
|
||||
teq->setProfile( "SCEI" );
|
||||
domAny *any = (domAny*)(daeElement*)teq->add(COLLADA_ELEMENT_COLOR);
|
||||
domAny *any = (domAny*)(daeElement*)teq->add( COLLADA_ELEMENT_COLOR );
|
||||
|
||||
std::ostringstream colVal;
|
||||
colVal << dCol.r() << " " << dCol.g() << " " << dCol.b() << " " << dCol.a();
|
||||
@@ -298,15 +300,15 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
}
|
||||
}
|
||||
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add(COLLADA_ELEMENT_SPECULAR));
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add(COLLADA_ELEMENT_COLOR));
|
||||
cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( COLLADA_ELEMENT_SPECULAR ) );
|
||||
col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( COLLADA_ELEMENT_COLOR ) );
|
||||
col->getValue().append( sCol.r() );
|
||||
col->getValue().append( sCol.g() );
|
||||
col->getValue().append( sCol.b() );
|
||||
col->getValue().append( sCol.a() );
|
||||
|
||||
domCommon_float_or_param_type *fop = daeSafeCast< domCommon_float_or_param_type >( phong->add(COLLADA_ELEMENT_SHININESS));
|
||||
domCommon_float_or_param_type_complexType::domFloat *f = daeSafeCast< domCommon_float_or_param_type_complexType::domFloat >( fop->add(COLLADA_ELEMENT_FLOAT));
|
||||
domCommon_float_or_param_type *fop = daeSafeCast< domCommon_float_or_param_type >( phong->add( COLLADA_ELEMENT_SHININESS ) );
|
||||
domCommon_float_or_param_type_complexType::domFloat *f = daeSafeCast< domCommon_float_or_param_type_complexType::domFloat >( fop->add(COLLADA_ELEMENT_FLOAT) );
|
||||
f->setValue( shininess );
|
||||
}
|
||||
|
||||
@@ -364,9 +366,9 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co
|
||||
}
|
||||
else if (tex != NULL && tex->getImage( 0 ) != NULL)
|
||||
{
|
||||
domCommon_transparent_type *ctt = daeSafeCast< domCommon_transparent_type >( phong->add(COLLADA_ELEMENT_TRANSPARENT));
|
||||
domCommon_transparent_type *ctt = daeSafeCast< domCommon_transparent_type >( phong->add(COLLADA_ELEMENT_TRANSPARENT) );
|
||||
ctt->setOpaque( FX_OPAQUE_ENUM_A_ONE );
|
||||
domCommon_color_or_texture_type_complexType::domTexture * dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( ctt->add(COLLADA_ELEMENT_TEXTURE));
|
||||
domCommon_color_or_texture_type_complexType::domTexture * dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( ctt->add(COLLADA_ELEMENT_TEXTURE) );
|
||||
|
||||
#ifndef EARTH_TEX
|
||||
std::string sampName = efName + "-sampler";
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <osg/Billboard>
|
||||
#include <osg/CameraView>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
// Write non-standard node data as extra of type "Node" with "OpenSceneGraph" technique
|
||||
void daeWriter::writeNodeExtra(osg::Node &node)
|
||||
@@ -128,6 +128,8 @@ void daeWriter::apply( osg::Group &node )
|
||||
}
|
||||
else
|
||||
{
|
||||
writeAnimations(node);
|
||||
|
||||
currentNode->setId(getNodeName(node,"group").c_str());
|
||||
}
|
||||
|
||||
@@ -353,19 +355,21 @@ void daeWriter::apply( osg::LightSource &node )
|
||||
{
|
||||
debugPrint( node );
|
||||
|
||||
domInstance_light *pDomInstanceLight = daeSafeCast< domInstance_light >( currentNode->add(COLLADA_ELEMENT_INSTANCE_LIGHT));
|
||||
domInstance_light *il = daeSafeCast< domInstance_light >( currentNode->add( COLLADA_ELEMENT_INSTANCE_LIGHT ) );
|
||||
std::string name = node.getName();
|
||||
if ( name.empty() )
|
||||
{
|
||||
name = uniquify( "light" );
|
||||
}
|
||||
std::string url = "#" + name;
|
||||
pDomInstanceLight->setUrl( url.c_str() );
|
||||
il->setUrl( url.c_str() );
|
||||
|
||||
if ( lib_lights == NULL )
|
||||
{
|
||||
lib_lights = daeSafeCast< domLibrary_lights >( dom->add( COLLADA_ELEMENT_LIBRARY_LIGHTS ) );
|
||||
}
|
||||
domLight *light = daeSafeCast< domLight >( lib_lights->add( COLLADA_ELEMENT_LIGHT ) );
|
||||
light->setId( name.c_str() );
|
||||
|
||||
osg::Light* pOsgLight = node.getLight();
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Copyright 2006 Sony Computer Entertainment Inc.
|
||||
*
|
||||
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
|
||||
* 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.
|
||||
* 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 "daeWriter.h"
|
||||
@@ -19,9 +19,42 @@
|
||||
#include <dom/domConstants.h>
|
||||
#include <dae/domAny.h>
|
||||
|
||||
#include <osgAnimation/Bone>
|
||||
#include <osgSim/DOFTransform>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
|
||||
void daeWriter::writeUpdateTransformElements(const osg::Vec3 &pos, const osg::Quat &q, const osg::Vec3 &s)
|
||||
{
|
||||
// Make a scale place element
|
||||
domScale *scale = daeSafeCast< domScale >( currentNode->add( COLLADA_ELEMENT_SCALE ) );
|
||||
scale->setSid("scale");
|
||||
scale->getValue().append3( s.x(), s.y(), s.z() );
|
||||
|
||||
// Make a three rotate place elements for the euler angles
|
||||
// TODO decompose quaternion into three euler angles
|
||||
double angle;
|
||||
osg::Vec3 axis;
|
||||
q.getRotate( angle, axis );
|
||||
|
||||
domRotate *rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) );
|
||||
rot->setSid("rotateZ");
|
||||
rot->getValue().append4( 0, 0, 1, osg::RadiansToDegrees(angle) );
|
||||
|
||||
rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) );
|
||||
rot->setSid("rotateY");
|
||||
rot->getValue().append4( 0, 1, 0, osg::RadiansToDegrees(angle) );
|
||||
|
||||
rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) );
|
||||
rot->setSid("rotateX");
|
||||
rot->getValue().append4( 1, 0, 0, osg::RadiansToDegrees(angle) );
|
||||
|
||||
// Make a translate place element
|
||||
domTranslate *trans = daeSafeCast< domTranslate >( currentNode->add( COLLADA_ELEMENT_TRANSLATE ) );
|
||||
trans->setSid("translate");
|
||||
trans->getValue().append3( pos.x(), pos.y(), pos.z() );
|
||||
}
|
||||
|
||||
//MATRIX
|
||||
void daeWriter::apply( osg::MatrixTransform &node )
|
||||
@@ -38,30 +71,43 @@ void daeWriter::apply( osg::MatrixTransform &node )
|
||||
}
|
||||
|
||||
currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) );
|
||||
currentNode->setId(getNodeName(node,"matrixTransform").c_str());
|
||||
|
||||
domMatrix *mat = daeSafeCast< domMatrix >(currentNode->add( COLLADA_ELEMENT_MATRIX ) );
|
||||
const osg::Matrix::value_type *mat_vals = node.getMatrix().ptr();
|
||||
//for ( int i = 0; i < 16; i++ )
|
||||
//{
|
||||
// mat->getValue().append( mat_vals[i] );
|
||||
//}
|
||||
mat->getValue().append( mat_vals[0] );
|
||||
mat->getValue().append( mat_vals[4] );
|
||||
mat->getValue().append( mat_vals[8] );
|
||||
mat->getValue().append( mat_vals[12] );
|
||||
mat->getValue().append( mat_vals[1] );
|
||||
mat->getValue().append( mat_vals[5] );
|
||||
mat->getValue().append( mat_vals[9] );
|
||||
mat->getValue().append( mat_vals[13] );
|
||||
mat->getValue().append( mat_vals[2] );
|
||||
mat->getValue().append( mat_vals[6] );
|
||||
mat->getValue().append( mat_vals[10] );
|
||||
mat->getValue().append( mat_vals[14] );
|
||||
mat->getValue().append( mat_vals[3] );
|
||||
mat->getValue().append( mat_vals[7] );
|
||||
mat->getValue().append( mat_vals[11] );
|
||||
mat->getValue().append( mat_vals[15] );
|
||||
std::string nodeName = getNodeName(node,"matrixTransform");
|
||||
currentNode->setId(nodeName.c_str());
|
||||
|
||||
osg::NodeCallback* ncb = node.getUpdateCallback();
|
||||
bool handled = false;
|
||||
if (ncb)
|
||||
{
|
||||
osgAnimation::UpdateMatrixTransform* ut = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(ncb);
|
||||
// If targeted by an animation we split up the matrix into multiple place element so they can be targeted individually
|
||||
if (ut)
|
||||
{
|
||||
handled = true;
|
||||
|
||||
const osg::Matrix &mat = node.getMatrix();
|
||||
|
||||
// Note: though this is a generic matrix, based on the fact that it will be animated by and UpdateMatrixTransform,
|
||||
// we assume the initial matrix can be decomposed into translation, rotation and scale elements
|
||||
writeUpdateTransformElements(mat.getTrans(), mat.getRotate(), mat.getScale());
|
||||
}
|
||||
}
|
||||
|
||||
// If not targeted by an animation simply write a single matrix place element
|
||||
if (!handled)
|
||||
{
|
||||
domMatrix *mat = daeSafeCast< domMatrix >(currentNode->add( COLLADA_ELEMENT_MATRIX ) );
|
||||
nodeName += "_matrix";
|
||||
mat->setSid(nodeName.c_str());
|
||||
|
||||
const osg::Matrix::value_type *mat_vals = node.getMatrix().ptr();
|
||||
for ( int i = 0; i < 4; i++ )
|
||||
{
|
||||
for ( int j = 0; j < 4; j++ )
|
||||
{
|
||||
mat->getValue().append( mat_vals[i + j*4] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastDepth = _nodePath.size();
|
||||
|
||||
@@ -84,41 +130,56 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node )
|
||||
lastDepth--;
|
||||
}
|
||||
currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) );
|
||||
currentNode->setId(getNodeName(node,"positionAttitudeTransform").c_str());
|
||||
|
||||
std::string nodeName = getNodeName(node,"positionAttitudeTransform");
|
||||
currentNode->setId(nodeName.c_str());
|
||||
|
||||
const osg::Vec3 &pos = node.getPosition();
|
||||
const osg::Quat &q = node.getAttitude();
|
||||
const osg::Vec3 &s = node.getScale();
|
||||
|
||||
if ( pos.x() != 0 || pos.y() != 0 || pos.z() != 0 )
|
||||
osg::NodeCallback* ncb = node.getUpdateCallback();
|
||||
bool handled = false;
|
||||
if (ncb)
|
||||
{
|
||||
//make a translate
|
||||
domTranslate *trans = daeSafeCast< domTranslate >( currentNode->add( COLLADA_ELEMENT_TRANSLATE ) );
|
||||
trans->getValue().append( pos.x() );
|
||||
trans->getValue().append( pos.y() );
|
||||
trans->getValue().append( pos.z() );
|
||||
osgAnimation::UpdateMatrixTransform* ut = dynamic_cast<osgAnimation::UpdateMatrixTransform*>(ncb);
|
||||
// If targeted by an animation we split up the matrix into multiple place element so they can be targeted individually
|
||||
if (ut)
|
||||
{
|
||||
handled = true;
|
||||
|
||||
writeUpdateTransformElements(pos, q, s);
|
||||
}
|
||||
}
|
||||
|
||||
double angle;
|
||||
osg::Vec3 axis;
|
||||
q.getRotate( angle, axis );
|
||||
if ( angle != 0 )
|
||||
// If not targeted by an animation simply add the elements that actually contribute to placement
|
||||
if (!handled)
|
||||
{
|
||||
//make a rotate
|
||||
domRotate *rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) );
|
||||
rot->getValue().append( axis.x() );
|
||||
rot->getValue().append( axis.y() );
|
||||
rot->getValue().append( axis.z() );
|
||||
rot->getValue().append( osg::RadiansToDegrees(angle) );
|
||||
}
|
||||
if ( s.x() != 1 || s.y() != 1 || s.z() != 1 )
|
||||
{
|
||||
// Make a scale place element
|
||||
domScale *scale = daeSafeCast< domScale >( currentNode->add( COLLADA_ELEMENT_SCALE ) );
|
||||
scale->setSid("scale");
|
||||
scale->getValue().append3( s.x(), s.y(), s.z() );
|
||||
}
|
||||
|
||||
double angle;
|
||||
osg::Vec3 axis;
|
||||
q.getRotate( angle, axis );
|
||||
if ( angle != 0 )
|
||||
{
|
||||
// Make a rotate place element
|
||||
domRotate *rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) );
|
||||
rot->setSid("rotate");
|
||||
rot->getValue().append4( axis.x(), axis.y(), axis.z(), osg::RadiansToDegrees(angle) );
|
||||
}
|
||||
|
||||
if ( s.x() != 1 || s.y() != 1 || s.z() != 1 )
|
||||
{
|
||||
//make a scale
|
||||
domScale *scale = daeSafeCast< domScale >( currentNode->add( COLLADA_ELEMENT_SCALE ) );
|
||||
scale->getValue().append( s.x() );
|
||||
scale->getValue().append( s.y() );
|
||||
scale->getValue().append( s.z() );
|
||||
{
|
||||
// Make a translate place element
|
||||
domTranslate *trans = daeSafeCast< domTranslate >( currentNode->add( COLLADA_ELEMENT_TRANSLATE ) );
|
||||
trans->setSid("translate");
|
||||
trans->getValue().append3( pos.x(), pos.y(), pos.z() );
|
||||
}
|
||||
}
|
||||
|
||||
writeNodeExtra(node);
|
||||
@@ -128,7 +189,7 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node )
|
||||
traverse( node );
|
||||
}
|
||||
|
||||
void daeWriter::apply( osg::Transform &node )
|
||||
void daeWriter::apply( osg::Transform &node )
|
||||
{
|
||||
debugPrint( node );
|
||||
|
||||
@@ -139,7 +200,7 @@ void daeWriter::apply( osg::Transform &node )
|
||||
lastDepth--;
|
||||
}
|
||||
currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) );
|
||||
|
||||
|
||||
// If a DOFTransform node store it's data as extra "DOFTransform" data in the "OpenSceneGraph" technique
|
||||
osgSim::DOFTransform* dof = dynamic_cast<osgSim::DOFTransform*>(&node);
|
||||
if (writeExtras && dof)
|
||||
@@ -223,14 +284,24 @@ void daeWriter::apply( osg::Transform &node )
|
||||
animationOn->setValue(toString<bool>(dof->getAnimationOn()).c_str());
|
||||
|
||||
domAny *putMatrix = (domAny*)teq->add("PutMatrix" );
|
||||
putMatrix->setValue(toString(dof->getPutMatrix()).c_str());
|
||||
putMatrix->setValue(toString(dof->getPutMatrix()).c_str());
|
||||
|
||||
currentNode->setId(getNodeName(node, "doftransform").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
currentNode->setId(getNodeName(node, "transform").c_str());
|
||||
osg::notify( osg::WARN ) << "some other transform type. Missing " << node.getNumChildren() << " children" << std::endl;
|
||||
osgAnimation::Bone* bone = dynamic_cast<osgAnimation::Bone*>(&node);
|
||||
if (bone)
|
||||
{
|
||||
domNode *pDomNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ));
|
||||
pDomNode->setType(NODETYPE_JOINT);
|
||||
pDomNode->setId(getNodeName(node, "bone").c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
currentNode->setId(getNodeName(node, "transform").c_str());
|
||||
osg::notify( osg::WARN ) << "some other transform type. Missing " << node.getNumChildren() << " children" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
writeNodeExtra(node);
|
||||
@@ -240,7 +311,9 @@ void daeWriter::apply( osg::Transform &node )
|
||||
traverse( node );
|
||||
}
|
||||
|
||||
void daeWriter::apply( osg::CoordinateSystemNode &node )
|
||||
void daeWriter::apply( osg::CoordinateSystemNode &node )
|
||||
{
|
||||
osg::notify( osg::WARN ) << "CoordinateSystemNode. Missing " << node.getNumChildren() << " children" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,16 +21,9 @@
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace osgdae {
|
||||
namespace osgDAE {
|
||||
|
||||
std::string toString(osg::Vec3f value)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << value.x() << " " << value.y() << " " << value.z();
|
||||
return str.str();
|
||||
}
|
||||
|
||||
std::string toString(osg::Vec3d value)
|
||||
std::string toString(osg::Vec3 value)
|
||||
{
|
||||
std::stringstream str;
|
||||
str << value.x() << " " << value.y() << " " << value.z();
|
||||
@@ -50,11 +43,11 @@ std::string toString(osg::Matrix value)
|
||||
|
||||
daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons, bool GoogleMode, TraversalMode tm, bool _writeExtras) : osg::NodeVisitor( tm ),
|
||||
dae(dae_),
|
||||
_domLibraryAnimations(NULL),
|
||||
writeExtras(_writeExtras),
|
||||
rootName(*dae_),
|
||||
usePolygons (_usePolygons),
|
||||
m_GoogleMode(GoogleMode),
|
||||
m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN)
|
||||
m_GoogleMode(GoogleMode)
|
||||
{
|
||||
success = true;
|
||||
|
||||
@@ -64,12 +57,12 @@ daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons,
|
||||
dae->getDatabase()->createDocument( fileURI.c_str(), &doc );
|
||||
dom = (domCOLLADA*)doc->getDomRoot();
|
||||
//create scene and instance visual scene
|
||||
domCOLLADA::domScene *scene = daeSafeCast< domCOLLADA::domScene >( dom->add(COLLADA_ELEMENT_SCENE));
|
||||
domInstanceWithExtra *ivs = daeSafeCast< domInstanceWithExtra >( scene->add(COLLADA_ELEMENT_INSTANCE_VISUAL_SCENE));
|
||||
domCOLLADA::domScene *scene = daeSafeCast< domCOLLADA::domScene >( dom->add( COLLADA_ELEMENT_SCENE ) );
|
||||
domInstanceWithExtra *ivs = daeSafeCast< domInstanceWithExtra >( scene->add( COLLADA_ELEMENT_INSTANCE_VISUAL_SCENE ) );
|
||||
ivs->setUrl( "#defaultScene" );
|
||||
//create library visual scenes and a visual scene and the root node
|
||||
lib_vis_scenes = daeSafeCast<domLibrary_visual_scenes>( dom->add(COLLADA_ELEMENT_LIBRARY_VISUAL_SCENES));
|
||||
vs = daeSafeCast< domVisual_scene >( lib_vis_scenes->add(COLLADA_ELEMENT_VISUAL_SCENE));
|
||||
lib_vis_scenes = daeSafeCast<domLibrary_visual_scenes>( dom->add( COLLADA_ELEMENT_LIBRARY_VISUAL_SCENES ) );
|
||||
vs = daeSafeCast< domVisual_scene >( lib_vis_scenes->add( COLLADA_ELEMENT_VISUAL_SCENE ) );
|
||||
vs->setId( "defaultScene" );
|
||||
currentNode = daeSafeCast< domNode >( vs->add( COLLADA_ELEMENT_NODE ) );
|
||||
currentNode->setId( "sceneRoot" );
|
||||
@@ -79,12 +72,16 @@ daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons,
|
||||
|
||||
lib_cameras = NULL;
|
||||
lib_effects = NULL;
|
||||
lib_controllers = NULL;
|
||||
lib_geoms = NULL;
|
||||
lib_lights = NULL;
|
||||
lib_mats = NULL;
|
||||
|
||||
lastDepth = 0;
|
||||
|
||||
// Clean up caches
|
||||
uniqueNames.clear();
|
||||
|
||||
currentStateSet = new osg::StateSet();
|
||||
}
|
||||
|
||||
@@ -104,20 +101,12 @@ void daeWriter::debugPrint( osg::Node &node )
|
||||
#endif
|
||||
}
|
||||
|
||||
bool daeWriter::writeFile()
|
||||
{
|
||||
if ( dae->save( (daeUInt)0 ) != DAE_OK )
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void daeWriter::setRootNode( const osg::Node &node )
|
||||
{
|
||||
std::string fname = osgDB::findDataFile( node.getName() );
|
||||
//rootName = fname.c_str();
|
||||
//rootName.validate();
|
||||
|
||||
const_cast<osg::Node*>(&node)->accept( _animatedNodeCollector );
|
||||
}
|
||||
|
||||
//### provide a name to node
|
||||
@@ -166,6 +155,8 @@ void daeWriter::createAssetTag()
|
||||
domAsset::domCreated *c = daeSafeCast< domAsset::domCreated >(asset->add(COLLADA_ELEMENT_CREATED));
|
||||
domAsset::domModified *m = daeSafeCast< domAsset::domModified >(asset->add(COLLADA_ELEMENT_MODIFIED));
|
||||
domAsset::domUnit *u = daeSafeCast< domAsset::domUnit >(asset->add(COLLADA_ELEMENT_UNIT));
|
||||
domAsset::domUp_axis *up = daeSafeCast< domAsset::domUp_axis >(asset->add(COLLADA_ELEMENT_UP_AXIS));
|
||||
up->setValue(UPAXISTYPE_Z_UP);
|
||||
|
||||
//TODO : set date and time
|
||||
c->setValue( "2006-07-25T00:00:00Z" );
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*
|
||||
* Copyright 2006 Sony Computer Entertainment Inc.
|
||||
*
|
||||
* Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DAE_WRITER_H_
|
||||
@@ -40,9 +40,14 @@
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgSim/MultiSwitch>
|
||||
#include <osgAnimation/AnimationManagerBase>
|
||||
#include <osgAnimation/UpdateBone>
|
||||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
#include <dae.h>
|
||||
#include <dae/daeDocument.h>
|
||||
#include <dom/domChannel.h>
|
||||
|
||||
|
||||
class domCOLLADA;
|
||||
@@ -54,6 +59,7 @@ class domLibrary_geometries;
|
||||
class domLibrary_lights;
|
||||
class domLibrary_materials;
|
||||
class domLibrary_visual_scenes;
|
||||
class domLibrary_animations;
|
||||
class domMaterial;
|
||||
class domMesh;
|
||||
class domNode;
|
||||
@@ -61,7 +67,7 @@ class domSource;
|
||||
class domVisual_scene;
|
||||
class domP;
|
||||
|
||||
namespace osgdae {
|
||||
namespace osgDAE {
|
||||
|
||||
/// Convert value to string using it's stream operator
|
||||
template <typename T>
|
||||
@@ -74,11 +80,56 @@ std::string toString(T value) {
|
||||
std::string toString(osg::Vec3f value);
|
||||
std::string toString(osg::Vec3d value);
|
||||
std::string toString(osg::Matrix value);
|
||||
|
||||
|
||||
// Collects all nodes that are targeted by an animation
|
||||
class FindAnimatedNodeVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
FindAnimatedNodeVisitor():
|
||||
osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
osg::NodeCallback* ncb = node.getUpdateCallback();
|
||||
if (ncb)
|
||||
{
|
||||
osgAnimation::AnimationUpdateCallback<osg::NodeCallback>* ut = dynamic_cast<osgAnimation::AnimationUpdateCallback<osg::NodeCallback>*>(ncb);
|
||||
if (ut)
|
||||
{
|
||||
if (_updateCallbackNameNodeMap[ut->getName()] == NULL)
|
||||
{
|
||||
_updateCallbackNameNodeMap[ut->getName()] = &node;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO store in a multimap and let the exporter create multiple <channel>s for each connected node
|
||||
osg::notify( osg::WARN ) << "Multiple nodes using the same update callback not supported" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
osg::Node* getTargetNode(const std::string& targetName)
|
||||
{
|
||||
UpdateCallbackNameNodeMap::iterator it = _updateCallbackNameNodeMap.find(targetName);
|
||||
if (it != _updateCallbackNameNodeMap.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map< std::string, osg::Node*> UpdateCallbackNameNodeMap;
|
||||
UpdateCallbackNameNodeMap _updateCallbackNameNodeMap;
|
||||
};
|
||||
|
||||
/**
|
||||
@class daeWriter
|
||||
@brief Write a OSG scene into a DAE file
|
||||
*/
|
||||
@brief Write a OSG scene into a DAE file
|
||||
*/
|
||||
class daeWriter : public osg::NodeVisitor
|
||||
{
|
||||
protected:
|
||||
@@ -116,33 +167,28 @@ public:
|
||||
//virtual void apply( osg::ClearNode &node)
|
||||
//virtual void apply( osg::OccluderNode &node)
|
||||
|
||||
void writeNodeExtra(osg::Node &node);
|
||||
|
||||
|
||||
|
||||
void traverse (osg::Node &node);
|
||||
|
||||
/*protected:
|
||||
struct MeshData {
|
||||
domMesh *mesh;
|
||||
domSource *pos;
|
||||
domSource *norm;
|
||||
domSource *color;
|
||||
std::vector< domSource * > texcoord;
|
||||
std::string name;
|
||||
};*/
|
||||
|
||||
|
||||
|
||||
|
||||
protected: //methods
|
||||
|
||||
void writeAnimations(osg::Node& node);
|
||||
void writeNodeExtra(osg::Node &node);
|
||||
void writeUpdateTransformElements(const osg::Vec3 &pos, const osg::Quat &q, const osg::Vec3 &s);
|
||||
void writeRigGeometry(osgAnimation::RigGeometry *pOsgRigGeometry);
|
||||
void writeMorphGeometry(osgAnimation::MorphGeometry *pOsgMorphGeometry);
|
||||
|
||||
void debugPrint( osg::Node &node );
|
||||
|
||||
|
||||
|
||||
domGeometry* getOrCreateDomGeometry(osg::Geometry* pOsgGeometry);
|
||||
bool processGeometry( osg::Geometry *geom, domGeometry *geo, const std::string &name );
|
||||
domSource* createSource( daeElement *parent, const std::string &baseName, int size, bool color = false, bool uv = false );
|
||||
template < typename Ty >
|
||||
Ty *createPrimGroup( daeString type, domMesh *mesh, domSource *norm, domSource *color, const std::vector< domSource* > &texcoord );
|
||||
|
||||
void processMaterial( osg::StateSet *ss, domInstance_geometry *ig, const std::string &geoName );
|
||||
void processMaterial( osg::StateSet *ss, domBind_material *pDomBindMaterial, const std::string &geoName );
|
||||
|
||||
void createAssetTag();
|
||||
|
||||
@@ -156,10 +202,12 @@ protected: //members
|
||||
domCOLLADA *dom;
|
||||
domLibrary_cameras *lib_cameras;
|
||||
domLibrary_effects *lib_effects;
|
||||
domLibrary_controllers *lib_controllers;
|
||||
domLibrary_geometries *lib_geoms;
|
||||
domLibrary_lights *lib_lights;
|
||||
domLibrary_materials *lib_mats;
|
||||
domLibrary_visual_scenes *lib_vis_scenes;
|
||||
domLibrary_animations* _domLibraryAnimations;
|
||||
domNode *currentNode;
|
||||
domVisual_scene *vs;
|
||||
|
||||
@@ -176,19 +224,20 @@ protected: //members
|
||||
return ss1->compare(*ss2, true) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
std::map< std::string, int > uniqueNames;
|
||||
|
||||
std::map< osg::Geometry*, domGeometry * > geometryMap;
|
||||
|
||||
typedef std::map< osg::ref_ptr<osg::StateSet>, domMaterial *, CompareStateSet> MaterialMap;
|
||||
typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
|
||||
typedef std::map< osg::Geometry*, domGeometry *> OsgGeometryDomGeometryMap;
|
||||
typedef std::map< osgAnimation::RigGeometry*, domController *> OsgRigGeometryDomControllerMap;
|
||||
typedef std::map< osgAnimation::MorphGeometry*, domController *> OsgMorphGeometryDomControllerMap;
|
||||
|
||||
std::map< std::string, int > uniqueNames;
|
||||
OsgGeometryDomGeometryMap geometryMap;
|
||||
OsgRigGeometryDomControllerMap _osgRigGeometryDomControllerMap;
|
||||
OsgMorphGeometryDomControllerMap _osgMorphGeometryDomControllerMap;
|
||||
|
||||
MaterialMap materialMap;
|
||||
|
||||
typedef std::stack<osg::ref_ptr<osg::StateSet> > StateSetStack;
|
||||
|
||||
StateSetStack stateSetStack;
|
||||
|
||||
osg::ref_ptr<osg::StateSet> currentStateSet;
|
||||
@@ -200,7 +249,7 @@ protected: //members
|
||||
osg::StateSet* CleanStateSet(osg::StateSet* pStateSet) const;
|
||||
|
||||
protected: //inner classes
|
||||
class ArrayNIndices
|
||||
class ArrayNIndices
|
||||
{
|
||||
public:
|
||||
enum Mode { NONE = 0, VEC2 = 2, VEC3 = 3, VEC4 = 4 };
|
||||
@@ -237,7 +286,7 @@ protected: //inner classes
|
||||
};
|
||||
|
||||
private: //members
|
||||
|
||||
|
||||
/** append elements (verts, normals, colors and texcoord) for file write */
|
||||
void appendGeometryIndices(osg::Geometry *geom,
|
||||
domP * p,
|
||||
@@ -253,7 +302,7 @@ private: //members
|
||||
|
||||
/** provide a name to node */
|
||||
std::string getNodeName(const osg::Node & node,const std::string & defaultName);
|
||||
|
||||
|
||||
/** provide an unique name */
|
||||
std::string uniquify( const std::string &name );
|
||||
|
||||
@@ -263,6 +312,8 @@ private: //members
|
||||
/** Current RenderingHint */
|
||||
/** This are needed because the stateSet merge code currently does not handle it */
|
||||
int m_CurrentRenderingHint;
|
||||
|
||||
FindAnimatedNodeVisitor _animatedNodeCollector;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include <dom/domSource.h>
|
||||
|
||||
using namespace osgdae;
|
||||
using namespace osgDAE;
|
||||
|
||||
domSourceReader::domSourceReader() : m_array_type( None ), m_count( 0 )
|
||||
{}
|
||||
@@ -32,7 +32,20 @@ domSourceReader::domSourceReader( domSource *src ) : m_array_type( None ), m_cou
|
||||
int stride = accessor->getStride();
|
||||
m_count = accessor->getCount();
|
||||
|
||||
switch ( stride ) {
|
||||
// Only handle floats or name array for now...
|
||||
daeDoubleArray* float_array = NULL;
|
||||
if (src->getFloat_array())
|
||||
{
|
||||
float_array = &(src->getFloat_array()->getValue());
|
||||
}
|
||||
else if (src->getName_array())
|
||||
{
|
||||
m_array_type = String;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (stride)
|
||||
{
|
||||
case 1:
|
||||
m_array_type = Float;
|
||||
m_float_array = new osg::FloatArray();
|
||||
@@ -49,39 +62,48 @@ domSourceReader::domSourceReader( domSource *src ) : m_array_type( None ), m_cou
|
||||
m_array_type = Vec4;
|
||||
m_vec4_array = new osg::Vec4Array();
|
||||
break;
|
||||
case 16:
|
||||
m_array_type = Matrix;
|
||||
m_matrix_array = new osg::MatrixfArray();
|
||||
break;
|
||||
default:
|
||||
osg::notify(osg::WARN)<<"Unsupported stride: "<<stride<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Only handle floats for now...
|
||||
daeDoubleArray* float_array = NULL;
|
||||
if ( src->getFloat_array() != NULL ) {
|
||||
float_array = &(src->getFloat_array()->getValue());
|
||||
}
|
||||
if ( !float_array ) {
|
||||
osg::notify(osg::WARN)<<"No float array found"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
daeDoubleArray& va = *float_array;
|
||||
for ( size_t i = 0; i < accessor->getCount(); i++ ) {
|
||||
switch ( accessor->getStride() ) {
|
||||
case 1:
|
||||
m_float_array->push_back( va[i] );
|
||||
break;
|
||||
case 2:
|
||||
m_vec2_array->push_back( osg::Vec2( va[i*2], va[i*2+1] ) );
|
||||
break;
|
||||
case 3:
|
||||
m_vec3_array->push_back( osg::Vec3( va[i*3], va[i*3+1], va[i*3+2] ) );
|
||||
break;
|
||||
case 4:
|
||||
m_vec4_array->push_back( osg::Vec4( va[i*4], va[i*4+1], va[i*4+2], va[i*4+3] ) );
|
||||
break;
|
||||
default:
|
||||
osg::notify(osg::WARN)<<"Unsupported stride in Source: "<<accessor->getStride()<<std::endl;
|
||||
return;
|
||||
if (float_array)
|
||||
{
|
||||
daeDoubleArray& va = *float_array;
|
||||
for ( size_t i = 0; i < accessor->getCount(); i++ )
|
||||
{
|
||||
switch ( accessor->getStride() )
|
||||
{
|
||||
case 1:
|
||||
m_float_array->push_back(va[i]);
|
||||
break;
|
||||
case 2:
|
||||
m_vec2_array->push_back( osg::Vec2( va[i*2], va[i*2+1]));
|
||||
break;
|
||||
case 3:
|
||||
m_vec3_array->push_back( osg::Vec3( va[i*3], va[i*3+1], va[i*3+2]));
|
||||
break;
|
||||
case 4:
|
||||
m_vec4_array->push_back( osg::Vec4( va[i*4], va[i*4+1], va[i*4+2], va[i*4+3]));
|
||||
break;
|
||||
case 16:
|
||||
m_matrix_array->push_back(osg::Matrixf( va[i*16+0], va[i*16+4], va[i*16+8], va[i*16+12],
|
||||
va[i*16+1], va[i*16+5], va[i*16+9], va[i*16+13],
|
||||
va[i*16+2], va[i*16+6], va[i*16+10], va[i*16+14],
|
||||
va[i*16+3], va[i*16+7], va[i*16+11], va[i*16+15]));
|
||||
break;
|
||||
default:
|
||||
osg::notify(osg::WARN) << "Unsupported stride in Source: " << accessor->getStride() << std::endl;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::WARN) << "No float array found" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
class domSource;
|
||||
|
||||
namespace osgdae {
|
||||
namespace osgDAE {
|
||||
|
||||
/**
|
||||
@class domSourceReader
|
||||
@@ -28,7 +28,7 @@ namespace osgdae {
|
||||
class domSourceReader
|
||||
{
|
||||
public:
|
||||
enum ArrayType {None,Float,Vec2,Vec3,Vec4};
|
||||
enum ArrayType {None,Float,Vec2,Vec3,Vec4,Matrix,String};
|
||||
|
||||
public:
|
||||
|
||||
@@ -44,7 +44,9 @@ public:
|
||||
osg::Vec3Array* getVec3Array() { return m_vec3_array.get(); };
|
||||
|
||||
osg::Vec4Array* getVec4Array() { return m_vec4_array.get(); };
|
||||
|
||||
|
||||
osg::MatrixfArray* getMatrixArray() { return m_matrix_array.get(); };
|
||||
|
||||
int getCount() const { return m_count; };
|
||||
|
||||
#define ASSERT_TYPE(type) if (type!=m_array_type) { osg::notify(osg::WARN)<<"Wrong array type requested ("#type" != "<<m_array_type<<")"<<std::endl; }
|
||||
@@ -57,6 +59,8 @@ public:
|
||||
|
||||
osg::Vec4 const& getVec4( int index ) { ASSERT_TYPE( Vec4 ); return (*m_vec4_array)[index]; };
|
||||
|
||||
osg::Matrixf const& getMatrix( int index ) { ASSERT_TYPE( Matrix ); return (*m_matrix_array)[index]; };
|
||||
|
||||
#undef ASSERT_TYPE
|
||||
|
||||
protected:
|
||||
@@ -68,6 +72,7 @@ protected:
|
||||
osg::ref_ptr<osg::Vec2Array> m_vec2_array;
|
||||
osg::ref_ptr<osg::Vec3Array> m_vec3_array;
|
||||
osg::ref_ptr<osg::Vec4Array> m_vec4_array;
|
||||
osg::ref_ptr<osg::MatrixfArray> m_matrix_array;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user