OSM Scene Loader

_Archic

12-12-2006 12:49:30

Hi!

I convert OSM Scene Loader (change syntax) from ODN (http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=1483&highlight=ofusion)
that was also converted from original c++ code :-)

May be this will be useful for someone..



using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Xml;
using Mogre;

namespace MyApp
{
public class OSMLoader
{
private XmlDocument xd;
private SceneManager mSceneMgr;
private RenderWindow mWindow;

private const int SCENE_SKYPLANE = 1;
private const int SCENE_SKYDOME = 2;
private const int SCENE_SKYBOX = 3;

private Hashtable cameras, lights, entities;

public Hashtable Cameras
{
get { return cameras; }
}

public Hashtable Lights
{
get { return lights; }
}

public Hashtable Entities
{
get { return entities; }
}

public SceneManager SceneMgr
{
get { return mSceneMgr; }
}

public event LoadedSceneObjectEventHandler OnCameraCreate;
public event LoadedSceneObjectEventHandler OnNodeCreate;
public event LoadedSceneObjectEventHandler OnLightCreate;
public event LoadedSceneObjectEventHandler OnEntityCreate;

public OSMLoader(SceneManager mgr, RenderWindow wnd)
{
mSceneMgr = mgr;
mWindow = wnd;
cameras = new Hashtable();
entities = new Hashtable();
lights = new Hashtable();
}

public void Initialize(string xmlFile)
{
LogManager.Singleton.LogMessage(@"
**********************************************
** OSM Scene Loader **
**********************************************
");
LogManager.Singleton.LogMessage("OSMLoader loading scene form file: " + xmlFile);
if (!ResourceGroupManager.Singleton.ResourceExists(
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
xmlFile))
{
LogManager.Singleton.LogMessage("Not found file: " + xmlFile);
throw new FileNotFoundException("Not found scene file.", xmlFile);
}

xd = new XmlDocument();
try
{
DataStreamPtr dsp = ResourceGroupManager.Singleton.OpenResource(xmlFile);
xd.LoadXml(dsp.AsString);
dsp.Dispose();
}
catch (XmlException ex)
{
xd = null;
LogManager.Singleton.LogMessage("Can't parse scene data, detail error message:\r\n" + ex.Message);
throw ex;
}
}

public bool CreateScene(SceneNode parent)
{
if (xd == null) return false;
LogManager.Singleton.LogMessage("OSMLoader: Creating scene on '" +
(parent == null ? "Root" : parent.Name) + "' node.");

if (mSceneMgr == null)
{
if (xd.SelectSingleNode("/sceneManager") != null)
setSceneProperties(xd);
else
mSceneMgr = Root.Singleton.CreateSceneManager(SceneType.ST_GENERIC);
}

if (parent == null)
parent = mSceneMgr.RootSceneNode.CreateChildSceneNode();

try
{
CreateEntities(xd.SelectNodes("/oe_scene/entities/entity"), parent);
}
catch
{
}
try
{
CreateLights(xd.SelectNodes("/oe_scene/lights/light"), parent);
}
catch
{
}
try
{
CreateCameras(xd.SelectNodes("/oe_scene/cameras/camera"), parent);
}
catch
{
}

LogManager.Singleton.LogMessage(@"
********************************
** oSceneLoader: Scene loaded **
********************************
");
return true;
}

// no use
/*
private void declareResources()
{
if (xd == null) return;
try
{
XmlElement xe = (XmlElement) xd.SelectSingleNode("/entities");
if (xe != null)
foreach (XmlElement item in xe.ChildNodes)
ResourceGroupManager.Instance.declareResource(item.GetAttribute("filename"), "Mesh");
}
catch
{
} // i don't know why not process exception here in c++ source file.
}
*/

private ColourValue parseColor(string r, string g, string b)
{
ColourValue clr = new ColourValue();
clr.r = float.Parse(r);
clr.g = float.Parse(g);
clr.b = float.Parse(b);

return clr;
/*return Color.FromArgb(
(int)(255 * float.Parse(r)),
(int)(255 * float.Parse(g)),
(int)(255 * float.Parse(b)));*/
}

private void setSceneProperties(XmlDocument xd)
{
// Scene manager
XmlElement sceneMgrElem = (XmlElement)xd.SelectSingleNode("sceneManager");
/*
ST_GENERIC = 1,
ST_EXTERIOR_CLOSE = 2,
ST_EXTERIOR_FAR = 4,
ST_EXTERIOR_REAL_FAR = 8,
ST_INTERIOR = 16
*/
int type = int.Parse(sceneMgrElem.GetAttribute("type"));
SceneType sceneType = (SceneType)type;
mSceneMgr = Root.Singleton.CreateSceneManager(sceneType);

string worldGeometry = sceneMgrElem.GetAttribute("worldGeometry");
if (worldGeometry != null)
mSceneMgr.SetWorldGeometry(worldGeometry);

// Background Color
XmlElement colorElem = (XmlElement)xd.SelectSingleNode("bkgcolor");
if (colorElem != null && mWindow != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));

mWindow.GetViewport(0).BackgroundColour = color;
}

// Ambient light Color
colorElem = (XmlElement)xd.SelectSingleNode("lightColor");
if (colorElem != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));
mSceneMgr.AmbientLight = color;
}


// Scene shadows
XmlElement shadowsElem = (XmlElement)xd.SelectSingleNode("shadowTechnique");
if (shadowsElem != null)
{
type = int.Parse(shadowsElem.GetAttribute("type"));
ShadowTechnique shadowType = (ShadowTechnique)type;

mSceneMgr.ShadowTechnique = shadowType;

int tex_size = int.Parse(shadowsElem.GetAttribute("tex_size"));
int tex_count = int.Parse(shadowsElem.GetAttribute("tex_count"));

mSceneMgr.SetShadowTextureSettings((ushort)tex_size, (ushort)tex_count);

// Shadow Color
colorElem = (XmlElement)shadowsElem.SelectSingleNode("color");
if (colorElem != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));

mSceneMgr.ShadowColour = color;
}
}

