Ancient V.S. Contemporary Comedies

Something I noticed while reading Lysistrata is that it was actually funny, and I enjoyed it quite a bit. Maybe it’s my taste, but I find contemporary comedies (movies) are just terrible. All the comedies my friends like, I hardly find humorous. Which makes it interesting how a play written a few thousand years ago can stay timeless and still make someone laugh. Maybe there are some good contemporary comedic plays around. I’ll have to look into this.

Advertisements

3D Processing.js Development Deadlock

A few days ago I blogged about the problem of adding 3D to the Processing.js library. After I wrote the blog, I knew I needed to dig a bit further. A blog was okay, but I needed more. So I began the terribly confusing task of trying to categorize functions into releases and delegate the work so each developer doesn’t rely on other concurrently developing code. After I had something workable on paper, I posted it on our wiki page so it can be reviewed by the rest of the Processing.js team.

Deadlock

The main issue is there’s a bit of a deadlock for release 0.5. Anna is responsible for the box() function which renders a box in the scene. That function depends on Mickael’s camera() and perspective() functions, which are difficult to test without rendering something! I think to begin with, we’ll all have to work together (as in the same room) to figure all this out. Hopefully this week’s Processing.js team meeting will clear up some things.

Preliminary Plan For 3D in Processing.js

I was talking to Dave Humphrey on IRC about the state of the tickets which involve adding 3D functionality to the Processing.js library. And well, things are a bit hectic right now. We have a slew of tickets in lighthouse which need review, 3D dependencies haven’t been identified. We have code for drawing spheres and boxes, but no camera or perspective code checked in. All this needs some serious attention. What we need to do is identify what the dependencies are and focus our energy on getting those tickets checked in. Once that’s done, we can begin working on getting our other tickets ready for review.

Our next release is happening on the 5th. By that time we need to get a whole bunch of things ready for super review. The question is which parts? I have identified the blocking code here.

PMatrix3D

Let’s start with this object. This isn’t used by Processing.js scripts directly. It’s an internal structure for us developers working on the Pjs library. Once we have parts of it written we can all benefit from the tested code it provides. The problem is it’s huge. It has functions to scale, rotate, translate, skew, invert, etc. Luckily for us, since it isn’t exposed to users writing sketches, we can omit the functions of the class which aren’t mandatory and we can focus on the core elements, which are only a handful of functions. I believe we should concentrate on those, get the basics in then worry about the rest. I’ve tried to limit the code to the absolute minimum since the more function we add, the more tests are required. The more tests we need, the further back the release gets pushed. I want a substantial amount to get pushed, but no more than necessary. So these are the functions which need attention:

set() – Sets the matrix
mult() – Multiplies a vector by a matrix
apply() – Multiplies the matrix with another matrix

Yes, this is a very short list and I’m leaving out a whole bunch of functions. I’m even leaving out trivial code like transpose and reset (which sets the matrix to an identity matrix). These will need to get done manually until we have a test. Without a test, I don’t want to put it up for super review. We can still do translations, rotations and whatever by specifying our own matrices and calling apply(), so it still provides enough functionality to do some work.

On one hand, I don’t want to stunt the development of adding 3D to Processing.js, but I also don’t want us to push buggy code. That could leave someone scratching their head for hours because they think our code works when in fact it has a bug. I’m drawing the line at these functions. If someone notices we need another one, we’ll need a test for it. The code for these have already been written, now we have to delegate the work of writing the tests.
TODO:

  • Write tests for set(), mult() and apply()

camera()

camera() ticket

The camera() function places a virtual camera in the scene. It describes where the camera is, where it’s pointing and it’s ‘up’ direction. By default, this is called when a user creates a 3D scene, this makes the implementation an absolute must and of high dependency. Even if we don’t have any objects rendered, we need this guy landed.

Luckily Mickael Medel has already written the JavaScript implementation of camera(), it just requires fixing, debugging and a test. While I was reviewing the code, I saw it depends on PVector, but that’s fine since PVector has already been checked in. Nice.
TODO:

  • Fix bugs
  • Write a test for camera()

perspective()

perspective() ticket

