Collada::getBoundingBox()
{
// The Collada object has a scene graph which always has one root.
// We pass in an identity matrix since the Root is a TransformNode
// which wants a matrix. We could also pass in null and do a check.
return sceneGraph.getRoot().getBoudingBox(identityMatrix);
}
A root node is actually just an instance of a TransformNode which main purpose is to hold a transformation matrix. Calling the TransformNode’s getBoundingBox will walk down
the graph until we reach the base case and call the GeometryNode’s getBoundingBox().
TransformNode::getBoundingBox(matrix)
{
// don’t set these to zero as the smallest vertex may actually be a
// positive number, instead use undefined to flag there are no values
// associated with these variables. This was one of my bugs.
var minVertex, maxVertex, boudingBox;
for( all child nodes)
{
// get the bounding box of all the children.
var boundingBox = child[iter].getBoundingBox(matrix * thisTransform);
// if we don’t have any values for the min and max, then use the values
// returned form the first child.
if(minVertex is not defined)
{
minVertex = new Array(boundingBox[0], boundingBox[1], boundingBox[2]);
maxVertex = new Array(boundingBox[3], boundingBox[4], boundingBox[5]);
}
else
{
for( i =0; i < 3 i++ )
{
if( boundingBox[i] < min) min[i] = boundingBox;
}
for( i =3; i < 6 i++ )
{
if( boundingBox[i] > max) max[i] = boundingBox;
}
}
}
return boundingBox;
}
The purpose of the geometry node is to store geometry, in our case it will store a Model instance, which has all the vertices.
GeometryNode::getBoudingBox(matrix)
{
var minVertex, maxVertex;
// Here was another bug. Previously I had been just getting the bounding box of the
// model (in model space), returning it, then transforming it and then finally comparing.
// The vertices need to be transformed first then compared.
for( all verts in model)
{
var v = vert * matrix;
if(minVertex is undefined)
{
minVertex = maxVertex = v;
}
else
{
for(var i=0; i < 3; i++)
{
if( v[i] < minVertex[i] ) minVertex[i] = v[i];
}
for(var i=0; i < 3; i++)
{
if( v[i] > maxVertex[i] ) maxVertex[i] = v[i];
}
}
}
return [minVertex[0], minVertex[1], minVertex[2], maxVertex[0], maxVertex[1], maxVertex[2]];
}
Going back to the scenegraph having only one root, this created some problems. When I wrote the parser, I noticed the standard allowed many nodes to be at the top level. However, I needed to have only a single root node, which would make transforming entire Collada objects simple. If a Collada object was transformed, it would just relay that transformation to the scenegraph’s root.Therefore if the collada file has 2 nodes, one transform and one geometry, my parser adds a root node. The Collada object in memory will therefore have 3 nodes: the root with an identity, then the transform node and finally the geometry. This caused me some frustration when I tried getting the transform of the Collada object and it was returning an identity, but the object obviously wasn’t at the origin.
Halfway through my debugging I decided to add a visual box, numbers weren’t cutting it anymore. It helped me quite a bit.
Alas, I have approached the summit. With my hands, I have created a Mac application, which runs, and has the customized chrome interface. This alone is an incredible feat for me, since I rarely create GUI-based programs, and I certainly haven’t developed them on a Mac before. The only problem is that the canvas element isn’t rendering.
I’m so close, goshdarnit…
In the real world there are many phenomena which exist as set of particles, such as falling snow, sparks from arc welding, rain and fireworks. Systems which manage (create, update and destroy) a set of these particles are known as particle systems. Particle systems typically keep track of these particles with a collection such as an array, vector or list. If you examine falling snow, you will notice the particles all behave similarly, falling downwards to the ground, but do so slightly differently. They will have different positions and vary slightly in x and z speeds. This slight variation applies to all particle systems and gives them a sense of realism. However, particle systems aren’t limited to the previous examples, but can also model things like fog, smoke, fire, water, waterfalls, a flock of birds or almost anything given the proper logic for moving the particles.When I started designing the basics of implementing a particle system in the library, I decided to break down the implementation into 3 main parts: the particle, subsystem and the actual particle system.
At its most basic implementation a particle will have properties such as position, velocity, age and lifetime. The particle is placed somewhere in the world and moves about, after its age exceeds its lifetime, the particle dies and is no longer updated and drawn. When a new particle is required, it can reuse the old one by resetting its attributes. Additional attributes I decided to add are color and size.
A SubSystem is a particle system in itself, albeit downgraded just to create a class which a particle system can hold. For example, in a fire particle system, there are many different types of particle systems: the embers which do not move, but glow, flames which move quickly, smoke which has a long lifetime and sparks which follow a trajectory-like path. Each of these can be a subsystem added into a fire particle system. Their positions will be relative to the particle system and if the particle system moves, so do the subsystems. A subsystem will have properties every particle will have such as image/texture, blend modes, acceleration and animation state(playing, paused, stopped).
When a particle is born, it will receive random values for all of its properties based on a range which the user provides. If the user is specifying smoke particles, they’ll likely want the smoke to range from gray to black.
Finally the Particle System will contain a list of subsystems. The user will be able to pause the animation of individual subsystems and move the subsystems around relative to the particle system.
Technicalities
In the past, when implementing a particle system, one would create a textured, billboarded quadrilateral for each particle. This would be a primitive with four vertices which always faces the camera. That way the texture is not skewed when the camera isn’t looking at it. Billboarding can be a waste of processing and using four vertices is a waste of memory, since what users really want is to slap a texture onto a point. Rendering API architects then provided support for point sprites. As for OpenGL, they started supporting it with version 1.5. Point sprites are view-space aligned textured points. That is, single vertices with a textured placed at the center of the point. This makes implementing particles system much more efficient and easy. Users no longer have to manually orient the particles and they have to specify only one vertex instead of four. The trade off of point sprites is they cannot be rotated; the sides of the texture will always be parallel to the viewport. There are some cases in which rotating a particle is desired, for example when modeling falling leaves or a spiral texture that spins.No point sprites
OpenGLES does not support point sprites, which is a shame. It doesn’t support quads either; however it is possible to specify vertices as a triangle fan, effectively keeping particles limited to four points. Since we are stuck using a quad, there might as well be an option to assign angular velocity to the particles as well as a choice of billboarding them.Future Work
Particle systems can create impressive effects, they can be even more interesting events are added. Events can change the attributes of a particle which would not usually change, such as color or size. We can create time-based events which change the size of the particle as it ages, making its disappearance less abrupt. Events could also be position-based, which are triggered when a particle gets to a certain height at which point its color changes. Once the basics are in place of the subsystems and particle system, I will create the classes necessary to make events.Usage
Right now I’m treating the subsystem as the particle system itself as I build it up. This is how I’m setting up the subsystem.var psys = new SubSystem();
psys.setMinVelocity([-1,-1, -1]);
psys.setMaxVelocity([1,1, 1]);
psys.setMinLifetime(1);
psys.setMaxLifetime(15);
psys.setMinColor([0,0,.4,1]);
psys.setMaxColor([0,0,1,1]);
psys.setTexture("particle.jpg");
psys.setAcceleration([0,1,0]);
psys.init(50);
scn.addObjectToScene(psys);
Example
You can check out a primitive example here if you have the Canvas3D extension. Recently we have added 3 more people to our team so I thought it fitting to do a brief introduction. Shawn Dinis, Michael Segal, and Chay Edry will now be joining our team to help us make some cool demos. I wanted to start by welcoming them to our team. The three of them will be working on making use of our library for making cool demos. Some of the stuff coming up will be very interesting. One of the first things that we need to change desparately is our front page. That red spinning teapot is just not cutting it anymore. Our library is capable of doing so much more now. I would love to see something cooler looking there. My initial thought was to do a small carnival type game on the front. Something that moved and showed off the library. Chay’s words were “that wouldn’t be very interesting to look at. i have a much better idea!”. I’ll hold off on describing what Chay is planning for now but I if it even comes close to doing what he said it would, it would definitely be much better than my little carnival booth. I’ve been toying around with refactoring the canvs3d library using namespace is “proper” object oriented inheritance. Proper meaning within the construct of the JavaScript language.The refactoring is far from complete however, a major milestone (in my eyes) has been accomplished today. Rendering a triangle on the screen and using the camera to rotate around it, using the OpenGLES1.1 rendering context. I’ve been working on bits and pieces and leaving empty stubs for the OpenGLES20 context code. The intention to get a working proof of concept for the code layout as soon as possible. The code has been designed with the intention of supporting both contexts though, so it should only be a matter of going back and filling in 2.0 context specific code where its needed.One of the many objectives with the refactorization is to clear up the global scope of all the library variables, functions and objects–and that has certainly been accomplished. Everything resides within the global variable “c3dl”. For example, constants are defined in the c3dl property “const”. For example the “TOLERANCE” constant that represents the smallest size of a number before it’s considered to be zero can be accessed as “c3dl.const.TOLERANCE”.
Another new feature is the use of default parameters for certain function calls. Currently, because only such a small part of the code base has been converted, only one or two functions make use of the feature–but as the code gets converted more functions certainly will. The call to the scene constructor now makes use of a second parameter called options. The options is an object literal where you can specify attributes to overide the scene defaults. Take a look at this code from the api source, it defines the defaults that are currently used for the scene constructor.
// default parameters passed to scene constructor
c3dl.scene.defaults = {
// background color of scene
clearColor: new Array(0.4, 0.4, 0.5, 1.0),
// default to newest and greatest gles
renderer: c3dl.renderer.OpenGLES11,
// default camera
camera: c3dl.camera
};
What this means is that the minimal code required for creating a scene and getting it going has become much simpler. The following code is taken from the refactorization folder in demos, the hello world demo demonstrates utilizing c3dl api to render a triangle on the screen. This code is all that is needed to render a triangle on the screen.
var scn = new c3dl.scene('viewport');
// add an object
var tri = new c3dl.primitive.triangle();
scn.add(tri);
scn.start();
As you can see, all you need to do is pass the canvas tag Id to the scene constructor, create a triangle primitive and add it to the scene and you are off and running.This new simplicity does not hinder your ability be more specific though! What if you wanted to use the OpenGLES2.0 context, and use a chase camera instead of a free camera? Easy, simply override the defaults. The following code accomplishes just that.
var scn = new c3dl.scene('viewport', {camera: c3dl.camera.chase, renderer: c3dl.renderer.OpenGles20});
// add an object
var tri = new c3dl.primitive.triangle();
scn.add(tri);
scn.start();
As you can see this will finally allow us to deliver extremely simple API use with optional fine grain control.
So anyway, the new code is available in SVN under c3dl_namespace of the root folder. I invite you to take a look.
Cheers.
PS: The demo scene loop uses a little speed hack to acheive frames per second upwards of 400. Heres a screen shot of the demo running at ~800 fps.

