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):
Then to use it :
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 ) has the kind of motion I want, I suppose someone (at least Wallaber ) knows a way to do it.
Regards from Sweden!
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 ) has the kind of motion I want, I suppose someone (at least Wallaber ) knows a way to do it.
Regards from Sweden!