// Scene sky
XmlElement skyElem = (XmlElement)xd.SelectSingleNode("skyTechnique");
if (skyElem != null)
{
type = int.Parse(skyElem.GetAttribute("type"));
String materialName = skyElem.GetAttribute("material");

if (materialName != " ")
{
bool drawFirst = bool.Parse(skyElem.GetAttribute("drawFirst"));
float tiling = float.Parse(skyElem.GetAttribute("tiling"));
float scale = float.Parse(skyElem.GetAttribute("scale"));
float dist = float.Parse(skyElem.GetAttribute("dist"));
float bow = float.Parse(skyElem.GetAttribute("bow"));
int xSegments = int.Parse(skyElem.GetAttribute("xSegments"));
int ySegments = int.Parse(skyElem.GetAttribute("ySegments"));
Quaternion quat = Quaternion.IDENTITY;
Plane plane = new Plane();
plane.d = dist;

plane.normal = new Vector3();
plane.normal = -(Vector3.UNIT_Y);


switch (type)
{
case SCENE_SKYPLANE:

mSceneMgr.SetSkyPlane(true, plane, materialName, scale,
tiling, drawFirst, bow, xSegments, ySegments);

mSceneMgr.SetSkyBox(false, "");
mSceneMgr.SetSkyDome(false, "");

break;

case SCENE_SKYBOX:

mSceneMgr.SetSkyBox(true, materialName, dist, drawFirst, quat);
mSceneMgr.SetSkyPlane(false, plane, "");
mSceneMgr.SetSkyDome(false, "");

break;

case SCENE_SKYDOME:

mSceneMgr.SetSkyDome(true, materialName, bow, tiling, dist,
drawFirst, quat, xSegments, ySegments);

mSceneMgr.SetSkyPlane(false, plane, "");
mSceneMgr.SetSkyBox(false, "");

break;

}
}
}
}

