Going with creating a scene in a script doesn't give me any kind of perf gains or fancy new features but it does make iteration faster and easier moving forward. I no longer have to worry about updating my XML schema every time I want to add a new component. I still need to bind the new component to Lua but that's a far quicker task. This work also had the side effect of getting me to do a little bit of refactoring as well. My XML loading code was doing some work that should have been placed elsewhere so now it is cleaned up and hopefully a bit more straight forward.
Thanks go out to Jason Z who had the suggestion of going with a script over XML in an earlier journal post.
Here's what an example script file looks like right now. Not really sexy but it is functional and fairly readable as well:
-- Lighting Objects
Scene:SetAmbient(0.2, 0.2, 0.2, 1.0)
Light1 = CLight:new()
Light1:SetName("Light1")
Light1:SetDirection(0.408248,-0.816497,0.408248)
Light1:SetDiffuse(0.0,0.8,0.0,1.0)
Light1:SetSpecular(1.0,1.0,1.0,1.0)
Scene:AddLight(Light1)
Light2 = CLight:new()
Light2:SetName("Light2")
Light2:SetDirection(0.408248,-0.816497,-0.408248)
Light2:SetDiffuse(0.8,0.0,0.0,1.0)
Light2:SetSpecular(1.0,1.0,1.0,1.0)
Scene:AddLight(Light2)
-- Camera
Camera = CCamera:new()
Camera:SetPosition(6.0,3.0,5.0)
Camera:SetLookAt(2.0,0.0,5.0)
Camera:SetUp(0.0,1.0,0.0)
Camera:SetView(45.0,0.1,20.0)
Scene:SetCurrentCamera(Camera)
------------- Game Objects
-- General Input Handler
Object1 = CGameObject:new()
Object1:SetName("General")
Object1:SetEnabled(true)
Script1 = Scene:RequestScript("../../data/HelloWorld.lua")
InputListen1 = CInputListener:new()
InputListen1:SetScript(Script1)
Object1:SetInputListener(InputListen1)
Scene:AddObject(Object1)
-- Duck Model Object
Object2 = CGameObject:new()
Object2:SetName("Duck")
Object2:SetEnabled(true)
-- Create Positionable
Positionable1 = CPositionable:new()
Positionable1:SetPosition(2.0,0.0,5.0)
Positionable1:SetRotation(0.0,0.0,0.0)
Positionable1:SetScale(1.0,1.0,1.0)
Object2:SetPositionable(Positionable1)
-- Load Resources
Material1 = Scene:RequestMaterial("Metal",64.0,1.0,1.0,1.0,1.0)
Texture1 = Scene:RequestTexture("../../data/duckCM.tga")
Texture2 = Scene:RequestTexture("../../data/hello2.tga")
Shader1 =
Scene:RequestShader("MVPLight","../../data/StandardMVP.v.glsl","../../data/Lighting.f.glsl")
Mesh1 = Scene:RequestMesh("../../data/duck.dae")
Mesh1:SetMaterial(Material1)
-- Create Renderable
Renderable1 = CRenderable:new()
Renderable1:SetTexture(0,Texture1)
Renderable1:SetTexture(1,Texture2)
Renderable1:SetShader(Shader1)
Renderable1:SetMesh(Mesh1)
Renderable1:SetWireFrame(false)
Object2:SetRenderable(Renderable1)
Scene:AddObject(Object2)
-- Box Model
Object3 = CGameObject:new()
Object3:SetName("Box")
Object3:SetEnabled(true)
-- Create Positionable
Positionable2 = CPositionable:new()
Positionable2:SetPosition(-2.0,0.0,5.0)
Positionable2:SetRotation(0.0,0.0,0.0)
Positionable2:SetScale(1.0,1.0,1.0)
Object3:SetPositionable(Positionable2)
-- Load Resources
Material2 = Scene:RequestMaterial("Metal",64.0,1.0,1.0,1.0,1.0)
Texture3 = Scene:RequestTexture("../../data/test.png")
Texture4 = Scene:RequestTexture("../../data/hello2.tga")
Shader2 =
Scene:RequestShader("MVPLight","../../data/StandardMVP.v.glsl","../../data/Lighting.f.glsl")
Mesh2 = Scene:RequestMesh("../../data/test.x")
Mesh2:SetMaterial(Material2)
-- Create Renderable
Renderable2 = CRenderable:new()
Renderable2:SetTexture(0,Texture3)
Renderable2:SetTexture(1,Texture4)
Renderable2:SetShader(Shader2)
Renderable2:SetMesh(Mesh2)
Renderable2:SetWireFrame(false)
Object3:SetRenderable(Renderable2)
Scene:AddObject(Object3)
-- Overlay Test Object
Object4 = CGameObject:new()
Object4:SetName("Overlay")
Object4:SetEnabled(true)
-- Create Positionable
Positionable3 = CPositionable:new()
Positionable3:SetPosition(0.0,0.0,0.0)
Positionable3:SetRotation(0.0,0.0,0.0)
Positionable3:SetScale(1.0,1.0,1.0)
Object4:SetPositionable(Positionable3)
-- Load Resources
Texture5 = Scene:RequestTexture("../../data/hello1.tga")
Texture6 = Scene:RequestTexture("../../data/hello2.tga")
Shader3 =
Scene:RequestShader("Ortho","../../data/StandardMVP.v.glsl","../../data/NoLighting.f.glsl")
Quad1 = CQuad:new(0.0,0.0,1.0,1.0,0.0,0.0,1.0,1.0)
-- Create Renderable
Renderable3 = CRenderable:new()
Renderable3:SetTexture(0,Texture5)
Renderable3:SetTexture(1,Texture6)
Renderable3:SetShader(Shader3)
Renderable3:SetQuad(Quad1)
Renderable3:SetWireFrame(false)
Renderable3:SetOrthogonal(true)
Object4:SetRenderable(Renderable3)
Scene:AddObject(Object4)
[color=#1C2837][size=2][color=#660066]Light2[/color][color=#000000] [/color][color=#666600]=[/color][color=#000000] [/color][color=#660066]CLight[/color][color=#666600]:[/color][color=#000088]new[/color][color=#666600]()[/color][color=#000000]
[/color][color=#660066]Light2[/color][color=#666600]:[/color][color=#660066]SetName[/color][color=#666600]([/color][color=#008800]"Light2"[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Light2[/color][color=#666600]:[/color][color=#660066]SetDirection[/color][color=#666600]([/color][color=#006666]0.408248[/color][color=#666600],-[/color][color=#006666]0.816497[/color][color=#666600],-[/color][color=#006666]0.408248[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Light2[/color][color=#666600]:[/color][color=#660066]SetDiffuse[/color][color=#666600]([/color][color=#006666]0.8[/color][color=#666600],[/color][color=#006666]0.0[/color][color=#666600],[/color][color=#006666]0.0[/color][color=#666600],[/color][color=#006666]1.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Light2[/color][color=#666600]:[/color][color=#660066]SetSpecular[/color][color=#666600]([/color][color=#006666]1.0[/color][color=#666600],[/color][color=#006666]1.0[/color][color=#666600],[/color][color=#006666]1.0[/color][color=#666600],[/color][color=#006666]1.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Scene[/color][color=#666600]:[/color][color=#660066]AddLight[/color][color=#666600]([/color][color=#660066]Light2[/color][color=#666600])[/color][color=#000000]
[/color][color=#666600]--[/color][color=#000000] [/color][color=#660066]Camera[/color][color=#000000]
[/color][color=#660066]Camera[/color][color=#000000] [/color][color=#666600]=[/color][color=#000000] [/color][color=#660066]CCamera[/color][color=#666600]:[/color][color=#000088]new[/color][color=#666600]()[/color][color=#000000]
[/color][color=#660066]Camera[/color][color=#666600]:[/color][color=#660066]SetPosition[/color][color=#666600]([/color][color=#006666]6.0[/color][color=#666600],[/color][color=#006666]3.0[/color][color=#666600],[/color][color=#006666]5.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Camera[/color][color=#666600]:[/color][color=#660066]SetLookAt[/color][color=#666600]([/color][color=#006666]2.0[/color][color=#666600],[/color][color=#006666]0.0[/color][color=#666600],[/color][color=#006666]5.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Camera[/color][color=#666600]:[/color][color=#660066]SetUp[/color][color=#666600]([/color][color=#006666]0.0[/color][color=#666600],[/color][color=#006666]1.0[/color][color=#666600],[/color][color=#006666]0.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Camera[/color][color=#666600]:[/color][color=#660066]SetView[/color][color=#666600]([/color][color=#006666]45.0[/color][color=#666600],[/color][color=#006666]0.1[/color][color=#666600],[/color][color=#006666]20.0[/color][color=#666600])[/color][color=#000000]
[/color][color=#660066]Scene[/color][color=#666600]:[/color][color=#660066]SetCurrentCamera[/color][color=#666600]([/color][color=#660066]Camera[/color][color=#666600])[/color][/size][/color]
I might set it up as:
[code]
scene=
{
{name="Light1", type=CLight, direction={0.408248, -0.816497, 0.408248}, diffuse={0,0.8,0,1}, specular={1,1,1,1},
{name="Camera", type=CCamera, position={6.0,3.0,5.0}, lookat={2.0,0.0,5.0}, up={0,1,0}, view={45,0.1,20}
}
[/code]
then write code to parse these types of table declarations, and create the appropriate object. This saves a LOT of typing, and provides conciseness and better human-readability. An entire scene or sub-scene can be grouped in a single table and parsed as a whole, and you can even nest descriptors for parent-child relationships.