LuRenJia
19-06-2006 09:34:15
Hi all!
I had converted oFusion SceneLoader from c++ to c# yesterday, but not test yet, any one would like to test it?
The source code posted below:
I had converted oFusion SceneLoader from c++ to c# yesterday, but not test yet, any one would like to test it?
The source code posted below:
using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Xml;
using Math3D;
using OgreDotNet;
namespace OgreAddons
{
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.Instance.logMessage(@"
**********************************************
** OSM Scene Loader **
**********************************************
");
LogManager.Instance.logMessage("OSMLoader loading scene form file: " + xmlFile);
if (!File.Exists(xmlFile))
{
LogManager.Instance.logMessage("Not found file: " + xmlFile);
throw new FileNotFoundException("Not found scene file.", xmlFile);
}
xd = new XmlDocument();
try
{
xd.Load(xmlFile);
}
catch (XmlException ex)
{
xd = null;
LogManager.Instance.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.Instance.logMessage("OSMLoader: Creating scene on '" +
(parent == null ? "Root" : parent.Name) + "' node.");
if (mSceneMgr == null)
{
if (xd.SelectSingleNode("/sceneManager") != null)
setSceneProperties(xd);
else
mSceneMgr = Root.GetSingleton().CreateSceneManager((ushort) SceneType.Generic);
}
if (parent == null)
mSceneMgr.RootSceneNode.CreateChildSceneNode();
try
{
CreateCameras(xd.SelectNodes("/cameras/*"), parent);
}
catch
{
}
try
{
CreateLights(xd.SelectNodes("/lights/*"), parent);
}
catch
{
}
try
{
CreateEntities(xd.SelectNodes("/entities/*"), parent);
}
catch
{
}
LogManager.Instance.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 Color parseColor(string r, string g, string b)
{
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.Instance.CreateSceneManager((ushort) 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)
{
Color color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));
mWindow.GetViewport(0).SetBackgroundColour(color);
}
// Ambient light Color
colorElem = (XmlElement) xd.SelectSingleNode("lightColor");
if (colorElem != null)
{
Color color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));
mSceneMgr.SetAmbientLight(color);
}
// Scene shadows
XmlElement shadowsElem = (XmlElement) xd.SelectSingleNode("shadowTechnique");
if (shadowsElem != null)
{
type = int.Parse(shadowsElem.GetAttribute("type"));
ShadowTechnique shadowType = (ShadowTechnique) type;
mSceneMgr.SetShadowTechnique(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)
{
Color color = parseColor(
colorElem.GetAttribute("r"),
colorElem.GetAttribute("g"),
colorElem.GetAttribute("b"));
mSceneMgr.SetShadowColour(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 OgreVector3(-Vector3.UnitY);
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 == null) return null;
// Check if this node has a parent
string pszParent = elet.GetAttribute("parent");
if (pszParent == null)
{
// 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.SetPosition(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.Linear);
}
// Create animation track for this node
NodeAnimationTrack pTrack = pAnim.CreateNodeTrack((ushort) (pAnim.GetNumNodeTracks() + 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.SetTranslate(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.SetRotation(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.SetScale(scale);
}
}
}
}
return pNode;
}
private void ENABLE_LOGMANAGER()
{
throw new NotImplementedException();
}
private void DISABLE_LOGMANAGER()
{
throw new NotImplementedException();
}
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.SetFOVy(new Radian(float.Parse(item.GetAttribute("FOV"))));
pCamera.SetNearClipDistance(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.Point;
}
else if (pszType == "spot")
{
pLight.Type = Light.LightTypes.Spot;
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.Directional;
}
// Check if the light should be on
string pszOn = pLightElem.GetAttribute("on");
if (pszOn == "true")
pLight.SetVisible(true);
else
pLight.SetVisible(false);
// Check if the object should cast shadows
string pszCastShadows = pLightElem.GetAttribute("CastShadows");
if (pszCastShadows == "no")
pLight.SetCastShadows(false);
else
pLight.SetCastShadows(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.SetCastShadows(false);
else
pEntity.SetCastShadows(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
{
continue;
}
}
}
}
public delegate void LoadedSceneObjectEventHandler(Object obj, XmlElement xmlSrc);
}