Archive

Monthly Archives: October 2011

Well… I got it working.
I was messing around just trying to make it save anything that wasn’t a 0’d array.
So I stuck alert(“stuff”); everywhere, in a mad stab at a timing based issue.

Who would have guessed…:
An Alert
what
Oh wow… It Works.
hey it worked...

 
If I call alert(); AFTER rendering to a canvas, and BEFORE saving the pixels it works fine.
setTimeout() works too:

function makePNG() {
   var image = pCtx.createImageData(p.width, p.height);
   arr = new Uint8Array(r.width * r.height * 4);
   rCtx.readPixels(0, 0, r.width, r.height, rCtx.RGBA, rCtx.UNSIGNED_BYTE, arr);
      for (var y = 0; y < p.height; y++){
        for (var x = 0; x < p.width; x++){
          var index = (y * p.width + x) * 4;
          var index2 = ((p.height-1-y) * p.width + x) * 4;
          for(var z = 0; z < 4; z++){
            image.data[index2 + z] = arr[index + z];
          }
        }
      }
   pCtx.putImageData(image, 0, 0);   
}
setTimeout("makePNG()", 500);

 
All three methods to save a 3Dcanvas to 2D work if I do this!
The other 2 being:

   // 1. get data url and write to canvas B
   //var data = r.toDataURL("image/png");
   //var img = new Image();
   //img.src = data;
   //pCtx.drawImage(img, 0, 0);
   // in case you want to try pasting the url in a new window
   //alert(data);

   // 2. draw 3Dcanvas to 2Dcanvas,
   //pCtx.drawImage(r, 0, 0);

 
 
Evidentially this is a time issue.
Speaking with ccliffe on IRC shed slightly more light on this.
He thinks its the RequestAnimationFrame call running *before* drawing the current frame.
(I have no idea what this means either, its o.k. :P)
Apparently it was done this way to workaround a timing bug in Firefox.

 
 
Applying my newfound knowledge to the sundae test suite:

   if (test.secondCanvas.src) 
      sourceLoader(test.secondCanvas, b, function () {
      alert("hax");
      whenDone('second');
      });
   }

Same Deal
Same Deal
Cool
Cool
Really Cool
Really Cool

 
 
It works, but this posed a new problem.
Sundae tries to run every test as fast as possible – all at once (multi-threaded too).
CubicVR can only render to ONE canvas at a time.
It just stays “running…” forever on the second test.
Was good while it lasted...

 
 
What has to happen next:

--> Sundae may not be the best framework for this, or needs to be heavily modified.
- The processing.js ref tester looked fantastic for this, I wonder if I can just use that?
 
--> Using setTimeout() is an extremely hacky way of making this work, It may not even work the same on every server/computer.
- Ideally this is an issue that can be fixed within CubicVR?
- Is this a bug, or just me incorrectly setting all this up?
 
--> What exactly does the "Test Creator" need to do, other then run code and give you a PNG back?
- How can I run the code that you paste in a text-box WITHOUT eval();

 
 
Is this enough for 0.2? I don’t even know.
What I do know is I’m going to keep working on this till Friday 😛

Spent the day rigging up the test builder.
You paste the code here:
Paste The Code Here
Click Run – It Renders it and gives you back a PNG:
Where’s the PNG…
It Renders

 
 
So far:

function runBuilder () {
   var canvasFrame = document.getElementById('render-frame'),
       pngFrame = document.getElementById('png-frame'),
       code = document.getElementById('code');

   // get rendering canvas and context
   var r = window.document.createElement('canvas');
   var rCtx = r.getContext("experimental-webgl", {preserveDrawingBuffer: true});
   r.id = "render";
   r.width = 300;
   r.height = 300;
   canvasFrame.appendChild(r);

   // get the png canvas and context
   var p = window.document.createElement('canvas');
   var pCtx = p.getContext("2d");
   p.id = "pngImage";
   p.width = 300;
   p.height = 300;
   pngFrame.appendChild(p);

   // run code.
   eval(code.value);
   test(r, function(){});
}

eval(code.value);
-> Will basically declare the input function (which you name test for now.)
-> I know eval() is bad practice. This is just duct-tape at the moment.
test(r, function(){});
-> Calls it on render canvas.

 
 
My problem now is no matter what I do it will not save the render as a PNG.
– Directly draw canvas to the 2d canvas:

pCtx.drawImage(r, 0, 0);

– Get image URI and draw that to canvas. (the image URI is one of a white 0’d out png)

