[SOLVED] ONewt integration in DotScene & Motion on a pla

abecam

20-04-2006 19:02:39

Then, my first topic here, so first thanks for all the Ogre Community with this great job. I had a great fun developping with Ogre and ONewt so far, and everything work well (only my brain is limited now).
I have enhanced the DotScene Loader with User Data from the wiki to automatically add the entities into tree collisions. The nice point is that you can also change it to add rigid bodies, I don't know if it is bad or good to have several tree collisions instead of one... Maybe it can help, so here it is (it's raw, it might be incomplete or buggy, but it works for me):


/*------------------------------------------------------------------------------
* DotScene.h
*
* This file provides some methods for the parsing of a .scene file, with
* support for userData.
*------------------------------------------------------------------------------*/

#ifndef DOT_SCENE_H
#define DOT_SCENE_H

#include <vector>
#include <string>
#include <Ogre.h>
#include <OgreNewt.h>

#include "tinyxml.h"

using namespace std;
using namespace Ogre;

class nodeProperty
{
public:
String nodeName;
String propertyNm;
String valueName;
String typeName;

nodeProperty(String node,String propertyName,String value,String type)
{
nodeName = node;
propertyNm = propertyName;
valueName = value;
typeName = type;
}
};

class CDotScene
{
public:
CDotScene() : mSceneMgr(0) {}
virtual ~CDotScene() {}

void parseDotScene( const String &SceneName, const String& groupName, SceneManager *yourSceneMgr, OgreNewt::World *m_World, SceneNode *pAttachNode = NULL, String sPrependNode = "");
String getProperty(String ndNm, String prop);

vector<nodeProperty> nodeProperties;

protected:
void processNode(TiXmlElement *XMLNode, SceneNode *pAttach,OgreNewt::World *m_World);
SceneManager *mSceneMgr;
String m_sPrependNode;
};

#endif



/*------------------------------------------------------------------------------
* DotScene.cpp
*
* This file provides some methods for the parsing of a .scene file, with
* support for userData.
*------------------------------------------------------------------------------*/

#include <Ogre.h>
#include "StdAfx.h"
#include "DotScene.h"
#include "tinyxml.h"

using namespace Ogre;

static Light* LoadLight( TiXmlElement *XMLLight, SceneManager *mSceneMgr )
{
TiXmlElement *XMLDiffuse, *XMLSpecular, *XMLAttentuation, *XMLPosition;

// Create a light (point | directional | spot | radPoint)
Light* l = mSceneMgr->createLight( XMLLight->Attribute("name") );
if( !XMLLight->Attribute("type") || String(XMLLight->Attribute("type")) == "point" )
l->setType( Light::LT_POINT );
else if( String(XMLLight->Attribute("type")) == "directional")
l->setType( Light::LT_DIRECTIONAL );
else if( String(XMLLight->Attribute("type")) == "spot")
l->setType( Light::LT_SPOTLIGHT );
else if( String(XMLLight->Attribute("type")) == "radPoint")
l->setType( Light::LT_POINT );

XMLDiffuse = XMLLight->FirstChildElement("colourDiffuse");
if( XMLDiffuse ){
ColourValue Diffuse;
Diffuse.r = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("r") );
Diffuse.g = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("g") );
Diffuse.b = Ogre::StringConverter::parseReal( XMLDiffuse->Attribute("b") );
Diffuse.a = 1;
l->setDiffuseColour(Diffuse);
}
XMLSpecular = XMLLight->FirstChildElement("colourSpecular");
if( XMLSpecular ){
ColourValue Specular;
Specular.r = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("r") );
Specular.g = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("g") );
Specular.b = Ogre::StringConverter::parseReal( XMLSpecular->Attribute("b") );
Specular.a = 1;
l->setSpecularColour(Specular);
}

XMLAttentuation = XMLLight->FirstChildElement("lightAttenuation");
if( XMLAttentuation )
{
//get defaults incase not all values specified
Real range, constant, linear, quadratic;
range = l->getAttenuationRange();
constant = l->getAttenuationConstant();
linear = l->getAttenuationLinear();
quadratic = l->getAttenuationQuadric();

if( XMLAttentuation->Attribute("range") )
range = StringConverter::parseReal( XMLAttentuation->Attribute("range") );
if( XMLAttentuation->Attribute("constant") )
constant = StringConverter::parseReal( XMLAttentuation->Attribute("constant") );
if( XMLAttentuation->Attribute("linear") )
linear = StringConverter::parseReal( XMLAttentuation->Attribute("linear") );
if( XMLAttentuation->Attribute("quadratic") )
quadratic = StringConverter::parseReal( XMLAttentuation->Attribute("quadratic") );

l->setAttenuation( range, constant, linear, quadratic );
}

