Hey there everyone.
I've just been working on state management in my team's game engine and we're using .NET 2.0 as our framework (obviously). The system uses an abstract class to represent a state change, and then these are linked together into a tree to create the scene representation.
Everything seems to be working well at the moment - it's doing whats expected, but I'm sure it can do it (the traversal mainly) faster than it is at the moment. So I present to you, my material system code.
The first snippet is my abstract state change class. This is most of the meat on the state changes themselves.
abstract class StateChange
{
protected StateChange parent;
protected List<StateChange> children = new List<StateChange>();
protected List<SceneEntity> entities = new List<SceneEntity>();
protected StateManager manager;
public StateManager StateManager
{
get { return manager; }
set { manager = value; }
}
internal List<StateChange> Children
{
get { return children; }
}
internal List<SceneEntity> Entities
{
get { return entities; }
}
public StateChange Parent
{
get { return parent; }
set
{
value.AddChild(this);
}
}
public void AddChild(StateChange child)
{
// First, check that the child did not previously have a parent, and if so - remove the child from the parent
if (child.parent != null)
{
child.parent.RemoveChild(child);
}
// Now add the child, and set its parent.
if (!children.Contains(child))
{
children.Add(child);
child.parent = this;
}
}
private void RemoveChild(StateChange child)
{
if (children.Contains(child))
{
children.Remove(child);
child.parent = null;
}
else
throw new NullReferenceException("Unable to remove a state change that is not a child of this parent");
}
public void AddEntity(SceneEntity entity)
{
if(!entities.Contains(entity))
entities.Add(entity);
}
public abstract void Apply();
}
An example implemtation of this is:
class ShaderTexture : StateChange
{
private string parameter;
private Microsoft.DirectX.Direct3D.Texture texture;
public Microsoft.DirectX.Direct3D.Texture Texture
{
get { return texture; }
set { texture = value; }
}
public string Parameter
{
get { return parameter; }
set { parameter = value; }
}
public ShaderTexture(string parameter, Microsoft.DirectX.Direct3D.Texture texture)
{
this.parameter = parameter;
this.texture = texture;
}
public override void Apply()
{
manager.ActiveShader.SetVariable(parameter, texture);
}
}
}
And here is how I'm traversing the scene:
internal class StateTraverser
{
RenderVisitor renderVisitor = new RenderVisitor();
Matrix view, projection;
internal void Enter(StateChange change)
{
view = Engine.Active.SceneManager.ActiveCamera.View;
projection = Engine.Active.SceneManager.ActiveCamera.Projection;
VisitNode(change);
}
void VisitNode(StateChange change)
{
change.Apply();
foreach (StateChange sc in change.Children)
VisitNode(sc);
foreach (SceneEntity e in change.Entities)
if (e.IsVisible)
{
Engine.Active.GraphicsDevice.States.ActiveShader.Update(e.WorldMatrix * Engine.Active.SceneManager.RootWorld, view, projection);
Engine.Active.GraphicsDevice.States.ActiveShader.Direct3DEffect.CommitChanges();
e.Accept(renderVisitor);
}
}
}
Now my main concerns are with copying data and stuff. I think when I do "foreach SceneEntity e in change.Entities" there's some type of copy happening. Sure I read something like that somewhere.
Anyway, any ideas are appreciated!