I’ve just finished updating the particle systems demo. There wasn’t anything wrong with the demo itself, but there was an array in the particle system class that wasn’t being initialized properly that suddenly started causing Minefield to crash. The strange thing is that until recently Minefield wasn’t complaining about it. But as of the nightly build on the 23rd it didn’t just complain, it outright crashed. By populating the array with 0s when it is initialized, I’ve got particles working again. The misleading problem was that this happened at the same time I was fixing an issue with colours for Chromium was preventing it from displaying. It started crashing one browser at the same time I fixed a problem for another. It turns out that was caused because colour values were being read out of a file and split into an array, but they were never explicitly made into floating point values. Minefield and Webkit understood them as such anyway, but Chromium didn’t like that. A temporary solution was to multiply the values by 1 before using them, but that isn’t a very good solution. Once I actually traced the problem to its source, a quick parseFloat took care of it. Slightly slower, but more correct.
Something we need to do is simplify the C3DL library interface. When approaching such tasks, one method I found extremely useful was to analyze the code in terms of the interface, or that is from the user’s perspective. To do this I first created a basic demo of a spinning cube by writing the necessary HTML and JavaScript files. As for the HTML, it will need to be something like this:
(I emphasized the code which potentially could be changed)
<html>
<head>
<title>Cavas3D Demo</title>
<script>var SCRIPT_PATH = '../../canvas3dapi/'</script>
<script src="../../canvas3dapi/c3dapi.js"></script>
<script src="basic_demo.js"></script>
</head>
<body>
<canvas id="demo" width="500" height="500"></canvas>
</body>
</html>
It would be great if this could be simplified to something like this:
<html>
<head>
<title>Cavas3D Demo</title>
<script src="../../canvas3dapi/c3dapi.js"></script>
</head>
<body>
<canvas datasrc="basic_demo.js" id="demo" width="500" height="500">
</canvas>
</body>
</html>
I removed the somewhat unintuitive SCRIPT_PATH variable and moved the basic_demo.js resource into the canvas tag making it more obvious which .js file is associated to which canvas. These changes haven’t actually been made, I’m just playing with possible changes, brainstorming which parts might be able to be modified.Now, very few changes were made here and it will probably require a significant amount of effort to make it work. But this work is justified by the fact that the user’s experience and first impression will be more positive. If the user has to spend more than a few minutes trying to get a simple example to render, they’ll probably look for alternatives.
Let’s see how the JavaScript could be changed. Right now, you need to write something like this:
(Again, I emphasized the code which potentially could be changed)
c3dl.addModel('cube.dae');
c3dl.addMainCallBack(mainDemo, 'demo');
function mainDemo(canvasName)
{
var scn = new c3dl.Scene();
scn.setCanvasTag(canvasName);
var renderer = new c3dl.OpenGLES20();
scn.setRenderer(renderer);
scn.init();
var cam = new c3dl.FreeCamera();
cam.setPosition([0,0,50]);
cam.setLookAtPoint([0,0,-1]);
var cube = new c3dl.Collada();
cube.init('cube.dae');
cube.setAngularVel([0.001,0.001,0.0]);
scn.addObjectToScene(cube);
scn.setCamera(cam);
scn.startScene();
}
Some changes I had in mind involved getting rid of the global c3dl.addModel() and c3dl.addMainCallback() calls and changing OpenGLES20 to just Renderer. The Renderer is an interesting problem. When WebGL started out as Canvas3D, we called the renderer OpenGLES11, then later it became OpenGLES20 and now it could probably be WebGL. Considering how much it has changed and will change, we’ll have to invest some time to make this stop. One simple solution is to abstract the renderer.For example, if we change OpenGLES20 class to Renderer, the user will no longer need to be concerned what underlying rendering method is used. If a visitor loads the user’s demo, but visitor’s browser doesn’t support WebGL (i.e. it’s I.E.), the demo still loads. This of course only works if we accommodate for this case. So if the browser is IE, we use DirectX. If the browser supports WebGL, we use that. The end result is the user’s page will create the appropriate renderer without them needing to worry about the user’s browser. So let’s look at what lines changed:
function mainDemo(canvasName)
{
var scn = new c3dl.Scene();
var renderer = new c3dl.Renderer();
scn.init(renderer);
var cam = new c3dl.FreeCamera();
cam.setPosition([0,0,50]);
cam.setLookAtPoint([0,0,-1]);
var cube = new c3dl.Collada();
cube.init('cube.dae');
cube.setAngularVel([0.001,0.001,0.001]);
scn.addObjectToScene(cube);
scn.setCamera(cam);
scn.startScene();
}
In terms of the lines trimmed, I’m not certain how much of it is viable. The reason some of the seemingly redundant code is required was because I couldn’t devise any alternative at the time. Looking at it from a different perspective, I should be able to come up with something. In the end we’ll have an interface which is more flexible, easier to understand and of course simple.
I’m continuing to update the demos with the copy of the library that works cross-browser (and will continue to do so). There was a slight delay in the motion capture demo due to the difference in how the browsers read xml files. We had been using:
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.async = false;
xmlDoc.load(xmlFile);
but Safari and Chrome don’t accept that. After a quick search (ignoring the pages that make it sound more complicated than it is and want to sell you code to take care of it) I found the answer to be quite simple.
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.async = false;
var xmlReq = new XMLHttpRequest();
xmlReq.open("GET", xmlFile, false);
xmlReq.send(null);
xmlDoc=xmlReq.responseXML;
It ends up as a few extra lines, but it works for all three. This was a problem with the code for that individual page, but it seems to be the kind of thing we can expect when trying to write complex code for multiple browsers.
I’ll be working on the particle systems demo next, as it also has a bit of code that is firefox only.
I finally have our library working properly on Firefox (Gecko/20100114 Minefield/3.7a1pre), Safari (Version 4.0.4 (5531.21.10, r53178)) and Chrome (Chromium 4.0.299.0 (36242))
I’ve updated the orbiter demo with the new code, and will shortly be updating some of the older demos. There are still a few minor issues to deal with, such as the moon not showing up properly sometimes, but we’re not getting exceptions anymore.
Another of these issues (Chrome only) has to do with reading floating point values from collada files. When we try to use the values, it throws an exception, but if I multiply the values by 1 before we use them, it works. I’ll have to spend a little more time trying to figure out if this is caused by something I’m doing wrong, or if it might be a bug.