private SceneNode CreateNode(XmlElement elet, SceneNode parent)
{
SceneNode pNode = null;

// Try to find the parent node
string pszName = elet.GetAttribute("name");
if (pszName == string.Empty) return null;

// Check if this node has a parent
string pszParent = elet.GetAttribute("parent");
if (pszParent == string.Empty)
{
// Check if the scene node has already been created by a child
DISABLE_LOGMANAGER();

try
{
pNode = mSceneMgr.GetSceneNode(pszName);
}
catch
{
pNode = parent.CreateChildSceneNode(pszName);
}

ENABLE_LOGMANAGER();

}
else
{
SceneNode pParent = null;
DISABLE_LOGMANAGER();

try
{
// Try to find parent scenenode
pParent = mSceneMgr.GetSceneNode(pszParent);
}
catch
{
// We try to create the parent node as child of root node.
// Later when the parent (hopefully) is created, we can adjust it,
// if it is child of another node.
pParent = parent.CreateChildSceneNode(pszParent);
}


try
{
// Check if the scene node has already been created by a child
// In this case we would have to change the parent.
pNode = mSceneMgr.GetSceneNode(pszName);

// Get old parent (probably scene root)
SceneNode pOldParent = pNode.ParentSceneNode;

// Remove this node
pOldParent.RemoveChild(pNode);

// Insert us as child on the "real" parent
pParent.AddChild(pNode);
}
catch
{
pNode = pParent.CreateChildSceneNode(pszName);
}

ENABLE_LOGMANAGER();
}

// Position
XmlElement posElem = (XmlElement)elet.SelectSingleNode("position");
if (posElem != null)
{
Vector3 pos;

pos.x = float.Parse(posElem.GetAttribute("x"));
pos.y = float.Parse(posElem.GetAttribute("y"));
pos.z = float.Parse(posElem.GetAttribute("z"));
pNode.Position = pos;
}

// Rotation
XmlElement rotElem = (XmlElement)elet.SelectSingleNode("rotation");
if (rotElem != null)
{
pNode.SetOrientation(
float.Parse(rotElem.GetAttribute("w")),
float.Parse(rotElem.GetAttribute("x")),
float.Parse(rotElem.GetAttribute("y")),
float.Parse(rotElem.GetAttribute("z")));

}

// Scale
XmlElement scaleElem = (XmlElement)elet.SelectSingleNode("scale");
if (scaleElem != null)
{
Vector3 scale;
scale.x = float.Parse(scaleElem.GetAttribute("x"));
scale.y = float.Parse(scaleElem.GetAttribute("y"));
scale.z = float.Parse(scaleElem.GetAttribute("z"));
pNode.SetScale(scale);
}

// Notify
if (OnNodeCreate != null)
OnNodeCreate(pNode, elet);

// Animation
XmlElement animList = (XmlElement)elet.SelectSingleNode("animations");
if (animList != null)
{
//
foreach (XmlElement animElem in animList.ChildNodes)
{
// Get name of animation
string aniName = animElem.GetAttribute("name");

Animation pAnim = null;
DISABLE_LOGMANAGER();
try
{
pAnim = mSceneMgr.GetAnimation(aniName);
}
catch
{
}
ENABLE_LOGMANAGER();

// If this animation has not been created yet, we create it
if (pAnim == null)
{
float fLength = float.Parse(animElem.GetAttribute("length"));
pAnim = mSceneMgr.CreateAnimation(aniName, fLength);
pAnim.SetInterpolationMode(Animation.InterpolationMode.IM_LINEAR);
}

// Create animation track for this node
NodeAnimationTrack pTrack = pAnim.CreateNodeTrack((ushort)(pAnim.NumNodeTracks + 1), pNode);

// Iterate all keyframes for this node
foreach (XmlElement pKeyframeElem in animElem.ChildNodes)
{
float fTime = float.Parse(pKeyframeElem.GetAttribute("time"));
TransformKeyFrame pKeyFrame = pTrack.CreateNodeKeyFrame(fTime);

// Position
posElem = (XmlElement)pKeyframeElem.SelectSingleNode("position");
if (posElem != null)
{
Vector3 trans;
trans.x = float.Parse(posElem.GetAttribute("x"));
trans.y = float.Parse(posElem.GetAttribute("y"));
trans.z = float.Parse(posElem.GetAttribute("z"));
pKeyFrame.Translate = trans;
}

// Rotation
rotElem = (XmlElement)pKeyframeElem.SelectSingleNode("rotation");
if (rotElem != null)
{
Quaternion qRot;
qRot.x = float.Parse(rotElem.GetAttribute("x"));
qRot.y = float.Parse(rotElem.GetAttribute("y"));
qRot.z = float.Parse(rotElem.GetAttribute("z"));
qRot.w = float.Parse(rotElem.GetAttribute("w"));
pKeyFrame.Rotation= qRot;
}

// Scale
scaleElem = (XmlElement)pKeyframeElem.SelectSingleNode("scale");
if (scaleElem != null)
{
Vector3 scale;
scale.x = float.Parse(scaleElem.GetAttribute("x"));
scale.y = float.Parse(scaleElem.GetAttribute("y"));
scale.z = float.Parse(scaleElem.GetAttribute("z"));
pKeyFrame.Scale = scale;
}
}
}
}

return pNode;
}

private void ENABLE_LOGMANAGER()
{
LogManager.Singleton.SetLogDetail(LoggingLevel.LL_NORMAL);
}

private void DISABLE_LOGMANAGER()
{
LogManager.Singleton.SetLogDetail(LoggingLevel.LL_LOW);
}

private void CreateCameras(XmlNodeList list, SceneNode parent)
{
// Iterate all Cameras, creating them. We do not attach them yet, since
// we need to make sure all potential item entities have been created.
foreach (XmlElement item in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other Cameras
try
{
// Create camera
Camera pCamera = mSceneMgr.CreateCamera(item.GetAttribute("name"));
if (pCamera == null) continue;

// Set Field of View on camera
pCamera.FOVy = new Radian(float.Parse(item.GetAttribute("FOV")));
pCamera.NearClipDistance = 5;

// Create node with full information
SceneNode pCameraNode = CreateNode(item, parent);

// Attach the Camera entity to node
pCameraNode.AttachObject(pCamera);

// Target
XmlElement targetElem = (XmlElement)item.SelectSingleNode("target");
if (targetElem != null)
{
// Create node with full information
SceneNode pTargetNode = CreateNode(targetElem, parent);
pCameraNode.SetAutoTracking(true, pTargetNode);
}

// Notify
if (OnCameraCreate != null)
OnCameraCreate(pCamera, item);

// Add to camera list
cameras.Add(pCamera.Name, pCamera);
}
catch
{
continue;
}
}
}