Perspective creates a viewing volume. When objects are placed ‘inside’ this volume, they appear as they do in real life. That is, when they are farther from the camera, they appear smaller. The code is written, we just need to fix, debug and write a test. Like camera(), this function is a must since it is called by default (I even checked the Processing code to make absolute sure). Perspective in turn calls frustum().
TODO:

  • Fix bugs
  • Write a test for perspective()

frustum()

frustum() ticket

This allows you to create the viewing volume directly with more control over the final ‘shape’ of the volume compared to perspective(). Not only is this called by perspective, but users can call it directly. So this is also of high priority. Fortunately for us, the code is quite simple and standard. Writing a test for this should be fairly straightforward.

TODO:

  • Write a test for frustum()

Plan Alterations

In a few days we’ll be having our weekly Processing.js meeting. At that time we can add, remove, and alter the details of this plan. Once we have these elements in the code, the user will be able to call size() (which has already landed), call camera() and set the viewing volume with either perspective() or frustum(). The user can also change the background color (also landed) and ….that’s about it :s If we get ahead of schedule, I’ll plow on and get box() or rect() ready for review. It seems like we are taking a step backwards, but I believe this is a step in the right direction.

My Processing.js Release 0.4

I’m working on parts of the Processing.js library for my open source class. This marks my 0.4 release.

For this release, students in the class weren’t actually supposed to write any code. This is because we have to sort through a large number of tickets in lighthouse, which need review. The plan was that the students would do some peer or first level review. If it passed that review, we could submit the bugs for super review so the code lands in the Processing.js branch. I browsed the tickets which needed review and assigned a few to myself. I have never officially reviewed another developer’s code, so I was interested in how it would work.

I started with a quick search on code review. Some of the more valuable links I found were:
Code Review Checklist
Mozilla – How to Submit a Patch

Before starting my reviews, I compiled a short checklist of things I’ll try to enforce. Not all of them apply, but I was just getting an idea of what things to look out for in the future.

  • Does the code work?
  • Does the code have tests?
  • Does it break regression tests?
  • Is the code properly documented?
  • Does the code introduce security concerns?
  • Are function and variable names congruent with the codebase?
  • Is the indent/brace/spacing style adhered to?
  • Does the code have a performance impact?
  • Can the code be simplified?
  • Can the code be more efficient?

I ended up assigning many more tickets to myself than I was able to review. I didn’t finish my reviews partly because I got stuck trying to fix the bugs present in the code I was reviewing. I know when submitting a patch to a large open source project there’s no way someone reviewing your code will start to debug it for you. But since we’re a fairly small team, I figured I could help out. Here are the tickets I did manage to review.

camera()

Lighthouse Ticket: camera()

Testing this one took a while, but I eventually managed to make it run. One of the problems is there was this line:

if( arguments.length = 0 )

It actually took me a while to catch it and I think many developers from time to time still make this mistake. I recall reading a textbook (probably Code Complete) which mentioned that if you find yourself making this mistake often, change your style to this:

if( 0 == arguments.length )

Anytime you try to use only one equal sign, you’ll get an error telling you zero isn’t an lvalue. That is, it can’t be on the left side of an assignment. And since we’re using JavaScript, we might as well add another equals sign.

if( 0 === arguments.length )

You can see the rest of my comments on camera() in the camera lighthouse ticket.

join()

Lighthouse ticket: join()
My additional tests: join() tests

Alex wrote a test for his implementation of join(). I wanted write a few more tests before I submitted the ticket for super review. I started writing them, but soon found that my tests were breaking the library. After some research I found that nf() was not returning the correct values. So I had to comment out those from my tests which used nf(). Once we have nf() working, I can update my tests to test for joining int and float arrays. Other than that, the code seems to pass my tests. I marked it for super review and moved on.

P3DMatrixStack object

Lighthouse Ticket: P3DMatrixStack

I got stuck on this one. The logic to multiply the matrices looked deceptively correct and simple. However the matrices that I was testing weren’t being properly multiplied. After finally just throwing in some debug print statements, I saw what was actually happening. The logic in fact was not correct. Whenever you see a matrix multiplication in nested for loops, keep in mind matrix multiplication is O(n3). If it doesn’t look like O(n3), it’s probably wrong (however there are some faster implementations). That is, there should be a bunch of logic in the last code block or there should be a third for loop.

frustum()

Lighthouse ticket: frustum()

