Skip to main content

History: DotScene Loader with User Data

Source of version: 5

Copy to clipboard
            {maketoc}

!!Getting Started
When you export a .scene file from blender, you have the option of exporting logic properties as userData. Then why not use it? But then, you may think, "Oh no! the dotSceneInterface doesn't support userData! Now I have to write a loader myself?!". The answer:- Not now, not when nikki has already written one!;). This loader requires TinyXML. All you have to is add all the TinyXML files to your project (2 header files and 4 source files).

See ((DotScene Loader with User Data Class)) for an alternative.

The modifications include: A fix for child nodes, Putting the code in a class, allowing the scene to be linked to a defined SceneNode and prepending a name to all the SceneNodes defined in the file. I use the SceneNode modifications for using multiple .scene files in a single scene. This allows us to create complex objects with multiple entities (and user properties) and to define SceneNodes for other uses (like attaching a weapon or effect). We can also use the same scene multiple times for multiple instances of the object.

JeDi has started from this code to write a new, easily extensible DotScene loader. You can found it at ((New DotScene Loader)).

!!The Source
Here's the source code of the loader. Copy it into a header file called dotScene.h, and include it in your application:-
{CODE(wrap="1", colors="c++")}/*------------------------------------------------------------------------------
 *  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 <Ogre.h>
#include <vector>
#include "tinyxml.h"
using namespace std;
using namespace Ogre;

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

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

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("castShadows") )
      if( String(XMLLight->Attribute("castShadows")) == "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;
}

vector<nodeProperty> nodeProperties;

void parseDotScene( const String &SceneName, const String& groupName, SceneManager *mSceneMgr )
{
   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;
   }
   
   XMLNodes = XMLRoot->FirstChildElement( "nodes" );
   
   // Read in the scene nodes
   if( XMLNodes )
   {
      TiXmlElement *XMLNode, *XMLPosition, *XMLRotation, *XMLScale,  *XMLEntity, *XMLBillboardSet,  *XMLLight, *XMLUserData;

      XMLNode = XMLNodes->FirstChildElement( "node" );
      
      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 = mSceneMgr->getRootSceneNode()->createChildSceneNode( NodeName );
         Vector3 TempVec;
         String TempValue;
         
         // Now position it...
         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);
            NewNode->setPosition( TempVec );
         }

         // Rotate it...
         XMLRotation = XMLNode->FirstChildElement("rotation");
         if( XMLRotation ){
            Quaternion TempQuat;
            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);
            NewNode->setOrientation( TempQuat );
         }

         // Scale it.
         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 );
         }

         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);
           
            //castShadows      (true | false) "true"
        NewEntity->setCastShadows( true );
        if( XMLEntity->Attribute("castShadows") )
               if( String(XMLEntity->Attribute("castShadows")) == "false" )
                  NewEntity->setCastShadows( false );
            
            NewNode->attachObject( NewEntity );
         }

         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" );
            }
         }

         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");
               nodeProperty newProp(first,second,third);
               nodeProperties.push_back(newProp);
               XMLProperty = XMLProperty->NextSiblingElement("property");
            }   
         }

         // Move to the next node
         XMLNode = XMLNode->NextSiblingElement( "node" );
      }
   }

   // Close the XML File
   delete XMLDoc;
}

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

#endif{CODE}

!!Example Usage
The usage is very simple. Use parseDotScene(String file,String resourceGroup,SceneManager sceneMgr) to load the .scene file. To get a property, use getProperty(String nodeName,String propertyName), which returns a string containing the value. Example:-
{CODE(wrap="1", colors="c++")}parseDotScene("scene.xml","General",mSceneMgr);
mWindow->setDebugText(getProperty("Robot","Life"));{CODE}

Enjoy! (written by nikki)
---
Alias: (alias(DotScene_Loader_with_User_Data))
        

History

Information Version
Sun 29 of Oct, 2017 23:08 GMT-0000 paroj 8
Fri 30 of Jun, 2017 22:22 GMT-0000 paroj 7
Fri 30 of Jun, 2017 22:22 GMT-0000 paroj 6
Thu 01 of Jul, 2010 13:42 GMT-0000 Slappy Added alias DotScene_Loader_with_User_Data 5
Sun 03 of Jan, 2010 00:24 GMT-0000 jacmoe 4
Fri 25 of Dec, 2009 21:36 GMT-0000 jacmoe 3
Fri 25 of Dec, 2009 21:35 GMT-0000 jacmoe 2
Mon 13 of Oct, 2008 15:09 GMT-0000 OgreWikiBot Robot: Cosmetic changes 1