private void CreateLights(XmlNodeList list, SceneNode parent)
{
// Iterate all Lights, creating them. We do not attach them yet, since
// we need to make sure all potential parent entities have been created.
foreach (XmlElement pLightElem in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other Lights
try
{
string pszName = pLightElem.GetAttribute("name");

Light pLight = mSceneMgr.CreateLight(pszName);
if (pLight == null) continue;

// Figure out which type of light we are using
string pszType = pLightElem.GetAttribute("type");
if (pszType == "omni")
{
pLight.Type = Light.LightTypes.LT_POINT;
}
else if (pszType == "spot")
{
pLight.Type = Light.LightTypes.LT_SPOTLIGHT;
pLight.SetSpotlightRange(
new Radian(new Degree(float.Parse(pLightElem.GetAttribute("hotspot")))),
new Radian(new Degree(float.Parse(pLightElem.GetAttribute("falloff")))));
pLight.SetDirection(0, 0, -1);

}
else if (pszType == "directional")
{
pLight.Type = Light.LightTypes.LT_DIRECTIONAL;
}

// Check if the light should be on
string pszOn = pLightElem.GetAttribute("on");
if (pszOn == "true")
pLight.Visible = true;
else
pLight.Visible = false;

// Check if the object should cast shadows
string pszCastShadows = pLightElem.GetAttribute("CastShadows");
if (pszCastShadows == "no")
pLight.CastShadows = false;
else
pLight.CastShadows = true;

// Diffuse Color
XmlElement colorElem = (XmlElement)pLightElem.SelectSingleNode("color");
if (colorElem != null)
{
pLight.SetDiffuseColour(
float.Parse(colorElem.GetAttribute("r")),
float.Parse(colorElem.GetAttribute("g")),
float.Parse(colorElem.GetAttribute("b")));
}

// Specular Color
XmlElement specularElem = (XmlElement)pLightElem.SelectSingleNode("specular");
if (specularElem != null)
{
pLight.SetSpecularColour(
float.Parse(specularElem.GetAttribute("r")),
float.Parse(specularElem.GetAttribute("g")),
float.Parse(specularElem.GetAttribute("b")));
}

// Attenuation
XmlElement attenElem = (XmlElement)pLightElem.SelectSingleNode("attenuation");
if (attenElem != null)
{
pLight.SetAttenuation(
float.Parse(attenElem.GetAttribute("range")),
float.Parse(attenElem.GetAttribute("constant")),
float.Parse(attenElem.GetAttribute("linear")),
float.Parse(attenElem.GetAttribute("quadratic")));
}

// Create node with full information
SceneNode pLightNode = CreateNode(pLightElem, parent);

// Attach the Light entity to node
pLightNode.AttachObject(pLight);

// Target
XmlElement targetElem = (XmlElement)pLightElem.SelectSingleNode("target");
if (targetElem != null)
{
// Create node with full information
SceneNode pTargetNode = CreateNode(targetElem, parent);
pLightNode.SetAutoTracking(true, pTargetNode);
}

// Notify
if (OnLightCreate != null)
OnLightCreate(pLight, pLightElem);

// Add to light list
lights.Add(pszName, pLight);
}
catch
{
continue;
}
}
}

private void CreateEntities(XmlNodeList list, SceneNode parent)
{
// Iterate all meshes, creating them.
foreach (XmlElement pMeshElem in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other meshes
try
{
string pszName = pMeshElem.GetAttribute("name");
string pszFileName = pMeshElem.GetAttribute("filename");

// try to create the mesh
Entity pEntity = mSceneMgr.CreateEntity(pszName, pszFileName);
if (pEntity == null) continue;

// Check if the object should cast shadows
string pszCastShadows = pMeshElem.GetAttribute("CastShadows");
if (pszCastShadows == "no")
pEntity.CastShadows = false;
else
pEntity.CastShadows = true;

// Create node with full information
SceneNode pObjNode = CreateNode(pMeshElem, parent);

// Attach the mesh entity to node
pObjNode.AttachObject(pEntity);

// Notify
if (OnEntityCreate != null)
OnEntityCreate(pEntity, pMeshElem);

// Add to entity list
entities.Add(pszName, pEntity);
}
catch (Exception ex)
{
continue;
}
}
}
}

public delegate void LoadedSceneObjectEventHandler(Object obj, XmlElement xmlSrc);

}


Example of usage

OSMLoader loader = new OSMLoader(sceneMgr, window);
loader.Initialize("test.osm");
loader.CreateScene(sceneMgr.RootSceneNode);

Bekas

12-12-2006 13:03:36

Great! This is very useful, can you add it to the wiki so that it won't get lost in the forums ?

_Archic

12-12-2006 13:25:32

No, because I can't login to Wiki page :oops:

Bekas

12-12-2006 13:33:42

You need to create an account to the main ogre forums too; wiki uses that account.

_Archic

13-12-2006 07:29:54

Thanx. Added to Code and Snippets http://www.ogre3d.org/wiki/index.php/MO ... ceneLoader
:-)

Vectrex

13-12-2006 12:22:48

thanks, much appreciated!

marc_antoine

30-12-2006 02:03:01

it is ok if i'm using managed ogre (MOGRE) but if im using unmanaged c#? like OGREDOTNET?... how do i use it?... :oops: :roll:

Bekas

31-12-2006 09:50:53

Archic converted the already working OgreDotNet code, which is here: http://www.ogre3d.org/phpBB2addons/viewtopic.php?t=1483&highlight=ofusion

(He mentions the link in his post)

smernesto

02-01-2007 00:16:34

Hi.

Well I am playing with oFusion and had a trouble.

The oFuscion Loader for Mogre is use this code in the CreateNode():
...
pos.x = float.Parse(posElem.GetAttribute("x"));

If you have this in the .osm :

<entity name="Box01" hidden="false" filename="Box01.mesh" CastShadows="yes" ReceiveShadows="yes">
<position x="-39.4941" y="0" z="5.53259" />
...

pos.x in with my configuration of Windows XP will be -394941 not -39.4941 because my decimal separator in Windows is ',' (coma) and not '.' (dot).
If I change <position x="-39.4941" y="0" z="5.53259" /> to
<position x="-39,4941" y="0" z="5,53259" />