This code looks fine, it’s the same logic you can find all over the Web, but we still need a test. So I marked the ticket as “needs work”.

Remnants & More Tests Required

A lot of the other lighthouse tickets I assigned myself to review don’t have tests. Since some of the students who worked on them are no longer in the class, I’ll have to undertake writing tests for those bugs. So here are the bugs I still need to review:

Simplifying the Interface

Something I need to do is simplify the C3DL 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 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">
  </head>

  <body>
    <canvas datasrc="basic_demo.js" 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.

WebGL Processing.js Reftests

I’m working on adding 3D functionality to the Processing.js library. Since any Processing.js scripts should render exactly the same as identical Processing scripts, it would make sense to use reference tests. This will ensure all my WebGL code is rendering objects where they should be and with correct lighting. I’m using Minefield to run the tests since it has reftest functionality along with support for WebGL to render the 3D objects.

HTML Vs. PNG

At first I had to play around with Minefield’s configuration to get reftests working. I was able to correctly compare two identical basic HTML files. Once I got over that hurdle, I went to the next one. I knew I would need to compare screenshots from the PDE environment against whatever is rendered in the web page using PJS. To make things simple, I started to experiment with very basic (no Processing) HTML vs. PNG reftest. I had a string rendered in an HTML page and a rasterized string in a PNG file. I ran the tests, but Minefield kept telling me some arbitrary number of pixels differed between the web page and the image.

Script Vs. Script

Not finding much help on the Web, I thought it might be a better decision to simply create a Processing script in the PDE, export it to HTML as my first compare file. Then use that same Processing script to create a PJS test in another web page as the second compare file. Finally I could ask Minefield to render and compare the two. It seemed like a good idea at the time. I was getting awfully tired of taking screenshots.

My Processing test case was as simple as it could get:

size(100,100);
background(0);

I threw this in the PDE, exported it, cut out all the unnecessary CSS and got a plain black canvas rendered in a Web page. Before creating a real PJS script, I decided to first test with a page which just had an tag with the same black square. When I went back to my shell and ran the tests, they failed. Now, when reftests are executed, the browser opens a window, renders the page and closes it. This happens pretty quickly, and I saw a bunch of blue text, which was very odd. It should have been drawing the black square. It turns out I opened the exported Processing file in my default browser earlier (that’s why it worked) and now I was running the reftests in Minefield and I was getting this:

Get the latest Java Plug-in here.

That’s when I remembered Minefield doesn’t have a compatible JRE, at least for OSX. This means there’s no way I can load the applet in Minefield to properly test. Of course I can go back to an older version of Firefox which does have Java, but that won’t have support for WebGL. As much as this sucks, the situation is a bit funny.

? Vs. ?

Okay, what can I do now? I could go back and figure out how to make HTML vs. PNG comparisons work. I’m not keen on doing this because grabbing screenshots is extremely tedious. The solution is also very inflexible. If I change my PJS test script, I need to grab yet another screenshot as opposed to a simple export in PDE and trim away unneeded CSS. Another solution could involve running the reftests on another platform such as Windows or Linux. Perhaps they have Java runtimes available. Hmm… Are reftests powerful enough to have a page open with one version of Firefox and another page with Minefield? I doubt it. Maybe there is some other technique of getting this to work. I’ll bring it up in this week’s Processing.js conference call. Hopefully I’ll get some suggestions.

Offering Alms

I always found it a bit awkward offering money or food to the needy if they didn’t ask. Will they be insulted? Will they reject my alms? That would be embarrassing. I was feeling terrible for tragedy that struck Haiti, but didn’t see any way I could help. So I decided to do something to help someone closer in proximity. I saw a homeless man and I forced myself to risk the embarrassment of rejection and offered food I had on me. I asked him if he’d like it, and he accepted. I felt like I helped someone out. “Be the change you want to see in the world“. I want to see more people helping one another out, so I tried and did the least I could. Then I was told the homeless guy was a retired law professor. Nice.

My girlfriend sorted our laundry a few days ago since we’ll be washing everything on the weekend. In the process, she gathered some old clothes and set them aside for donations to Value Village. When we arrived home, I realized there is probably a program in place to send donations to Haiti, so we agreed to send the bags of clothing there instead.