XMLPosition = XMLLight->FirstChildElement("position");
if( XMLPosition ) {
Vector3 p = Vector3(0,0,0);
if( XMLPosition->Attribute("x") )
p.x = StringConverter::parseReal( XMLPosition->Attribute("x") );
if( XMLPosition->Attribute("y") )
p.y = StringConverter::parseReal( XMLPosition->Attribute("y") );
if( XMLPosition->Attribute("z") )
p.z = StringConverter::parseReal( XMLPosition->Attribute("z") );

l->setPosition( p );
}

//castShadows (true | false) "true"
l->setCastShadows( true );
if( XMLLight->Attribute("visible") )
if( String(XMLLight->Attribute("visible")) == "false" )
l->setCastShadows( false );

//visible (true | false) "true"
l->setVisible( true );
if( XMLLight->Attribute("visible") )
if( String(XMLLight->Attribute("visible")) == "false" )
l->setVisible( false );

return l;
}

void CDotScene::parseDotScene( const String &SceneName, const String& groupName, SceneManager *yourSceneMgr, OgreNewt::World *m_World,SceneNode *pAttachNode, String sPrependNode)
{
// set up shared object values
m_sPrependNode = sPrependNode;
mSceneMgr = yourSceneMgr;

TiXmlDocument *XMLDoc;
TiXmlElement *XMLRoot, *XMLNodes;

try
{
DataStreamPtr pStream = ResourceGroupManager::getSingleton().
openResource( SceneName, groupName );

String data = pStream->getAsString();
// Open the .scene File
XMLDoc = new TiXmlDocument();
XMLDoc->Parse( data.c_str() );
pStream->close();
pStream.setNull();

if( XMLDoc->Error() )
{
//We'll just log, and continue on gracefully
LogManager::getSingleton().logMessage("[dotSceneLoader] The TiXmlDocument reported an error");
delete XMLDoc;
return;
}
}
catch(...)
{
//We'll just log, and continue on gracefully
LogManager::getSingleton().logMessage("[dotSceneLoader] Error creating TiXmlDocument");
delete XMLDoc;
return;
}

// Validate the File
XMLRoot = XMLDoc->RootElement();
if( String( XMLRoot->Value()) != "scene" ) {
LogManager::getSingleton().logMessage( "[dotSceneLoader]Error: Invalid .scene File. Missing <scene>" );
delete XMLDoc;
return;
}

// figure out where to attach any nodes we create
if(pAttachNode == NULL)
{
pAttachNode = mSceneMgr->getRootSceneNode();
}

XMLNodes = XMLRoot->FirstChildElement( "nodes" );

// Read in the scene nodes
if( XMLNodes )
{
processNode(XMLNodes->FirstChildElement( "node" ), pAttachNode,m_World);
}

// Close the XML File
delete XMLDoc;
}