The position is good.

The problem is that float.Parse takes the windows decimal separator to parse the string to float.

Then if you make a game with this code and give it to a person that has not the same decimal separator the game will not work fine.

Well the solution is to use some class or parameter of .NET that configure the decimal separator.

Well sorry my english is not fluid and is hard to me to explain well.
The solution is easy.

Thanks

Ernesto

smernesto

02-01-2007 19:11:47

HI. I fixed the problem of culture dependent code in the float.Parse, now the loader may work in Windows with decimal separator different that . (dot). I Used the code in the wiki http://www.ogre3d.org/wiki/index.php/MOGRE_OSMSceneLoader

I tested the code in my application and it works fine, the code parse the float numbers well. Please try the code.

I used System.Globalization namespace and NumberFormatInfo numberFormat = new NumberFormatInfo() class.
Using a instance of the class -> numberFormat.DecimalSeparator = "." and using in float.Parse(stringWithNumber) -> and now is...
float.Parse(stringWithNumber, numberFormatInfo);

Ernesto Gutierrez


//Update: 02/Feb/2007
//Fixed a problem with the code to parse float numbers, the code was dependent of the culture and the decimal separator.

using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Xml;
using System.Globalization;
using Mogre;

namespace MyApp
{
public class OSMLoader
{
private XmlDocument xd;
private SceneManager mSceneMgr;
private RenderWindow mWindow;
private NumberFormatInfo numberFormat = new NumberFormatInfo();

private const int SCENE_SKYPLANE = 1;
private const int SCENE_SKYDOME = 2;
private const int SCENE_SKYBOX = 3;

private Hashtable cameras, lights, entities;

public Hashtable Cameras
{
get { return cameras; }
}

public Hashtable Lights
{
get { return lights; }
}

public Hashtable Entities
{
get { return entities; }
}

public SceneManager SceneMgr
{
get { return mSceneMgr; }
}

public event LoadedSceneObjectEventHandler OnCameraCreate;
public event LoadedSceneObjectEventHandler OnNodeCreate;
public event LoadedSceneObjectEventHandler OnLightCreate;
public event LoadedSceneObjectEventHandler OnEntityCreate;

public OSMLoader(SceneManager mgr, RenderWindow wnd)
{
numberFormat.CurrencyDecimalSeparator = ".";
mSceneMgr = mgr;
mWindow = wnd;
cameras = new Hashtable();
entities = new Hashtable();
lights = new Hashtable();
}

public void Initialize(string xmlFile)
{
LogManager.Singleton.LogMessage(@"
**********************************************
** OSM Scene Loader **
**********************************************
");
LogManager.Singleton.LogMessage("OSMLoader loading scene form file: " + xmlFile);
if (!ResourceGroupManager.Singleton.ResourceExists(
ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
xmlFile))
{
LogManager.Singleton.LogMessage("Not found file: " + xmlFile);
throw new FileNotFoundException("Not found scene file.", xmlFile);
}

xd = new XmlDocument();
try
{
DataStreamPtr dsp = ResourceGroupManager.Singleton.OpenResource(xmlFile);
xd.LoadXml(dsp.AsString);
dsp.Dispose();
}
catch (XmlException ex)
{
xd = null;
LogManager.Singleton.LogMessage("Can't parse scene data, detail error message:\r\n" + ex.Message);
throw ex;
}
}

public bool CreateScene(SceneNode parent)
{
if (xd == null) return false;
LogManager.Singleton.LogMessage("OSMLoader: Creating scene on '" +
(parent == null ? "Root" : parent.Name) + "' node.");

if (mSceneMgr == null)
{
if (xd.SelectSingleNode("/sceneManager") != null)
setSceneProperties(xd);
else
mSceneMgr = Root.Singleton.CreateSceneManager(SceneType.ST_GENERIC);
}

if (parent == null)
parent = mSceneMgr.RootSceneNode.CreateChildSceneNode();

try
{
CreateEntities(xd.SelectNodes("/oe_scene/entities/entity"), parent);
}
catch
{
}
try
{
CreateLights(xd.SelectNodes("/oe_scene/lights/light"), parent);
}
catch
{
}
try
{
CreateCameras(xd.SelectNodes("/oe_scene/cameras/camera"), parent);
}
catch
{
}

LogManager.Singleton.LogMessage(@"
********************************
** oSceneLoader: Scene loaded **
********************************
");
return true;
}

// no use
/*
private void declareResources()
{
if (xd == null) return;
try
{
XmlElement xe = (XmlElement) xd.SelectSingleNode("/entities");
if (xe != null)
foreach (XmlElement item in xe.ChildNodes)
ResourceGroupManager.Instance.declareResource(item.GetAttribute("filename"), "Mesh");
}
catch
{
} // i don't know why not process exception here in c++ source file.
}
*/

private ColourValue parseColor(string r, string g, string b)
{
ColourValue clr = new ColourValue();
clr.r = float.Parse(r, numberFormat);
clr.g = float.Parse(g, numberFormat);
clr.b = float.Parse(b, numberFormat);

return clr;
}

private void setSceneProperties(XmlDocument xd)
{
// Scene manager
XmlElement sceneMgrElem = (XmlElement)xd.SelectSingleNode("sceneManager");
/*
ST_GENERIC = 1,
ST_EXTERIOR_CLOSE = 2,
ST_EXTERIOR_FAR = 4,
ST_EXTERIOR_REAL_FAR = 8,
ST_INTERIOR = 16
*/
int type = int.Parse(sceneMgrElem.GetAttribute("type"));
SceneType sceneType = (SceneType)type;
mSceneMgr = Root.Singleton.CreateSceneManager(sceneType);

string worldGeometry = sceneMgrElem.GetAttribute("worldGeometry");
if (worldGeometry != null)
mSceneMgr.SetWorldGeometry(worldGeometry);

// Background Color
XmlElement colorElem = (XmlElement)xd.SelectSingleNode("bkgcolor");
if (colorElem != null && mWindow != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));

mWindow.GetViewport(0).BackgroundColour = color;
}

// Ambient light Color
colorElem = (XmlElement)xd.SelectSingleNode("lightColor");
if (colorElem != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));
mSceneMgr.AmbientLight = color;
}


// Scene shadows
XmlElement shadowsElem = (XmlElement)xd.SelectSingleNode("shadowTechnique");
if (shadowsElem != null)
{
type = int.Parse(shadowsElem.GetAttribute("type"));
ShadowTechnique shadowType = (ShadowTechnique)type;

mSceneMgr.ShadowTechnique = shadowType;

int tex_size = int.Parse(shadowsElem.GetAttribute("tex_size"));
int tex_count = int.Parse(shadowsElem.GetAttribute("tex_count"));

mSceneMgr.SetShadowTextureSettings((ushort)tex_size, (ushort)tex_count);

// Shadow Color
colorElem = (XmlElement)shadowsElem.SelectSingleNode("color");
if (colorElem != null)
{
ColourValue color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));

mSceneMgr.ShadowColour = color;
}
}

