Ok, now I want to provide some code snippets from the ported Chicago sample.
After starting the application, the HordePanel has to be initialized. This should be done in the Load method of the form where the panel lies in. We also add all the controls we need like the two lights, the skybox and, of course, the crowd:
Code:
private void MainForm_Load(object sender, EventArgs e)
{
// configure horde options
HordeOptions options = new HordeOptions();
options.Pipeline = "pipeline_Chicago.xml";
options.FastAnimation = true;
// init the panel
hordePanel1.Init(options);
// create controls
SceneGraphObject env = new SceneGraphObject(new SceneGraphResource("scene.scene.xml"));
SceneGraphObject skybox = new SceneGraphObject(new SceneGraphResource("skybox.scene.xml"));
Light light1 = new Light("Light1", new Material("light.material.xml"));
Light light2 = new Light("Light2", new Material("light.material.xml"));
Camera camera = new Camera();
CrowdControl crowd = new CrowdControl();
// configure controls
skybox.Scale = new Point3D(500, 500, 500);
camera.Position = new Point3D(0, 10, 0);
camera.Rotation = new Point3D(-90, 0, 0);
light1.Position = new Point3D(0,25,-25);
light1.Rotation = new Point3D(-120,0,0);
light1.Radius = 100;
light1.FOV = 90;
light1.Col_B = 0.5f;
light1.Col_R = 0.98f;
light1.Col_G = 0.6f;
light2.Position = new Point3D(0, 25, 30);
light2.Rotation = new Point3D(-60, 0, 0);
light2.Radius = 50;
light2.FOV = 90;
light2.Col_B = 0.98f;
light2.Col_R = 0.5f;
light2.Col_G = 0.6f;
// add controls to panel
hordePanel1.Add(light1);
hordePanel1.Add(light2);
hordePanel1.Add(skybox);
hordePanel1.Add(env);
hordePanel1.Add(camera);
hordePanel1.Add(crowd);
}
That's all we have to do in the form. You may have noticed the "CrowdControl" class. This is a class we implemented in this sample. This class inherits from the HordeControl "Container" and it has the possibility to hold arbitrary other HordeControls in a list.
Here comes the class:
Code:
public class CrowdControl : Container
{
public CrowdControl()
{
for (int i = 0; i < 100; i++)
Add(new ManControl(i));
}
public override void Render(float fps)
{
base.Render(fps);
update(fps);
}
[...]
The CrowdControl has 100 "ManControl" in it's list. The "Render" method is called from the HordePanel in each Rendering loop for every control that has been added to the panel. So if we override it, we can do our application logic in every rendering loop. The Chicago sample calculates the new position and direction of each man in every loop, so we do the same in the update(...) method. We only had to change that the update method accesses the list of the CrowdControl and not the "old" "particle" list. We did not touch the calculation.
The only remaining thing is the ManControl class. A "man" consists of a SceneGraph node and an animation and he has the fields from the Chicago sample (fx, fy...). So we use an AnimationControl combined with a SceneGraphControl and we are done:
Code:
AnimatedObject _anim;
SceneGraphObject _man;
private int _index;
public float fx;
public float fz;
public float ox;
public float oz;
public float dx;
public float dz;
public float px;
public float pz;
public ManControl(int index)
{
_index = index;
_man = new SceneGraphObject(new SceneGraphResource("man.scene.xml"));
_anim = new AnimatedObject(_man,new Animation("man.anim"));
_anim.AnimationSpeed = 20.0f;
}
public override void Render(float fps)
{
_anim.Render(fps);
}
Because Horde3D renders the scene graph nodes one it's own, we only have to worry about that the animation is continued in the Render method.
You see that there is only the "application" logic that we had to implement. We do not care about Horde3D specific things. That is of course not suitable for all applications, because some may want to have the full possibilities the engine offers. But as mentioned, for small to medium sized applications and for programmers who start programming with a 3D engine, these HordeControls may be a good alternative.