void CDotScene::processNode(TiXmlElement *XMLNode, SceneNode *pAttach, OgreNewt::World *m_World )
{
TiXmlElement *XMLPosition, *XMLRotation, *XMLScale, *XMLEntity, *XMLBillboardSet, *XMLLight, *XMLUserData;

while( XMLNode )
{
// Process the current node
// Grab the name of the node
String NodeName = XMLNode->Attribute("name");
// First create the new scene node
SceneNode* NewNode = pAttach->createChildSceneNode( m_sPrependNode + NodeName );
OgreNewt::Body* bodDotScen = NULL;
Vector3 TempVec;
String TempValue;

// Scale it. (Before I add it in my collision ! Later is too late. )
XMLScale = XMLNode->FirstChildElement("scale");
if( XMLScale ){
TempValue = XMLScale->Attribute("x");
TempVec.x = StringConverter::parseReal(TempValue);
TempValue = XMLScale->Attribute("y");
TempVec.y = StringConverter::parseReal(TempValue);
TempValue = XMLScale->Attribute("z");
TempVec.z = StringConverter::parseReal(TempValue);
NewNode->setScale( TempVec );
// Humm this is not the good thing to do for OgreNewt... Maybe the right way is to scale the mesh, not the node...
}

XMLLight = XMLNode->FirstChildElement( "light" );
if( XMLLight )
NewNode->attachObject( LoadLight( XMLLight, mSceneMgr ) );

// Check for an Entity
XMLEntity = XMLNode->FirstChildElement("entity");
if( XMLEntity )
{
String EntityName, EntityMeshFilename;
EntityName = XMLEntity->Attribute( "name" );
EntityMeshFilename = XMLEntity->Attribute( "meshFile" );

// Create entity
Entity* NewEntity = mSceneMgr->createEntity(EntityName, EntityMeshFilename);
NewNode->attachObject( NewEntity );

// OgreNewt specific code (I just try !!!)
OgreNewt::Collision* colDotScen = new OgreNewt::CollisionPrimitives::TreeCollision( m_World, NewNode, false);
bodDotScen = new OgreNewt::Body( m_World, colDotScen );
delete colDotScen;

bodDotScen->attachToNode( NewNode );
// End OgreNewt
}

XMLBillboardSet = XMLNode->FirstChildElement( "billboardSet" );
if( XMLBillboardSet )
{
String TempValue;

BillboardSet* bSet = mSceneMgr->createBillboardSet( NewNode->getName() );

BillboardType Type;
TempValue = XMLBillboardSet->Attribute( "type" );
if( TempValue == "orientedCommon" )
Type = BBT_ORIENTED_COMMON;
else if( TempValue == "orientedSelf" )
Type = BBT_ORIENTED_SELF;
else Type = BBT_POINT;

BillboardOrigin Origin;
TempValue = XMLBillboardSet->Attribute( "type" );
if( TempValue == "bottom_left" )
Origin = BBO_BOTTOM_LEFT;
else if( TempValue == "bottom_center" )
Origin = BBO_BOTTOM_CENTER;
else if( TempValue == "bottomRight" )
Origin = BBO_BOTTOM_RIGHT;
else if( TempValue == "left" )
Origin = BBO_CENTER_LEFT;
else if( TempValue == "right" )
Origin = BBO_CENTER_RIGHT;
else if( TempValue == "topLeft" )
Origin = BBO_TOP_LEFT;
else if( TempValue == "topCenter" )
Origin = BBO_TOP_CENTER;
else if( TempValue == "topRight" )
Origin = BBO_TOP_RIGHT;
else
Origin = BBO_CENTER;

bSet->setBillboardType( Type );
bSet->setBillboardOrigin( Origin );


TempValue = XMLBillboardSet->Attribute( "name" );
bSet->setMaterialName( TempValue );

int width, height;
width = (int) StringConverter::parseReal( XMLBillboardSet->Attribute( "width" ) );
height = (int) StringConverter::parseReal( XMLBillboardSet->Attribute( "height" ) );
bSet->setDefaultDimensions( width, height );
bSet->setVisible( true );
NewNode->attachObject( bSet );

TiXmlElement *XMLBillboard;

XMLBillboard = XMLBillboardSet->FirstChildElement( "billboard" );

while( XMLBillboard )
{
Billboard *b;
// TempValue;
TempVec = Vector3( 0, 0, 0 );
ColourValue TempColour(1,1,1,1);

XMLPosition = XMLBillboard->FirstChildElement( "position" );
if( XMLPosition ){
TempValue = XMLPosition->Attribute("x");
TempVec.x = StringConverter::parseReal(TempValue);
TempValue = XMLPosition->Attribute("y");
TempVec.y = StringConverter::parseReal(TempValue);
TempValue = XMLPosition->Attribute("z");
TempVec.z = StringConverter::parseReal(TempValue);
}

TiXmlElement* XMLColour = XMLBillboard->FirstChildElement( "colourDiffuse" );
if( XMLColour ){
TempValue = XMLColour->Attribute("r");
TempColour.r = StringConverter::parseReal(TempValue);
TempValue = XMLColour->Attribute("g");
TempColour.g = StringConverter::parseReal(TempValue);
TempValue = XMLColour->Attribute("b");
TempColour.b = StringConverter::parseReal(TempValue);
}

b = bSet->createBillboard( TempVec, TempColour);

XMLBillboard = XMLBillboard->NextSiblingElement( "billboard" );
}
}

// Now position it...
Quaternion TempQuat;

XMLPosition = XMLNode->FirstChildElement("position");
if( XMLPosition ){
TempValue = XMLPosition->Attribute("x");
TempVec.x = StringConverter::parseReal(TempValue);
TempValue = XMLPosition->Attribute("y");
TempVec.y = StringConverter::parseReal(TempValue);
TempValue = XMLPosition->Attribute("z");
TempVec.z = StringConverter::parseReal(TempValue);
}

// Rotate it...
XMLRotation = XMLNode->FirstChildElement("rotation");
if( XMLRotation ){

TempValue = XMLRotation->Attribute("qx");
TempQuat.x = StringConverter::parseReal(TempValue);
TempValue = XMLRotation->Attribute("qy");
TempQuat.y = StringConverter::parseReal(TempValue);
TempValue = XMLRotation->Attribute("qz");
TempQuat.z = StringConverter::parseReal(TempValue);
TempValue = XMLRotation->Attribute("qw");
TempQuat.w = StringConverter::parseReal(TempValue);
if ( bodDotScen )
{
// We move the OgreNewt body, it will automatically move the corresponding node.
bodDotScen->setPositionOrientation(TempVec,TempQuat);
}
else
{
NewNode->setPosition( TempVec );
NewNode->setOrientation( TempQuat );
}
}


XMLUserData = XMLNode->FirstChildElement( "userData" );
if ( XMLUserData )
{
TiXmlElement *XMLProperty;
XMLProperty = XMLUserData->FirstChildElement("property");
while ( XMLProperty )
{
String first = NewNode->getName();
String second = XMLProperty->Attribute("name");
String third = XMLProperty->Attribute("data");
String type = XMLProperty->Attribute("type");
nodeProperty newProp(first,second,third,type);
nodeProperties.push_back(newProp);
XMLProperty = XMLProperty->NextSiblingElement("property");
}
}
TiXmlElement * ChildXMLNode;
ChildXMLNode = XMLNode->FirstChildElement( "node" );
if(ChildXMLNode)
processNode(ChildXMLNode, NewNode,m_World); // recurse to do all my children

XMLNode = XMLNode->NextSiblingElement( "node" ); // process my next sibling
}
}