// Scene sky
XmlElement skyElem = (XmlElement)xd.SelectSingleNode("skyTechnique");
if (skyElem != null)
{
type = int.Parse(skyElem.GetAttribute("type"));
String materialName = skyElem.GetAttribute("material");

if (materialName != " ")
{
bool drawFirst = bool.Parse(skyElem.GetAttribute("drawFirst"));
float tiling = float.Parse(skyElem.GetAttribute("tiling"), numberFormat);
float scale = float.Parse(skyElem.GetAttribute("scale"), numberFormat);
float dist = float.Parse(skyElem.GetAttribute("dist"), numberFormat);
float bow = float.Parse(skyElem.GetAttribute("bow"), numberFormat);
int xSegments = int.Parse(skyElem.GetAttribute("xSegments"));
int ySegments = int.Parse(skyElem.GetAttribute("ySegments"));
Quaternion quat = Quaternion.IDENTITY;
Plane plane = new Plane();
plane.d = dist;

plane.normal = new Vector3();
plane.normal = -(Vector3.UNIT_Y);


switch (type)
{
case SCENE_SKYPLANE:

mSceneMgr.SetSkyPlane(true, plane, materialName, scale,
tiling, drawFirst, bow, xSegments, ySegments);

mSceneMgr.SetSkyBox(false, "");
mSceneMgr.SetSkyDome(false, "");

break;

case SCENE_SKYBOX:

mSceneMgr.SetSkyBox(true, materialName, dist, drawFirst, quat);
mSceneMgr.SetSkyPlane(false, plane, "");
mSceneMgr.SetSkyDome(false, "");

break;

case SCENE_SKYDOME:

mSceneMgr.SetSkyDome(true, materialName, bow, tiling, dist,
drawFirst, quat, xSegments, ySegments);

mSceneMgr.SetSkyPlane(false, plane, "");
mSceneMgr.SetSkyBox(false, "");

break;

}
}
}
}