var data = r.toDataURL("image/png");
var img = new Image();
img.src = data;
pCtx.drawImage(img, 0, 0);

– Get a readPixel Array and draw that to the 2d canvas (also 0’d out?) (copied from XB-POINTSTREAM)

var image = pCtx.createImageData(p.width, p.height);
arr = new Uint8Array(r.width * r.height * 4);
rCtx.readPixels(0, 0, r.width, r.height, rCtx.RGBA, rCtx.UNSIGNED_BYTE, arr);
for (var y = 0; y < p.height; y++){
   for (var x = 0; x < p.width; x++){

      var index = (y * p.width + x) * 4;
      var index2 = ((p.height-1-y) * p.width + x) * 4;

      for(var z = 0; z < 4; z++){
         image.data[index2 + z] = arr[index + z];
      }
   }
}
pCtx.putImageData(image, 0, 0);

 
 
I found out about this: {preserveDrawingBuffer: true}
From This Blog

Tried putting it into my context:

// get rendering canvas and context
var r = window.document.createElement('canvas');
var rCtx = r.getContext("experimental-webgl", {preserveDrawingBuffer: true});

Tried putting it into the CubicVR init context:

if (gl_in.getContext !== undef && gl_in.width !== undef && gl_in.height !== undef)
{
   try {
      if (!gl) gl = gl_in.getContext("experimental-webgl", {preserveDrawingBuffer: true});

Nothing…

 
 
More tomorrow.

Next Step for the ref-test system is to create an interface that allows a User to paste in some code and get back a PNG of the rendering.
Starting on this today I had 0 idea of how to go about this.

Step 1: I grabbed the processing.js ref-test-builder as a template -> Here
 

Step 2: Trying to figure out how to get the code in the text-box to actually execute, the way its done on processing.js is exceedingly complex (at least for this phase of the ref-test creator).
It seems like I can use eval(code.value) to execute the code, but I have to think up a way to pass parameters through.

Around here I ran into a huge issue, even the most basic CubicVR.js samples were not running. (they did last week)

Error:[18:52:12.515] uncaught exception: [Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "file:///home/tuna/apache/CubicVR.js//source/CubicVR.Utility.js Line: 69"]

After a good waste of 2 hours, I found out that I had clicked the link to the file to load it, rather than navigating to it using my localhost domain.
URL with error:

file:///home/tuna/apache/CubicVR.js/samples/basic/cube.html

URL without Error:

http://localhost/CubicVR.js/samples/basic/cube.html

 

Step 3: Just to make sure everything is working, I made a button that renders a cube into a canvas on my test runner page.
Run Button:
<input onclick="runBuilder(document.getElementById('renderCv'))" type="button" value="Run"></input>
RenderCv is a 300×300 canvas.

runBuilder:

function runBuilder (aCanvas) {
	function renderCube(canvas, callback) {
	    var gl = CubicVR.init(canvas.id);

	    if (!gl) {
		alert("Sorry, no WebGL support.");
		return;
	    };

	    // Create a camera, position at 1,1,1 and target at 0,0,0
	    var camera = new CubicVR.Camera(canvas.width,canvas.height,60);
	    camera.position = [1,1,1];
	    camera.lookat([0,0,0]);

	    // Create a material for the mesh
	    var boxMaterial = new CubicVR.Material({
		textures: {
		    color: new CubicVR.Texture("../../samples/images/6583-diffuse.jpg")
		}
	    });

	    // Add a box to mesh, size 1.0, apply material and UV parameters
	    var boxMesh = CubicVR.primitives.box({
		size: 1.0,
		material: boxMaterial,
		uvmapper: {
		    projectionMode: CubicVR.enums.uv.projection.CUBIC,
		    scale: [1, 1, 1]
		}
	    });

	    // triangulate and buffer object to GPU, remove unused data
	    boxMesh.triangulateQuads().compile().clean();

	    // Add our camera to the window resize list
	    CubicVR.addResizeable(camera);

	    CubicVR.MainLoop(function(timer, gl) {
		CubicVR.renderObject(boxMesh, camera, CubicVR.IdentityMatrix);
	    });

	    callback();
	}
renderCube(aCanvas, function(){});
}

 

Result: (I Wonder why it’s warped??? – will update CubicVR to the newest tomorrow.)
Wow, It's Warped...
 

Tomorrow:
Make it run the code pasted in the text-box, and render it to the canvas.
The Canvas should be a PNG from a data URI.
This Link
Makes it seem easy, especially as HTML5 spec says it comes with pre-stripped gamma and color correction data.