String CDotScene::getProperty(String ndNm, String prop)
{
for ( unsigned int i = 0 ; i < nodeProperties.size(); i++ )
{
if ( nodeProperties[i].nodeName == ndNm && nodeProperties[i].propertyNm == prop )
{
return nodeProperties[i].valueName;
}
}
return " ";
}


Then to use it :


SceneNode* dotSceneNod;
dotSceneNod = mSceneMgr->getRootSceneNode()->createChildSceneNode( "DotSceneNode" );
LogManager::getSingleton().logMessage(" Loading the scene ");
myDotScene.parseDotScene( "OneScene.xml", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, mSceneMgr,m_World,dotSceneNod);
LogManager::getSingleton().logMessage(" Finished loading the scene!");


Hope it helps!

Then I have a small problem: I want my camera to be attached to a box linked by a joint to another one moving. And I want this last one to move on a plan (the camera is a RTS-like). I have try to add a static box, that's fine but unmovable :) Then I have tried to do it "physically", but with few success. I guess I have to find a nice joint to do that, but I don't know , then I will try again, but as Stunt Playground (so good :shock: :D ) has the kind of motion I want, I suppose someone (at least Wallaber ;) ) knows a way to do it.

Regards from Sweden!

walaber

20-04-2006 22:51:39

thanks for the contribution!

for the camera problem. I would suggest using an ellipsoid collision shape for the camera. then apply the prebuilt custom 2D joint... that will make the camera stay on a specific 2D plane, and you can then move it around with forces and it will stay on the plane.

abecam

21-04-2006 00:21:35

Thanks for this answer. It seems to help, then I have difficulties to have it on a plan (it has worked once), it often moves strangely (I have defined the pin as the normal to my plan), especially if I throw a ball on it (I am using your nice demos)... I must do something wrong. I will investigate first, I will ask for help if I am still stuck, or give some infos if I discover something nice. But for now vacations :D ... Without my laptop :cry: So I will not program my joints until next weeks.

abecam

18-05-2006 15:53:53

Then I was way too busy these last times. Just to say that it was resolved, just following Walaber's indications! Thanks!
I am now having a great fun with ONewt (currently looking on how to break a joint, I have to find where it is in the doc), so I will be back with some news later, and maybe some code, if it can be of any help.

capture

12-06-2007 15:21:53

Is this still the best way to load a dotscene into ogrenewt or is there another way that i dont know about yet?

abecam

12-06-2007 15:31:44

The best way I don't know, but that's ok :) ... Then it's for an old version of ONewt. Now you can use the serialization of TreeCollisions (TreeSerialization of something like that)-> Use the regular dotScene loader (not mine), and then serialize what you want (if you search for it, you will find some topic about it, Walaber has presented it some time after my posts here)
Still using my system though, so that's ok I guess.