private SceneNode CreateNode(XmlElement elet, SceneNode parent)
{
SceneNode pNode = null;

// Try to find the parent node
string pszName = elet.GetAttribute("name");
if (pszName == string.Empty) return null;

// Check if this node has a parent
string pszParent = elet.GetAttribute("parent");
if (pszParent == string.Empty)
{
// Check if the scene node has already been created by a child
DISABLE_LOGMANAGER();

try
{
pNode = mSceneMgr.GetSceneNode(pszName);
}
catch
{
pNode = parent.CreateChildSceneNode(pszName);
}

ENABLE_LOGMANAGER();

}
else
{
SceneNode pParent = null;
DISABLE_LOGMANAGER();

try
{
// Try to find parent scenenode
pParent = mSceneMgr.GetSceneNode(pszParent);
}
catch
{
// We try to create the parent node as child of root node.
// Later when the parent (hopefully) is created, we can adjust it,
// if it is child of another node.
pParent = parent.CreateChildSceneNode(pszParent);
}


try
{
// Check if the scene node has already been created by a child
// In this case we would have to change the parent.
pNode = mSceneMgr.GetSceneNode(pszName);

// Get old parent (probably scene root)
SceneNode pOldParent = pNode.ParentSceneNode;

// Remove this node
pOldParent.RemoveChild(pNode);

// Insert us as child on the "real" parent
pParent.AddChild(pNode);
}
catch
{
pNode = pParent.CreateChildSceneNode(pszName);
}

ENABLE_LOGMANAGER();
}

// Position
XmlElement posElem = (XmlElement)elet.SelectSingleNode("position");
if (posElem != null)
{
Vector3 pos;

pos.x = float.Parse(posElem.GetAttribute("x"), numberFormat);
pos.y = float.Parse(posElem.GetAttribute("y"), numberFormat);
pos.z = float.Parse(posElem.GetAttribute("z"), numberFormat);
pNode.Position = pos;
}

// Rotation
XmlElement rotElem = (XmlElement)elet.SelectSingleNode("rotation");
if (rotElem != null)
{
pNode.SetOrientation(
float.Parse(rotElem.GetAttribute("w"), numberFormat),
float.Parse(rotElem.GetAttribute("x"), numberFormat),
float.Parse(rotElem.GetAttribute("y"), numberFormat),
float.Parse(rotElem.GetAttribute("z"), numberFormat));

}

// Scale
XmlElement scaleElem = (XmlElement)elet.SelectSingleNode("scale");
if (scaleElem != null)
{
Vector3 scale;
scale.x = float.Parse(scaleElem.GetAttribute("x"), numberFormat);
scale.y = float.Parse(scaleElem.GetAttribute("y"), numberFormat);
scale.z = float.Parse(scaleElem.GetAttribute("z"), numberFormat);
pNode.SetScale(scale);
}

// Notify
if (OnNodeCreate != null)
OnNodeCreate(pNode, elet);

// Animation
XmlElement animList = (XmlElement)elet.SelectSingleNode("animations");
if (animList != null)
{
//
foreach (XmlElement animElem in animList.ChildNodes)
{
// Get name of animation
string aniName = animElem.GetAttribute("name");

Animation pAnim = null;
DISABLE_LOGMANAGER();
try
{
pAnim = mSceneMgr.GetAnimation(aniName);
}
catch
{
}
ENABLE_LOGMANAGER();

// If this animation has not been created yet, we create it
if (pAnim == null)
{
float fLength = float.Parse(animElem.GetAttribute("length"), numberFormat);
pAnim = mSceneMgr.CreateAnimation(aniName, fLength);
pAnim.SetInterpolationMode(Animation.InterpolationMode.IM_LINEAR);
}

// Create animation track for this node
NodeAnimationTrack pTrack = pAnim.CreateNodeTrack((ushort)(pAnim.NumNodeTracks + 1), pNode);

// Iterate all keyframes for this node
foreach (XmlElement pKeyframeElem in animElem.ChildNodes)
{
float fTime = float.Parse(pKeyframeElem.GetAttribute("time"), numberFormat);
TransformKeyFrame pKeyFrame = pTrack.CreateNodeKeyFrame(fTime);

// Position
posElem = (XmlElement)pKeyframeElem.SelectSingleNode("position");
if (posElem != null)
{
Vector3 trans;
trans.x = float.Parse(posElem.GetAttribute("x"), numberFormat);
trans.y = float.Parse(posElem.GetAttribute("y"), numberFormat);
trans.z = float.Parse(posElem.GetAttribute("z"), numberFormat);
pKeyFrame.Translate = trans;
}

// Rotation
rotElem = (XmlElement)pKeyframeElem.SelectSingleNode("rotation");
if (rotElem != null)
{
Quaternion qRot;
qRot.x = float.Parse(rotElem.GetAttribute("x"), numberFormat);
qRot.y = float.Parse(rotElem.GetAttribute("y"), numberFormat);
qRot.z = float.Parse(rotElem.GetAttribute("z"), numberFormat);
qRot.w = float.Parse(rotElem.GetAttribute("w"), numberFormat);
pKeyFrame.Rotation = qRot;
}

// Scale
scaleElem = (XmlElement)pKeyframeElem.SelectSingleNode("scale");
if (scaleElem != null)
{
Vector3 scale;
scale.x = float.Parse(scaleElem.GetAttribute("x"), numberFormat);
scale.y = float.Parse(scaleElem.GetAttribute("y"), numberFormat);
scale.z = float.Parse(scaleElem.GetAttribute("z"), numberFormat);
pKeyFrame.Scale = scale;
}
}
}
}

return pNode;
}

private void ENABLE_LOGMANAGER()
{
LogManager.Singleton.SetLogDetail(LoggingLevel.LL_NORMAL);
}

private void DISABLE_LOGMANAGER()
{
LogManager.Singleton.SetLogDetail(LoggingLevel.LL_LOW);
}

private void CreateCameras(XmlNodeList list, SceneNode parent)
{
// Iterate all Cameras, creating them. We do not attach them yet, since
// we need to make sure all potential item entities have been created.
foreach (XmlElement item in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other Cameras
try
{
// Create camera
Camera pCamera = mSceneMgr.CreateCamera(item.GetAttribute("name"));
if (pCamera == null) continue;

// Set Field of View on camera
pCamera.FOVy = new Radian(float.Parse(item.GetAttribute("FOV"), numberFormat));
pCamera.NearClipDistance = 5;

// Create node with full information
SceneNode pCameraNode = CreateNode(item, parent);

// Attach the Camera entity to node
pCameraNode.AttachObject(pCamera);

// Target
XmlElement targetElem = (XmlElement)item.SelectSingleNode("target");
if (targetElem != null)
{
// Create node with full information
SceneNode pTargetNode = CreateNode(targetElem, parent);
pCameraNode.SetAutoTracking(true, pTargetNode);
}

// Notify
if (OnCameraCreate != null)
OnCameraCreate(pCamera, item);

// Add to camera list
cameras.Add(pCamera.Name, pCamera);
}
catch
{
continue;
}
}
}

