Hello,
We are using Open Scene Graph for an application and we need COLLADA
support. While testing the pluggin we found a small bug and we are
submitting a patch.
The first attachment is a small program that creates a scene with two
pyramids, transformed by two instances of
osg::PositionAttitudeTransform. One of them is rotated 90 degrees in
the X axis, and the scene is exported both in the native OSG (.osg)
and COLLADA (.dae) formats. In the first case the rotated pyramid is
displayed correctly whereas in the second the pyramid seems not to be
rotated.
In the COLLADA 1.4.1 specification (found at
http://www.khronos.org/collada/) it is specified that
"The <rotate> element contains a list of four floating-point values
[...] followed by an angle in degrees" but the plugin seems to write
the value in radians.
The problem seems to be in the method daeWriter::apply() that seems to
be writing the angle value in radians to the COLLADA file. The patch
can be found in the second attachment and is simply a call to
RadiansToDegrees wrapped around the angle.
We are not really familiar with the code and so the patch might be
wrong, but it seems to work for us.
Thank you,
Loic Simon,
Panagiotis Koutsourakis,
Olivier Teboul.
#include <cmath>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/Transform>
#include <osg/PositionAttitudeTransform>
#include <osg/Group>
#include <osg/Vec3d>
#include <osg/Quat>
#include <osgDB/WriteFile>
osg::Geode* createPyramid();
int main(int argc, char** argv)
{
osg::ref_ptr<osg::Group> root = new osg::Group;
osg::ref_ptr<osg::Geode> geode1 = createPyramid();
osg::ref_ptr<osg::Geode> geode2 = createPyramid();
osg::ref_ptr<osg::PositionAttitudeTransform> tf1 = new osg::PositionAttitudeTransform;
osg::ref_ptr<osg::PositionAttitudeTransform> tf2 = new osg::PositionAttitudeTransform;
//Move the first pyramid
tf1->setPosition(osg::Vec3(3, 0, 0));
//Rotate the second pyramid.
tf2->setAttitude(osg::Quat(M_PI/2.0,osg::Vec3d(1.0,0.0,0.0)));
//Add the nodes to the scene.
root->addChild(tf1.get());
root->addChild(tf2.get());
tf1->addChild(geode1.get());
tf2->addChild(geode2.get());
//Export to OSG
osgDB::writeNodeFile(*root,std::string("test.osg"));
//Export to COLLADA
osgDB::writeNodeFile(*root,std::string("test.dae"));
return 0;
}
osg::Geode* createPyramid()
{
osg::Geode* pyramidGeode = new osg::Geode();
osg::Geometry* pyramidGeometry = new osg::Geometry();
pyramidGeode->addDrawable(pyramidGeometry);
// Specify the vertices:
osg::Vec3Array* pyramidVertices = new osg::Vec3Array;
pyramidVertices->push_back( osg::Vec3(0, 0, 0) ); // front left
pyramidVertices->push_back( osg::Vec3(2, 0, 0) ); // front right
pyramidVertices->push_back( osg::Vec3(2, 2, 0) ); // back right
pyramidVertices->push_back( osg::Vec3( 0,2, 0) ); // back left
pyramidVertices->push_back( osg::Vec3( 1, 1,2) ); // peak
// Associate this set of vertices with the geometry associated with the
// geode we added to the scene.
pyramidGeometry->setVertexArray( pyramidVertices );
// Create a QUAD primitive for the base by specifying the
// vertices from our vertex list that make up this QUAD:
osg::DrawElementsUInt* pyramidBase =
new osg::DrawElementsUInt(osg::PrimitiveSet::QUADS, 0);
pyramidBase->push_back(3);
pyramidBase->push_back(2);
pyramidBase->push_back(1);
pyramidBase->push_back(0);
// Add this primitive to the geometry:
pyramidGeometry->addPrimitiveSet(pyramidBase);
// code to create other faces goes here!
osg::DrawElementsUInt* pyramidFaceOne =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceOne->push_back(0);
pyramidFaceOne->push_back(1);
pyramidFaceOne->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceOne);
osg::DrawElementsUInt* pyramidFaceTwo =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceTwo->push_back(1);
pyramidFaceTwo->push_back(2);
pyramidFaceTwo->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceTwo);
osg::DrawElementsUInt* pyramidFaceThree =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceThree->push_back(2);
pyramidFaceThree->push_back(3);
pyramidFaceThree->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceThree);
osg::DrawElementsUInt* pyramidFaceFour =
new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES, 0);
pyramidFaceFour->push_back(3);
pyramidFaceFour->push_back(0);
pyramidFaceFour->push_back(4);
pyramidGeometry->addPrimitiveSet(pyramidFaceFour);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 0 red
colors->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f) ); //index 1 green
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f) ); //index 2 blue
colors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f) ); //index 3 white
colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); //index 4 red
pyramidGeometry->setColorArray(colors);
pyramidGeometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
// Since the mapping from vertices to texture coordinates is 1:1,
// we don't need to use an index array to map vertices to texture
// coordinates. We can do it directly with the 'setTexCoordArray'
// method of the Geometry class.
// This method takes a variable that is an array of two dimensional
// vectors (osg::Vec2). This variable needs to have the same
// number of elements as our Geometry has vertices. Each array element
// defines the texture coordinate for the cooresponding vertex in the
// vertex array.
osg::Vec2Array* texcoords = new osg::Vec2Array(5);
(*texcoords)[0].set(0.00f,0.0f); // tex coord for vertex 0
(*texcoords)[1].set(0.25f,0.0f); // tex coord for vertex 1
(*texcoords)[2].set(0.50f,0.0f); // ""
(*texcoords)[3].set(0.75f,0.0f); // ""
(*texcoords)[4].set(0.50f,1.0f); // ""
pyramidGeometry->setTexCoordArray(0,texcoords);
return pyramidGeode;
}
Index: src/osgPlugins/dae/daeWTransforms.cpp
===================================================================
--- src/osgPlugins/dae/daeWTransforms.cpp (revision 9034)
+++ src/osgPlugins/dae/daeWTransforms.cpp (working copy)
@@ -105,7 +105,7 @@
rot->getValue().append( axis.x() );
rot->getValue().append( axis.y() );
rot->getValue().append( axis.z() );
- rot->getValue().append( angle );
+ rot->getValue().append( osg::RadiansToDegrees(angle) );
}
if ( pos.x() != 0 || pos.y() != 0 || pos.z() != 0 )
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org