private void CreateLights(XmlNodeList list, SceneNode parent)
{
// Iterate all Lights, creating them. We do not attach them yet, since
// we need to make sure all potential parent entities have been created.
foreach (XmlElement pLightElem in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other Lights
try
{
string pszName = pLightElem.GetAttribute("name");

Light pLight = mSceneMgr.CreateLight(pszName);
if (pLight == null) continue;

// Figure out which type of light we are using
string pszType = pLightElem.GetAttribute("type");
if (pszType == "omni")
{
pLight.Type = Light.LightTypes.LT_POINT;
}
else if (pszType == "spot")
{
pLight.Type = Light.LightTypes.LT_SPOTLIGHT;
pLight.SetSpotlightRange(
new Radian(new Degree(float.Parse(pLightElem.GetAttribute("hotspot"), numberFormat))),
new Radian(new Degree(float.Parse(pLightElem.GetAttribute("falloff"), numberFormat))));
pLight.SetDirection(0, 0, -1);

}
else if (pszType == "directional")
{
pLight.Type = Light.LightTypes.LT_DIRECTIONAL;
}

// Check if the light should be on
string pszOn = pLightElem.GetAttribute("on");
if (pszOn == "true")
pLight.Visible = true;
else
pLight.Visible = false;

// Check if the object should cast shadows
string pszCastShadows = pLightElem.GetAttribute("CastShadows");
if (pszCastShadows == "no")
pLight.CastShadows = false;
else
pLight.CastShadows = true;

// Diffuse Color
XmlElement colorElem = (XmlElement)pLightElem.SelectSingleNode("color");
if (colorElem != null)
{
pLight.SetDiffuseColour(
float.Parse(colorElem.GetAttribute("r"), numberFormat),
float.Parse(colorElem.GetAttribute("g"), numberFormat),
float.Parse(colorElem.GetAttribute("b"), numberFormat));
}

// Specular Color
XmlElement specularElem = (XmlElement)pLightElem.SelectSingleNode("specular");
if (specularElem != null)
{
pLight.SetSpecularColour(
float.Parse(specularElem.GetAttribute("r"), numberFormat),
float.Parse(specularElem.GetAttribute("g"), numberFormat),
float.Parse(specularElem.GetAttribute("b"), numberFormat));
}

// Attenuation
XmlElement attenElem = (XmlElement)pLightElem.SelectSingleNode("attenuation");
if (attenElem != null)
{
pLight.SetAttenuation(
float.Parse(attenElem.GetAttribute("range"), numberFormat),
float.Parse(attenElem.GetAttribute("constant"), numberFormat),
float.Parse(attenElem.GetAttribute("linear"), numberFormat),
float.Parse(attenElem.GetAttribute("quadratic"), numberFormat));
}

// Create node with full information
SceneNode pLightNode = CreateNode(pLightElem, parent);

// Attach the Light entity to node
pLightNode.AttachObject(pLight);

// Target
XmlElement targetElem = (XmlElement)pLightElem.SelectSingleNode("target");
if (targetElem != null)
{
// Create node with full information
SceneNode pTargetNode = CreateNode(targetElem, parent);
pLightNode.SetAutoTracking(true, pTargetNode);
}

// Notify
if (OnLightCreate != null)
OnLightCreate(pLight, pLightElem);

// Add to light list
lights.Add(pszName, pLight);
}
catch
{
continue;
}
}
}

private void CreateEntities(XmlNodeList list, SceneNode parent)
{
// Iterate all meshes, creating them.
foreach (XmlElement pMeshElem in list)
{
// Ogre could cast an exception, in which case we just try to
// continue reading the other meshes
try
{
string pszName = pMeshElem.GetAttribute("name");
string pszFileName = pMeshElem.GetAttribute("filename");

// try to create the mesh
Entity pEntity = mSceneMgr.CreateEntity(pszName, pszFileName);
if (pEntity == null) continue;

// Check if the object should cast shadows
string pszCastShadows = pMeshElem.GetAttribute("CastShadows");
if (pszCastShadows == "no")
pEntity.CastShadows = false;
else
pEntity.CastShadows = true;

// Create node with full information
SceneNode pObjNode = CreateNode(pMeshElem, parent);

// Attach the mesh entity to node
pObjNode.AttachObject(pEntity);

// Notify
if (OnEntityCreate != null)
OnEntityCreate(pEntity, pMeshElem);

// Add to entity list
entities.Add(pszName, pEntity);
}
catch (Exception ex)
{
continue;
}
}
}
}

public delegate void LoadedSceneObjectEventHandler(Object obj, XmlElement xmlSrc);

}

Bekas

05-01-2007 12:58:09

Nice, can you update the wiki page as well?