summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpetersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 21:00:00 +0000
committerpetersont@google.com <petersont@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-12 21:00:00 +0000
commite512583b79e366db399a6566964412bb6e5af823 (patch)
treee15e3c05e273a0366caf2fcbc5689ae377b3e877
parenta37a999f87eed77b08e7e1b6bdb86d406f31ea9b (diff)
downloadchromium_src-e512583b79e366db399a6566964412bb6e5af823.zip
chromium_src-e512583b79e366db399a6566964412bb6e5af823.tar.gz
chromium_src-e512583b79e366db399a6566964412bb6e5af823.tar.bz2
Added textures, texture samplers and render targets to o3d-webgl. Also fixed bugs, added calls to parent class constructor to classes that didn't have them before, added a few demos to exhibit/test textures and render surfaces.
Review URL: http://codereview.chromium.org/856004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@41482 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--o3d/samples/o3d-webgl-samples/hellocube-colors.html343
-rw-r--r--o3d/samples/o3d-webgl-samples/hellocube-textures.html433
-rw-r--r--o3d/samples/o3d-webgl-samples/shadow-map.html636
-rw-r--r--o3d/samples/o3d-webgl/base.js23
-rw-r--r--o3d/samples/o3d-webgl/bitmap.js40
-rw-r--r--o3d/samples/o3d-webgl/client.js44
-rw-r--r--o3d/samples/o3d-webgl/draw_context.js1
-rw-r--r--o3d/samples/o3d-webgl/draw_list.js2
-rw-r--r--o3d/samples/o3d-webgl/draw_pass.js1
-rw-r--r--o3d/samples/o3d-webgl/effect.js54
-rw-r--r--o3d/samples/o3d-webgl/element.js6
-rw-r--r--o3d/samples/o3d-webgl/event.js12
-rw-r--r--o3d/samples/o3d-webgl/field.js18
-rw-r--r--o3d/samples/o3d-webgl/file_request.js49
-rw-r--r--o3d/samples/o3d-webgl/named_object.js23
-rw-r--r--o3d/samples/o3d-webgl/named_object_base.js4
-rw-r--r--o3d/samples/o3d-webgl/object_base.js12
-rw-r--r--o3d/samples/o3d-webgl/pack.js103
-rw-r--r--o3d/samples/o3d-webgl/param.js92
-rw-r--r--o3d/samples/o3d-webgl/param_object.js7
-rw-r--r--o3d/samples/o3d-webgl/raw_data.js11
-rw-r--r--o3d/samples/o3d-webgl/ray_intersection_info.js1
-rw-r--r--o3d/samples/o3d-webgl/render_node.js23
-rw-r--r--o3d/samples/o3d-webgl/render_surface.js61
-rw-r--r--o3d/samples/o3d-webgl/render_surface_set.js99
-rw-r--r--o3d/samples/o3d-webgl/sampler.js170
-rw-r--r--o3d/samples/o3d-webgl/shape.js6
-rw-r--r--o3d/samples/o3d-webgl/state_set.js2
-rw-r--r--o3d/samples/o3d-webgl/stream.js1
-rw-r--r--o3d/samples/o3d-webgl/stream_bank.js7
-rw-r--r--o3d/samples/o3d-webgl/texture.js68
-rw-r--r--o3d/samples/o3d-webgl/transform.js14
-rw-r--r--o3d/samples/o3d-webgl/tree_traversal.js5
-rw-r--r--o3d/samples/o3d-webgl/viewport.js13
-rw-r--r--o3d/samples/o3djs/webgl.js61
-rw-r--r--o3d/samples/primitives.html2
36 files changed, 2246 insertions, 201 deletions
diff --git a/o3d/samples/o3d-webgl-samples/hellocube-colors.html b/o3d/samples/o3d-webgl-samples/hellocube-colors.html
new file mode 100644
index 0000000..2af5699
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/hellocube-colors.html
@@ -0,0 +1,343 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+This sample creates an O3D area with a spinning cube. The user
+can change the color of the cube by clicking on one of the buttons that appear
+at the bottom of the page. This sample demonstrates how to use O3D Params
+to change the values of uniform parameters used by shaders.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Hello Square Colors: Getting started with O3D, take 2.
+</title>
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+
+// Events
+// Run the init() function once the page has finished loading.
+// Run the uninit() function when the page has is unloaded.
+window.onload = init;
+window.onunload = uninit;
+
+// global variables
+var g_o3d;
+var g_math;
+var g_pack;
+var g_client;
+var g_clock = 0;
+var g_timeMult = 1;
+var g_finished = false; // for selenium testing
+
+var g_cubeTransform;
+var g_cubeColorParam;
+
+/**
+ * Changes the color of the cube.
+ * @param red red component of the color
+ * @param green green component of the color
+ * @param blue blue component of the color
+ */
+function changeColor(red, green, blue) {
+ // Set the rgb color values and alpha = 1
+ g_cubeColorParam.value = [red, green, blue, 1];
+}
+
+/**
+ * Creates an O3D shape representing a cube. The shape consists of
+ * a single primitive with eight vertices and 12 triangles (two for each face
+ * of the cube).
+ * @param {o3d.Material} material the material used by the primitive.
+ * @return {o3d.Shape} The Shape object created.
+ */
+function createCube(material) {
+ // Create a Shape object for the mesh.
+ var cubeShape = g_pack.createObject('Shape');
+
+ // Create the Primitive that will contain the geometry data for
+ // the cube.
+ var cubePrimitive = g_pack.createObject('Primitive');
+
+ // Create a StreamBank to hold the streams of vertex data.
+ var streamBank = g_pack.createObject('StreamBank');
+
+ // Assign the material that was passed in to the primitive.
+ cubePrimitive.material = material;
+
+ // Assign the Primitive to the Shape.
+ cubePrimitive.owner = cubeShape;
+
+ // Assign the StreamBank to the Primitive.
+ cubePrimitive.streamBank = streamBank;
+
+ // The cube is made of 12 triangles. There's eight vertices in total which
+ // are shared between the face triangles.
+ cubePrimitive.primitiveType = g_o3d.Primitive.TRIANGLELIST;
+ cubePrimitive.numberPrimitives = 12; // 12 triangles
+ cubePrimitive.numberVertices = 8; // 8 vertices in total
+
+ // Generate the draw element for the cube primitive.
+ cubePrimitive.createDrawElement(g_pack, null);
+
+ // Create a javascript array that stores the X, Y and Z coordinates of each
+ // of the 8 corners of the cube.
+ var positionArray = [
+ -0.5, -0.5, 0.5, // vertex 0
+ 0.5, -0.5, 0.5, // vertex 1
+ -0.5, 0.5, 0.5, // vertex 2
+ 0.5, 0.5, 0.5, // vertex 3
+ -0.5, 0.5, -0.5, // vertex 4
+ 0.5, 0.5, -0.5, // vertex 5
+ -0.5, -0.5, -0.5, // vertex 6
+ 0.5, -0.5, -0.5 // vertex 7
+ ];
+
+ // The following array defines how vertices are to be put together to form
+ // the triangles that make up the cube's faces. In the index array, every
+ // three elements define a triangle. So for example vertices 0, 1 and 2
+ // make up the first triangle, vertices 2, 1 and 3 the second one, etc.
+ var indicesArray = [
+ 0, 1, 2, // face 1
+ 2, 1, 3,
+ 2, 3, 4, // face 2
+ 4, 3, 5,
+ 4, 5, 6, // face 3
+ 6, 5, 7,
+ 6, 7, 0, // face 4
+ 0, 7, 1,
+ 1, 7, 3, // face 5
+ 3, 7, 5,
+ 6, 0, 4, // face 6
+ 4, 0, 2
+ ];
+
+ // Create buffers containing the vertex data.
+ var positionsBuffer = g_pack.createObject('VertexBuffer');
+ var positionsField = positionsBuffer.createField('FloatField', 3);
+ positionsBuffer.set(positionArray);
+
+ var indexBuffer = g_pack.createObject('IndexBuffer');
+ indexBuffer.set(indicesArray);
+
+ // Associate the positions Buffer with the StreamBank.
+ streamBank.setVertexStream(
+ g_o3d.Stream.POSITION, // semantic: This stream stores vertex positions
+ 0, // semantic index: First (and only) position stream
+ positionsField, // field: the field this stream uses.
+ 0); // start_index: How many elements to skip in the
+ // field.
+
+ // Associate the triangle indices Buffer with the primitive.
+ cubePrimitive.indexBuffer = indexBuffer;
+
+ return cubeShape;
+}
+
+/**
+ * This method gets called every time O3D renders a frame. Here's where
+ * we update the cube's transform to make it spin.
+ * @param {o3d.RenderEvent} renderEvent The render event object that gives
+ * us the elapsed time since the last time a frame was rendered.
+ */
+function renderCallback(renderEvent) {
+ g_clock += renderEvent.elapsedTime * g_timeMult;
+ // Rotate the cube around the Y axis.
+ g_cubeTransform.identity();
+ g_cubeTransform.rotateY(2.0 * g_clock);
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, creates the cube and sets up the transform and
+ * render graphs.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initializes global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_client = o3dElement.client;
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+
+ // Create a pack to manage the objects created.
+ g_pack = g_client.createPack();
+
+ // Create the render graph for a view.
+ var viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot);
+
+ // Set up a perspective projection.
+ viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree fov.
+ g_client.width / g_client.height,
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation to look towards the world origin where the
+ // cube is located.
+ viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [0, 1, 5], // eye
+ [0, 0, 0], // target
+ [0, 1, 0]); // up
+
+ // Create an Effect object and initialize it using the shaders from the
+ // text area.
+ var cubeEffect = g_pack.createObject('Effect');
+ var vertexShaderString = document.getElementById('vshader').value;
+ var pixelShaderString = document.getElementById('pshader').value;
+ cubeEffect.loadVertexShaderFromString(vertexShaderString);
+ cubeEffect.loadPixelShaderFromString(pixelShaderString);
+
+ // Create a Material for the mesh.
+ var cubeMaterial = g_pack.createObject('Material');
+
+ // Set the material's drawList.
+ cubeMaterial.drawList = viewInfo.performanceDrawList;
+
+ // Apply our effect to this material. The effect tells the 3D hardware
+ // which shaders to use.
+ cubeMaterial.effect = cubeEffect;
+
+ // Create an O3D Param on the material for every uniform used by the
+ // shader.
+ cubeEffect.createUniformParameters(cubeMaterial);
+
+ // Get the color parameter from the material and set its value to red.
+ g_cubeColorParam = cubeMaterial.getParam('color');
+ g_cubeColorParam.value = [1, 0, 0, 1];
+
+ // Create the Shape for the cube mesh and assign its material.
+ var cubeShape = createCube(cubeMaterial);
+
+ // Create a new transform and parent the Shape under it.
+ g_cubeTransform = g_pack.createObject('Transform');
+ g_cubeTransform.addShape(cubeShape);
+
+ // Parent the cube's transform to the client root.
+ g_cubeTransform.parent = g_client.root;
+
+ // Set our render callback for animation.
+ // This sets a function to be executed every time a frame is rendered.
+ g_client.setRenderCallback(renderCallback);
+
+ g_finished = true; // for selenium testing.
+}
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function uninit() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+
+</script>
+</head>
+<body>
+<h1>Hello Square: Colors</h1>
+This example shows how to use parameters to the color output of a shader.
+<br/>
+
+
+<!-- Start of O3D plugin -->
+<div id="o3d" width="600px" height="600px"></div>
+<!-- End of O3D plugin -->
+
+<form name="default_form" action="#" method="get">
+ <p>
+ Change color:
+ <input type="button" value="Red" onclick="changeColor(1,0,0);" />
+ <input type="button" value="Green" onclick="changeColor(0,1,0);" />
+ <input type="button" value="Blue" onclick="changeColor(0,0,1);" />
+ <input type="button" value="Yellow" onclick="changeColor(1,1,0);" />
+ <input type="button" value="Cyan" onclick="changeColor(0,1,1);" />
+ <input type="button" value="Purple" onclick="changeColor(1,0,1);" />
+ <input type="button" value="White" onclick="changeColor(1,1,1);" />
+ </p>
+</form>
+
+<!-- Don't render the textarea -->
+<div style="display:none">
+<!-- Start of effect -->
+<textarea id="vshader">
+ // World View Projection matrix that will transform the input vertices
+ // to screen space.
+ uniform mat4 worldViewProjection;
+
+ // input parameters for our vertex shader
+ attribute vec4 position;
+
+ /**
+ * The vertex shader simply transforms the input vertices to screen space.
+ */
+ void main() {
+ // Multiply the vertex positions by the worldViewProjection matrix to
+ // transform them to screen space.
+ gl_Position = worldViewProjection * position;
+ }
+
+</textarea>
+<textarea id="pshader">
+ // Color to draw with.
+ uniform vec4 color;
+
+ /**
+ * This pixel shader just returns the color red.
+ */
+ void main() {
+ gl_FragColor = color;
+ }
+
+ // Here we tell our effect file *which* functions are
+ // our vertex and pixel shaders.
+</textarea>
+<!-- End of effect -->
+</div>
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/hellocube-textures.html b/o3d/samples/o3d-webgl-samples/hellocube-textures.html
new file mode 100644
index 0000000..0c20cf4
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/hellocube-textures.html
@@ -0,0 +1,433 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+This sample creates an O3D area with a textured cube in the middle. The
+user can specify the URL where the texture image will be picked from.
+This sample is a simple demonstration of texture usage in O3D.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Hello Square Textures: Getting started with O3D, take 3.
+</title>
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.io');
+
+// Events
+// Run the init() function once the page has finished loading.
+// Run the uninit() function when the page is unloaded.
+window.onload = init;
+window.onunload = uninit;
+
+// global variables
+var g_o3d;
+var g_math;
+var g_pack;
+var g_client;
+var g_cubeTransform;
+var g_sampler;
+var g_clock = 0;
+var g_timeMult = 1;
+var g_finished = false; // for selenium testing
+var g_textureLoadDenied = false; // also for selenium testing
+
+/**
+ * Creates an O3D shape representing a cube.
+ * @param {o3d.Material} material the material used by the primitive.
+ * @return {o3d.Shape} The Shape object created.
+ */
+function createCube(material) {
+ // Create a Shape object for the mesh.
+ var cubeShape = g_pack.createObject('Shape');
+
+ // Create the Primitive that will contain the geometry data for
+ // the cube.
+ var cubePrimitive = g_pack.createObject('Primitive');
+
+ // Create a StreamBank to hold the streams of vertex data.
+ var streamBank = g_pack.createObject('StreamBank');
+
+ // Assign the material that was passed in to the primitive.
+ cubePrimitive.material = material;
+
+ // Assign the Primitive to the Shape.
+ cubePrimitive.owner = cubeShape;
+
+ // Assign the StreamBank to the Primitive.
+ cubePrimitive.streamBank = streamBank;
+
+ // The cube is made of 12 triangles (6 faces x 2 triangles per face)
+ cubePrimitive.primitiveType = g_o3d.Primitive.TRIANGLELIST;
+ cubePrimitive.numberPrimitives = 12; // 12 triangles
+
+ // Vertices used by each triangle must specify both a position and texture
+ // coordinates. We cannot share vertices between adjacent cube faces since
+ // while their positions are the same, their texture coordinates are
+ // different. We therefore create 24 vertices, 4 for each of the cube's
+ // six faces.
+ cubePrimitive.numberVertices = 24;
+
+ // Generate the draw element for the cube primitive.
+ cubePrimitive.createDrawElement(g_pack, null);
+
+ // Create a javascript array that stores the X, Y and Z coordinates of each
+ // of the 24 vertices used by the cube.
+ var positionArray = [
+ -0.5, -0.5, 0.5,
+ 0.5, -0.5, 0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, 0.5, 0.5,
+ -0.5, 0.5, 0.5,
+ 0.5, 0.5, 0.5,
+ 0.5, 0.5, -0.5,
+ -0.5, 0.5, -0.5,
+ -0.5, 0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ -0.5, -0.5, -0.5,
+ -0.5, -0.5, -0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, -0.5, 0.5,
+ -0.5, -0.5, 0.5,
+ 0.5, -0.5, 0.5,
+ 0.5, -0.5, -0.5,
+ 0.5, 0.5, -0.5,
+ 0.5, 0.5, 0.5,
+ -0.5, -0.5, -0.5,
+ -0.5, -0.5, 0.5,
+ -0.5, 0.5, 0.5,
+ -0.5, 0.5, -0.5
+ ];
+
+ // The following array stores the texture coordinates (u, v) for each vertex.
+ // These coordinates are used by the shader when displaying the texture image
+ // on the mesh triangles.
+ var texCoordsArray = [
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ 1, 1,
+ 0, 1,
+ 0, 0,
+ 1, 0,
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1,
+ 0, 0,
+ 1, 0,
+ 1, 1,
+ 0, 1
+ ];
+
+ // The following array defines how vertices are to be put together to form
+ // the triangles that make up the cube's faces. In the index array, every
+ // three elements define a triangle. So for example vertices 0, 1 and 2
+ // make up the first triangle, vertices 0, 2 and 3 the second one, etc.
+ var indicesArray = [
+ 0, 1, 2,
+ 0, 2, 3,
+ 4, 5, 6,
+ 4, 6, 7,
+ 8, 9, 10,
+ 8, 10, 11,
+ 12, 13, 14,
+ 12, 14, 15,
+ 16, 17, 18,
+ 16, 18, 19,
+ 20, 21, 22,
+ 20, 22, 23
+ ];
+
+ // Create buffers containing the vertex data.
+ var positionsBuffer = g_pack.createObject('VertexBuffer');
+ var positionsField = positionsBuffer.createField('FloatField', 3);
+ positionsBuffer.set(positionArray);
+
+ var texCoordsBuffer = g_pack.createObject('VertexBuffer');
+ var texCoordsField = texCoordsBuffer.createField('FloatField', 2);
+ texCoordsBuffer.set(texCoordsArray);
+
+ var indexBuffer = g_pack.createObject('IndexBuffer');
+ indexBuffer.set(indicesArray);
+
+ // Associate the positions buffer with the StreamBank.
+ streamBank.setVertexStream(
+ g_o3d.Stream.POSITION, // semantic: This stream stores vertex positions
+ 0, // semantic index: First (and only) position stream
+ positionsField, // field: the field this stream uses.
+ 0); // start_index: How many elements to skip in the
+ // field.
+
+ // Associate the texture coordinates buffer with the primitive.
+ streamBank.setVertexStream(
+ g_o3d.Stream.TEXCOORD, // semantic
+ 0, // semantic index
+ texCoordsField, // field
+ 0); // start_index
+
+ // Associate the triangle indices Buffer with the primitive.
+ cubePrimitive.indexBuffer = indexBuffer;
+
+ return cubeShape;
+}
+
+/**
+ * This method gets called every time O3D renders a frame. Here's where
+ * we update the cube's transform to make it spin.
+ * @param {o3d.RenderEvent} renderEvent The render event object that gives
+ * us the elapsed time since the last time a frame was rendered.
+ */
+function renderCallback(renderEvent) {
+ g_clock += renderEvent.elapsedTime * g_timeMult;
+ // Rotate the cube around the Y axis.
+ g_cubeTransform.identity();
+ g_cubeTransform.rotateY(2.0 * g_clock);
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.webgl.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D, creates the quad and sets up the transform and
+ * render graphs.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Set the texture URL.
+ path = '../assets/texture_b3.jpg';
+ var url = document.getElementById("url").value = path;
+
+ // Initialize global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_client = o3dElement.client;
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+
+ // Create a pack to manage the objects created.
+ g_pack = g_client.createPack();
+
+ // Create the render graph for a view.
+ var viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot);
+
+ // Set up a perspective projection.
+ viewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree fov.
+ g_client.width / g_client.height,
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation to look towards the world origin where the
+ // cube is located.
+ viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ [0, 1, 5], // eye
+ [0, 0, 0], // target
+ [0, 1, 0]); // up
+
+ // Create an Effect object and initialize it using the shaders from the
+ // text area.
+ var cubeEffect = g_pack.createObject('Effect');
+ var vertexShaderString = document.getElementById('vshader').value;
+ var pixelShaderString = document.getElementById('pshader').value;
+ cubeEffect.loadVertexShaderFromString(vertexShaderString);
+ cubeEffect.loadPixelShaderFromString(pixelShaderString);
+
+ // Create a Material for the mesh.
+ var cubeMaterial = g_pack.createObject('Material');
+
+ // Set the material's drawList.
+ cubeMaterial.drawList = viewInfo.performanceDrawList;
+
+ // Apply our effect to this material. The effect tells the 3D hardware
+ // which shaders to use.
+ cubeMaterial.effect = cubeEffect;
+
+ // Create an O3D Param on the material for every uniform used by the
+ // shader.
+ cubeEffect.createUniformParameters(cubeMaterial);
+
+ // Get the material's sampler parameter so that we can set the texture value
+ // to it.
+ var samplerParam = cubeMaterial.getParam('texSampler0');
+
+ // Create a Sampler object and set the min filtering to ANISOTROPIC. This
+ // will improve the quality of the rendered texture when viewed at an angle.
+ g_sampler = g_pack.createObject('Sampler');
+ g_sampler.minFilter = g_o3d.Sampler.ANISOTROPIC;
+ g_sampler.maxAnisotropy = 4;
+ samplerParam.value = g_sampler;
+
+ // Create the Shape for the cube mesh and assign its material.
+ var cubeShape = createCube(cubeMaterial);
+
+ // Create a new transform and parent the Shape under it.
+ g_cubeTransform = g_pack.createObject('Transform');
+ g_cubeTransform.addShape(cubeShape);
+
+ // Note that we don't parent the transform until the texture is
+ // succesfully loaded because we don't want the system
+ // to try the draw the shape without its required texture.
+
+ // Set our render callback for animation.
+ // This sets a function to be executed every time a frame is rendered.
+ g_client.setRenderCallback(renderCallback);
+
+ // Set the initial texture.
+ changeTexture();
+}
+
+/**
+ * Fetches the bitmap pointed to by the URL supplied by the user, creates
+ * an O3D Texture object with it updates the Sampler used by the material
+ * to point to the newly created texture.
+ */
+function changeTexture() {
+ var textureUrl = document.getElementById('url').value;
+ o3djs.io.loadTexture(g_pack, textureUrl, function(texture, exception) {
+ // Remove the currently used texture from the pack so that when it's not
+ // referenced anymore, it can get destroyed.
+ if (g_sampler.texture)
+ g_pack.removeObject(g_sampler.texture);
+
+ // Because the loading is asynchronous an exception is not thrown but is
+ // instead passed on failure.
+ if (exception) {
+ g_sampler.texture = null;
+
+ g_textureLoadDenied = true; // for selenium testing.
+ } else {
+ // Set the texture on the sampler object to the newly created texture
+ // object returned by the request.
+ g_sampler.texture = texture;
+
+ // We can now safely add the cube transform to the root of the
+ // scenegraph since it now has a valid texture. If the transform
+ // is already parented under the root, the call will have no effect.
+ g_cubeTransform.parent = g_client.root;
+
+ g_finished = true; // for selenium testing.
+ }
+ });
+}
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function uninit() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+
+</script>
+</head>
+<body>
+<h1>Hello Cube: Textures</h1>
+This example shows how texture map a cube using an image fetched from a URL.
+<br/>
+
+
+<!-- Start of O3D plugin -->
+<div id="o3d" width="600px" height="600px"></div>
+<!-- End of O3D plugin -->
+<br />
+Image URL: <input type="text" id="url" size="100">
+<input type="button" id="updateButton" onclick="changeTexture();" value="Update Texture"><BR>
+
+<!-- Don't render the textarea -->
+<div style="display:none">
+<!-- Start of effect -->
+<textarea id="vshader">
+ // World View Projection matrix that will transform the input vertices
+ // to screen space.
+ uniform mat4 worldViewProjection;
+
+ // input parameters for our vertex shader
+ attribute vec4 position;
+ attribute vec2 texCoord0;
+
+ varying vec2 uvs;
+
+ /**
+ * The vertex shader simply transforms the input vertices to screen space.
+ */
+ void main() {
+ // Multiply the vertex positions by the worldViewProjection matrix to
+ // transform them to screen space.
+ gl_Position = worldViewProjection * position;
+ uvs = texCoord0;
+ }
+
+</textarea>
+<textarea id="pshader">
+
+ // Color to draw with.
+ uniform sampler2D texSampler0;
+
+ varying vec2 uvs;
+
+ /**
+ * This pixel shader just returns the color red.
+ */
+ void main() {
+ gl_FragColor = texture2D(texSampler0, uvs);
+ }
+</textarea>
+<!-- End of effect -->
+</div>
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl-samples/shadow-map.html b/o3d/samples/o3d-webgl-samples/shadow-map.html
new file mode 100644
index 0000000..2bf81cc
--- /dev/null
+++ b/o3d/samples/o3d-webgl-samples/shadow-map.html
@@ -0,0 +1,636 @@
+<!--
+Copyright 2009, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<!--
+This sample uses a custom render graph to implement a basic shadow map
+algorithm.
+
+The technique works by rendering the scene in two passes. The first pass
+renders the geometry in the scene with a shader that colors each pixel a shade
+of gray representing how far the rendered point is from the light source. That
+image, the shadow map, is rendered to a texture, and then the second (visible)
+render pass samples it to determine which points in the scene are in shaodow.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=UTF-8">
+<title>
+Shadow Mapping
+</title>
+<script type="text/javascript" src="../o3d-webgl/base.js"></script>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.base.o3d = o3d;
+o3djs.require('o3djs.webgl');
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.effect');
+o3djs.require('o3djs.debug');
+o3djs.require('o3djs.material');
+
+// The initClient() function runs when the page has finished loading.
+window.onload = initClient;
+
+// global variables
+var g_o3dElement;
+var g_client;
+var g_o3d;
+var g_math;
+var g_pack;
+var g_colorViewInfo;
+var g_shadowViewInfo;
+var g_shadowTexture;
+var g_shadowMaterial;
+var g_colorEffect;
+var g_shadowSampler;
+var g_lightViewProjection;
+var g_lightFrustumTransform;
+var g_globalParams = { };
+var g_viewFromLight = false;
+
+var g_renderSurfaceSet;
+var g_colorPassRenderRoot;
+
+var g_lightWorldPos = [5, 10, 0];
+var g_lightColor = [1, 1, 1, 1];
+var g_eyePosition = [1, 6, 20];
+var g_targetPosition = [0, 2, 0];
+
+// constants.
+var SHADOW_MAP_WIDTH = 512;
+var SHADOW_MAP_HEIGHT = 512;
+
+var g_finished = false; // for selenium testing.
+
+
+/**
+ * Creates the client area.
+ */
+function initClient() {
+ o3djs.webgl.makeClients(main, 'FloatingPointTextures', true);
+}
+
+
+/**
+ * Initializes global variables, positions camera, draws shapes.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function main(clientElements) {
+ // Init global variables.
+ initGlobals(clientElements);
+
+ // Set up the rendergraph.
+ initRenderGraph();
+
+ // Load effects, bind material parameters.
+ initMaterials();
+
+ // Add the shapes to the transform graph.
+ createShapes();
+
+ // Set up the view and projection transformations for the camera.
+ updateCamera();
+
+ // Init global parameters. initGlobalParams() searches all materials in order
+ // to bind parameters, so it must be called after initMaterials()
+ initGlobalParams();
+
+ // Set the view and projection transformations for the light.
+ updateLightMatrix();
+
+ // Create the light that gets drawn.
+ createLightShape();
+
+ // Execute keyPressed() when we detect a keypress on the window or
+ // on the o3d object.
+ window.document.onkeypress = keyPressed;
+ g_o3dElement.onkeypress = keyPressed;
+
+ //toggleView();
+
+ g_finished = true; // for selenium testing.
+}
+
+
+/**
+ * Initializes global variables and libraries.
+ */
+function initGlobals(clientElements) {
+ g_o3dElement = clientElements[0];
+ g_client = g_o3dElement.client;
+ g_o3d = g_o3dElement.o3d;
+ g_math = o3djs.math;
+
+ // Create a pack to manage the objects created.
+ g_pack = g_client.createPack();
+}
+
+
+/**
+ * Sets up the render graph. Builds a basic view for the camera and the light
+ * point of view, arranges for the view from the light to be rendered to a
+ * texture for the shadow map. Unlike the basic render graph created by the
+ * the utility function o3djs.rendergraph.createBasicView, to render the shadow
+ * map and then render the scene, we need two subtrees of the render graph, one
+ * for shadow map render pass and one to draw the scene.
+ */
+function initRenderGraph() {
+ // The children of any one node in the render graph get traversed in order by
+ // priority. Here, we're forcing the shadow map to get rendered first by
+ // by giving its render root lower priority.
+ var shadowPassRenderRoot = g_pack.createObject('RenderNode');
+ shadowPassRenderRoot.priority = 0;
+
+ g_colorPassRenderRoot = g_pack.createObject('RenderNode');
+ g_colorPassRenderRoot.priority = 1;
+
+ g_colorPassRenderRoot.parent = g_client.renderGraphRoot;
+
+ // Create the texture that will store the depth information.
+ g_shadowTexture = g_pack.createTexture2D(SHADOW_MAP_WIDTH,
+ SHADOW_MAP_HEIGHT,
+ g_o3d.Texture.ABGR32F,
+ 1,
+ true);
+ var renderSurface = g_shadowTexture.getRenderSurface(0);
+
+ // Create the depth-stencil buffer required when rendering the teapot.
+ var depthSurface = g_pack.createDepthStencilSurface(SHADOW_MAP_WIDTH,
+ SHADOW_MAP_HEIGHT);
+
+ shadowPassRenderRoot.parent = g_client.renderGraphRoot;
+
+ g_renderSurfaceSet = g_pack.createObject('RenderSurfaceSet');
+ g_renderSurfaceSet.renderSurface = renderSurface;
+ g_renderSurfaceSet.renderDepthStencilSurface = depthSurface;
+
+ g_renderSurfaceSet.parent = shadowPassRenderRoot;
+
+ // Create a render sub-graph for the shadow map generation.
+ g_shadowViewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_renderSurfaceSet,
+ [1, 1, 1, 1]);
+
+ // Create a render sub-graph for the regular pass.
+ g_colorViewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_colorPassRenderRoot,
+ [0, 0, 0, 1]);
+}
+
+
+/**
+ * Switches between the camera and light point of view.
+ */
+function toggleView() {
+ if (g_viewFromLight) {
+ g_shadowViewInfo.root.parent = g_renderSurfaceSet;
+ g_colorPassRenderRoot.parent = g_client.renderGraphRoot;
+ g_viewFromLight = false;
+ } else {
+ g_shadowViewInfo.root.parent = g_client.renderGraphRoot;
+ g_colorPassRenderRoot.parent = null;
+ g_viewFromLight = true;
+ }
+}
+
+/**
+ * Creates a material to be put on all shapes in the scene for the shadow pass,
+ * and loads effects for materials in the scene. Other materials are created
+ * on the fly as the shapes are created.
+ */
+function initMaterials() {
+ var colorVertexShader = document.getElementById('colorVertexShader').text;
+ var colorPixelShader = document.getElementById('colorPixelShader').text;
+
+ g_colorEffect = g_pack.createObject('Effect');
+ g_colorEffect.loadVertexShaderFromString(colorVertexShader);
+ g_colorEffect.loadPixelShaderFromString(colorPixelShader);
+
+ var shadowVertexShader = document.getElementById('shadowVertexShader').text;
+ var shadowPixelShader = document.getElementById('shadowPixelShader').text;
+
+ g_shadowMaterial = g_pack.createObject('Material');
+ g_shadowMaterial.drawList = g_shadowViewInfo.performanceDrawList;
+
+ var shadowEffect = g_pack.createObject('Effect');
+ shadowEffect.loadVertexShaderFromString(shadowVertexShader);
+ shadowEffect.loadPixelShaderFromString(shadowPixelShader);
+
+ g_shadowMaterial.effect = shadowEffect;
+ shadowEffect.createUniformParameters(g_shadowMaterial);
+
+ g_shadowSampler = g_pack.createObject('Sampler');
+ g_shadowSampler.texture = g_shadowTexture;
+ g_shadowSampler.minFilter = g_o3d.Sampler.POINT;
+ g_shadowSampler.magFilter = g_o3d.Sampler.POINT;
+ g_shadowSampler.mipFilter = g_o3d.Sampler.POINT;
+ g_shadowSampler.addressModeU = g_o3d.Sampler.BORDER;
+ g_shadowSampler.addressModeV = g_o3d.Sampler.BORDER;
+ g_shadowSampler.borderColor = [1, 1, 1, 1];
+
+}
+
+
+/**
+ * Sets up reasonable view and projection matrices.
+ */
+function updateCamera() {
+ // Set up a perspective transformation for the projection.
+ g_colorViewInfo.drawContext.projection = g_math.matrix4.perspective(
+ g_math.degToRad(30), // 30 degree frustum.
+ g_o3dElement.clientWidth / g_o3dElement.clientHeight, // Aspect ratio.
+ 1, // Near plane.
+ 5000); // Far plane.
+
+ // Set up our view transformation to look towards the world origin where the
+ // cube is located.
+ g_colorViewInfo.drawContext.view = g_math.matrix4.lookAt(
+ g_eyePosition, // eye
+ g_targetPosition, // target
+ [0, 1, 0]); // up
+}
+
+
+/**
+ * Computes the view and projection matrices from the point of view of the
+ * light. Sets the lightViewProjection parameter so the color shader can access
+ * it.
+ */
+function updateLightMatrix() {
+ // The perspective projection matrix for the light.
+ var lightProjection = g_math.matrix4.perspective(
+ g_math.degToRad(45), // 45 degree fov.
+ SHADOW_MAP_WIDTH / SHADOW_MAP_HEIGHT, // Aspect ratio.
+ 4, // Near plane.
+ 20); // Far plane.
+
+ var adjustedProjection =
+ [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0], [0, 0, -1, 1]];
+ o3d.Transform.compose(
+ adjustedProjection, lightProjection, adjustedProjection);
+
+ // Make the light point toward the origin
+ var lightView = g_math.matrix4.lookAt(
+ g_lightWorldPos, // light
+ [0, 0, 0], // target
+ [1, 0, 0]); // up
+
+ g_lightViewProjection = g_math.matrix4.composition(
+ lightProjection, lightView);
+
+ g_shadowViewInfo.drawContext.projection = lightProjection;
+ g_shadowViewInfo.drawContext.view = lightView;
+ g_globalParams.lightViewProjection.value = g_lightViewProjection;
+}
+
+
+/**
+ * Creates shapes using the primitives utility library, and adds them to the
+ * transform graph at the root node.
+ */
+function createShapes() {
+ // A green phong-shaded material for the cube.
+ var cubeMaterial = createColorMaterial([0.2, 0.5, 0, 1]);
+
+ // The cube shape.
+ var cube = o3djs.primitives.createCube(
+ g_pack,
+ cubeMaterial,
+ 2); // The length of each side of the cube.
+
+ // A red phong-shaded material for the sphere.
+ var sphereMaterial = createColorMaterial([0.7, 0.2, 0.1, 1]);
+
+ // The sphere shape.
+ var sphere = o3djs.primitives.createSphere(
+ g_pack, sphereMaterial, 0.5, 50, 50);
+
+ // A blue phong-shaded material for the plane.
+ var planeMaterial = createColorMaterial([0, 0.3, 0.5, 1]);
+
+ // The plane shape.
+ var plane = o3djs.primitives.createPlane(
+ g_pack,
+ planeMaterial,
+ 20, // Width.
+ 20, // Depth.
+ 1, // Horizontal subdivisions.
+ 1); // Vertical subdivisions.
+
+ // Associate to each shape, a translation vector.
+ var transformTable = [
+ {shape: cube, translation: [0, 1, 0]},
+ {shape: sphere, translation: [0.5, 2.5, 0]},
+ {shape: plane, translation: [0, 0, 0]}
+ ];
+
+ // Add the shapes to the transform graph with the translation.
+ var modelRoot = g_pack.createObject('Transform');
+ modelRoot.parent = g_client.root;
+ for (var tt = 0; tt < transformTable.length; ++tt) {
+ var transform = g_pack.createObject('Transform');
+ transform.addShape(transformTable[tt].shape);
+ // The shadow material is bound to a DrawList in the subtree of the
+ // rendergraph that handles the shadow map generation, so it gets drawn in
+ // that render pass only.
+ transformTable[tt].shape.createDrawElements(g_pack, g_shadowMaterial);
+
+ transform.translate(transformTable[tt].translation);
+ transform.parent = modelRoot;
+ }
+}
+
+
+/**
+ * Creates the wireframe frustum showing the shadow map's render volume.
+ */
+function createLightShape() {
+ var inverseMatrix = g_math.matrix4.inverse(g_lightViewProjection);
+
+/*
+ // Scale and translate a cube of side length 2 to get a box
+ // that extends from [-1, -1, 0] to [1, 1, 1].
+ var shape = o3djs.debug.createLineCube(
+ g_pack,
+ o3djs.material.createConstantMaterial(g_pack,
+ g_colorViewInfo,
+ [1, 0, 0, 1]),
+ 2,
+ g_math.matrix4.compose(
+ g_math.matrix4.translation([0, 0, 0.5]),
+ g_math.matrix4.scaling([1, 1, 0.5])));*/
+
+ g_lightFrustumTransform = g_pack.createObject('Transform');
+ g_lightFrustumTransform.localMatrix = inverseMatrix;
+ g_lightFrustumTransform.parent = g_client.root;
+ //g_lightFrustumTransform.addShape(shape);
+}
+
+
+/**
+ * Creates a Phong-shaded, shadowed material based on the given color.
+ */
+function createColorMaterial(baseColor) {
+ var material = g_pack.createObject('Material');
+ material.drawList = g_colorViewInfo.performanceDrawList;
+
+ material.effect = g_colorEffect;
+ g_colorEffect.createUniformParameters(material);
+
+ material.getParam('shadowMapSampler').value = g_shadowSampler;
+
+ material.getParam('ambient').value = g_math.mulScalarVector(0.1, baseColor);
+ material.getParam('diffuse').value = g_math.mulScalarVector(0.8, baseColor);
+ material.getParam('specular').value = [1, 1, 1, 1];
+ material.getParam('shininess').value = 20;
+
+ return material;
+}
+
+/**
+ * Binds params for light position, light color and the light view-projection
+ * matrix to all materials in the scene where they apply.
+ */
+function initGlobalParams() {
+ var paramSpec = {
+ 'lightColor': 'ParamFloat4',
+ 'lightWorldPos': 'ParamFloat3',
+ 'lightViewProjection': 'ParamMatrix4'};
+
+ g_globalParams = o3djs.material.createParams(g_pack, paramSpec);
+ o3djs.material.bindParams(g_pack, g_globalParams);
+
+ g_globalParams.lightWorldPos.value = g_lightWorldPos;
+ g_globalParams.lightColor.value = g_lightColor;
+}
+
+
+/**
+ * The keyboard event handler.
+ */
+function keyPressed(event) {
+ var keyChar = String.fromCharCode(o3djs.event.getEventKeyChar(event));
+ keyChar = keyChar.toLowerCase();
+
+ var delta = 0.2;
+ switch(keyChar) {
+ case 'a':
+ moveLight([-delta, 0, 0]);
+ break;
+ case 'd':
+ moveLight([delta, 0, 0]);
+ break;
+ case 's':
+ moveLight([0, -delta, 0]);
+ break;
+ case 'w':
+ moveLight([0, delta, 0]);
+ break;
+ case 'i':
+ moveLight([0, 0, delta]);
+ break;
+ case 'o':
+ moveLight([0, 0, -delta]);
+ break;
+
+ case ' ':
+ toggleView();
+ break;
+ }
+}
+
+/**
+ * Moves the light by the given vector delta, and updates params so the light
+ * draws in the right spot and the shadows move.
+ */
+function moveLight(delta) {
+ g_lightWorldPos = g_math.addVector(g_lightWorldPos, delta);
+ g_globalParams.lightWorldPos.value = g_lightWorldPos;
+ updateLightMatrix();
+ g_lightFrustumTransform.localMatrix =
+ g_math.matrix4.inverse(g_lightViewProjection);
+}
+
+
+</script>
+
+
+
+<script id="shadowVertexShader" type="text/glsl">
+ /**
+ * This shader is for the effect applied in the first render pass, when the
+ * shadow map is created. The scene is rendered from the perspective of the
+ * light, the grayscale value of each pixel in the rendered image represents
+ * how far away the rendered point is from the light (the lighter, the
+ * farther) This image gets rendered to a texture, and that texture gets
+ * sampled in the second render pass, when the geometry is drawn to the
+ * screen.
+ */
+ attribute vec4 position;
+ uniform mat4 worldViewProjection;
+
+ varying vec4 vposition;
+
+ void main() {
+ vposition = worldViewProjection * position;
+ gl_Position = vposition;
+ }
+</script>
+<script id="shadowPixelShader" type="text/glsl">
+ varying vec4 vposition;
+
+ void main() {
+ vec4 color;
+ vec3 q = vposition.xyz / vposition.w;
+
+ float depth = 0.5*(q.z + 1.0);
+ color.r = fract(16777216.0 * depth);
+ color.g = fract(65536.0 * depth);
+ color.b = fract(256.0 * depth);
+ color.a = depth;
+
+ gl_FragColor = color;
+ }
+</script>
+
+
+<script id="colorVertexShader" type="text/glsl">
+ attribute vec4 position;
+ attribute vec3 normal;
+
+ uniform mat4 worldViewProjection;
+ uniform mat4 world;
+ uniform mat4 worldInverseTranspose;
+ uniform mat4 lightViewProjection;
+
+ varying vec4 vposition;
+ varying vec3 vnormal;
+ varying vec4 vprojTextureCoords;
+ varying vec4 vworldPosition;
+
+ /**
+ * The vertex shader simply transforms the input vertices to screen space.
+ */
+ void main() {
+ vworldPosition = world * position;
+ vnormal = vec3(worldInverseTranspose * vec4(normal, 0));
+ vposition = worldViewProjection * position;
+ vprojTextureCoords = lightViewProjection * world * position;
+ gl_Position = vposition;
+ }
+</script>
+<script id="colorPixelShader" type="text/glsl">
+ uniform vec4 ambient;
+ uniform vec4 diffuse;
+ uniform vec4 specular;
+ uniform float shininess;
+
+ varying vec4 vposition;
+ varying vec4 vworldPosition;
+ varying vec3 vnormal;
+ varying vec4 vprojTextureCoords;
+
+ uniform sampler2D shadowMapSampler;
+
+ uniform vec3 lightWorldPos;
+ uniform mat4 viewInverse;
+
+ vec3 lighting(vec3 position, vec3 normal, vec4 pigment, vec4 specular, float shininess) {
+ vec3 l = normalize(vec3(lightWorldPos) - position); // Toward light.
+ vec3 n = normalize(normal); // Normal.
+ vec3 v = normalize(vec3(viewInverse * vec4(0,0,0,1)) - position); // Toward eye.
+ vec3 r = normalize(-reflect(v, n));
+
+ return clamp(dot(n,l), 0.0, 1.0) * diffuse.rgb +
+ 0.2 * specular.rgb * pow(max(dot(l, r), 0.0), shininess);
+ }
+
+ void main() {
+ vec3 outColor = ambient.rgb;
+ vec4 projCoords = vprojTextureCoords;
+
+ // Convert texture coords to [0, 1] range.
+ projCoords /= projCoords.w;
+ projCoords.x = 0.5 * projCoords.x + 0.5;
+ projCoords.y = 0.5 * projCoords.y + 0.5;
+ projCoords.z = 0.5 * projCoords.z + 0.5;
+
+ float depth = projCoords.z;
+
+ float light;
+
+ // If the rednered point is farther from the light than the distance encoded
+ // in the shadow map, we give it a light coefficient of 0.
+ vec4 color = texture2D(shadowMapSampler, projCoords.xy);
+
+ light = (color.a +
+ color.b / 256.0 +
+ color.g / 65536.0 +
+ color.r / 16777216.0) + 0.008 > depth ? 1.0 : 0.0;
+
+ // Make the illuninated area a round spotlight shape just for fun.
+ // Comment this line out to see just the shadows.
+ light *= 1.0 - smoothstep(0.45, 0.5,
+ length(projCoords.xy - vec2(0.5, 0.5)));
+
+ outColor += light * lighting(
+ vec3(vworldPosition),
+ vnormal,
+ diffuse,
+ specular,
+ shininess);
+
+ gl_FragColor = vec4(outColor, 1.0);
+ }
+</script>
+
+
+
+</head>
+<body>
+<h1>Shadow Maps</h1>
+This sample implements a basic shadow map.
+<br/>
+<!-- Start of O3D plugin -->
+<div id="o3d" width="800px" height="600px"></div>
+<!-- End of O3D plugin -->
+Use A, S, D, W, I and O to move the light.
+Press spacebar to see the shadow map.
+</body>
+</html>
diff --git a/o3d/samples/o3d-webgl/base.js b/o3d/samples/o3d-webgl/base.js
index 9863ee6..9962de5 100644
--- a/o3d/samples/o3d-webgl/base.js
+++ b/o3d/samples/o3d-webgl/base.js
@@ -149,19 +149,31 @@ o3d.inherit = function(subClassName, superClassName) {
subClass.prototype = new superClass;
subClass.prototype.superClassName = superClassName;
subClass.prototype.superClass = superClass;
+ subClass.prototype.className = subClassName;
};
/**
+ * Utility function to remove an object from an array.
+ * @param {!Array} array The array.
+ * @param {Object} object The thing to be removed.
+ */
+o3d.removeFromArray = function(array, object) {
+ var i = array.indexOf(object);
+ if (i >= 0) {
+ array.splice(i, 1);
+ }
+}
+
+
+/**
* If an o3d function has not been implemented in javascript yet, it should
* call this function to throw an error because it's better than doing
* nothing.
*/
o3d.notImplemented = function() {
- var callerName = arguments.caller.toString();
- callerName = callerName.substr('function '.length);
- callerName = ownName.substr(0, ownName.indexOf('('));
- throw 'Not implemented: ' + callerName;
+ debugger;
+ throw 'Not implemented.';
};
@@ -179,6 +191,8 @@ o3d.include('param_object');
o3d.include('param');
o3d.include('event');
o3d.include('raw_data');
+o3d.include('texture');
+o3d.include('bitmap');
o3d.include('file_request');
o3d.include('client');
o3d.include('render_node');
@@ -192,7 +206,6 @@ o3d.include('render_surface_set');
o3d.include('render_surface');
o3d.include('state');
o3d.include('draw_context');
-o3d.include('texture');
o3d.include('sampler');
o3d.include('transform');
o3d.include('pack');
diff --git a/o3d/samples/o3d-webgl/bitmap.js b/o3d/samples/o3d-webgl/bitmap.js
index 6ce1df7..5e2fcfc 100644
--- a/o3d/samples/o3d-webgl/bitmap.js
+++ b/o3d/samples/o3d-webgl/bitmap.js
@@ -73,13 +73,20 @@ o3d.Bitmap.IMAGE = 6;
o3d.Bitmap.SLICE = 7;
+/**
+ * In webgl the bitmap object is represented by an offscreen canvas.
+ * @type {Canvas}
+ * @private
+ */
+o3d.Bitmap.prototype.canvas_ = null;
+
/**
* Flips a bitmap vertically in place.
- * @type {boolean}
*/
-o3d.Bitmap.prototype.flipVertically = false;
-
+o3d.Bitmap.prototype.flipVertically = function() {
+ this.defer_flip_vertically_to_texture_ = true;
+};
/**
@@ -94,7 +101,7 @@ o3d.Bitmap.prototype.flipVertically = false;
*/
o3d.Bitmap.prototype.generateMips =
function(source_level, num_levels) {
- o3d.notImplemented();
+ this.defer_mipmaps_to_texture_ = true;
};
@@ -113,12 +120,29 @@ o3d.Bitmap.prototype.width = 0;
o3d.Bitmap.prototype.height = 0;
+/**
+ * Instead of generating mipmaps in the bitmap object, just set this boolean
+ * to true, then the texture will generate mipmaps when it loads the bitmap.
+ * @type {boolean}
+ * @private
+ */
+o3d.Bitmap.prototype.defer_mipmaps_to_texture_ = false;
+
+
+/**
+ * Instead of flipping vertically in the bitmap object, just set this boolean
+ * to true, then the texture will generate mipmaps when it loads the bitmap.
+ * @type {boolean}
+ * @private
+ */
+o3d.Bitmap.prototype.defer_flip_vertically_to_texture_ = false;
+
/**
* The format of the bitmap (read only).
- * @type {number}
+ * @type {!o3d.Texture.Format}
*/
-o3d.Bitmap.prototype.format = 0;
+o3d.Bitmap.prototype.format = o3d.Texture.UNKNOWN_FORMAT;
@@ -132,9 +156,9 @@ o3d.Bitmap.prototype.numMipmaps = 1;
/**
* The Semantic of the bitmap.
- * @type {!o3d.Stream.Semantic}
+ * @type {!o3d.Bitmap.Semantic}
*/
-o3d.Bitmap.prototype.semantic = o3d.Stream.UNKNOWN_SEMANTIC;
+o3d.Bitmap.prototype.semantic = o3d.Bitmap.UNKNOWN_SEMANTIC;
diff --git a/o3d/samples/o3d-webgl/client.js b/o3d/samples/o3d-webgl/client.js
index 5bbb7b2..95912a9 100644
--- a/o3d/samples/o3d-webgl/client.js
+++ b/o3d/samples/o3d-webgl/client.js
@@ -125,7 +125,10 @@ o3d.Renderer.installRenderInterval = function() {
* The ClientInfo is used to get information about the client.
* @constructor
*/
-o3d.ClientInfo = function() { };
+o3d.ClientInfo = function() {
+ o3d.NamedObject.call(this);
+};
+o3d.inherit('ClientInfo', 'NamedObject');
/**
@@ -208,6 +211,7 @@ o3d.ClientInfo.prototype.non_power_of_two_textures = true;
* @constructor
*/
o3d.Client = function() {
+ o3d.NamedObject.call(this);
this.root = new o3d.Transform;
this.renderGraphRoot = new o3d.RenderNode;
this.root = new o3d.Transform;
@@ -231,7 +235,7 @@ o3d.Client.RenderCallback = goog.typedef;
o3d.Client.TickCallback = goog.typedef;
/**
- * @type {function(!o3d.Event): void}
+ * @type {function(string): void}
*/
o3d.Client.ErrorCallback = goog.typedef;
@@ -262,10 +266,13 @@ o3d.Client.prototype.then_ = 0;
*/
o3d.Client.prototype.root = null;
+
/**
* Function that gets called when the client encounters an error.
*/
-o3d.Client.prototype.error_callback = function(error_message) {};
+o3d.Client.prototype.error_callback = function(error_message) {
+ alert(error_message);
+};
/**
@@ -300,7 +307,7 @@ o3d.Client.prototype.cleanup = function () {
/**
* Creates a pack object.
* A pack object.
- * @returns {!o3d.Pack} A new pack object.
+ * @return {!o3d.Pack} A new pack object.
*/
o3d.Client.prototype.createPack =
function() {
@@ -314,7 +321,7 @@ o3d.Client.prototype.createPack =
* Searches the Client for an object matching the given id.
*
* @param {number} id The id of the object to look for.
- * @returns {o3d.ObjectBase} The object or null if a object
+ * @return {o3d.ObjectBase} The object or null if a object
* with the given id is not found.
*/
o3d.Client.prototype.getObjectById =
@@ -327,7 +334,7 @@ o3d.Client.prototype.getObjectById =
* Searches the Client for objects of a particular name and type.
* @param {string} name name of object to look for.
* @param {string} class_name name of class to look for.
- * @returns {!Array.<!o3d.ObjectBase>} Array of objects found.
+ * @return {!Array.<!o3d.ObjectBase>} Array of objects found.
*/
o3d.Client.prototype.getObjects =
function(name, class_name) {
@@ -339,7 +346,7 @@ o3d.Client.prototype.getObjects =
/**
* Searches the Client for objects of a particular type.
* @param {string} class_name name of class to look for.
- * @returns {!Array.<!Object>} Array of objects found.
+ * @return {!Array.<!Object>} Array of objects found.
*/
o3d.Client.prototype.getObjectsByClassName =
function(class_name) {
@@ -506,6 +513,27 @@ o3d.Client.prototype.__defineSetter__('height',
/**
+ * Initializes this client using the canvas.
+ * @param {Canvas}
+ */
+o3d.Client.prototype.initWithCanvas = function(canvas) {
+ var gl;
+ try {gl = canvas.getContext("experimental-webgl") } catch(e) { }
+ if (!gl)
+ try {gl = canvas.getContext("moz-webgl") } catch(e) { }
+ if (!gl) {
+ alert("No WebGL context found");
+ return null;
+ }
+
+ canvas.client.gl = gl;
+ gl.client = this;
+ gl.displayInfo = {width: canvas.width,
+ height: canvas.height};
+};
+
+
+/**
* Sets the per frame render callback.
*
* Note: The callback will not be called recursively. When your callback is
@@ -736,7 +764,7 @@ o3d.Client.prototype.invalidateAllParameters = function() {
* @param {string} mime_type The type of data url you want.
* Currently O3D only supports image/png. See HTML5 canvas tag
* for info about toDataURL.
- * @returns {string} A Data URL for the backbuffer.
+ * @return {string} A Data URL for the backbuffer.
*/
o3d.Client.prototype.toDataURL =
function(opt_mime_type) {
diff --git a/o3d/samples/o3d-webgl/draw_context.js b/o3d/samples/o3d-webgl/draw_context.js
index ee30d9b..bf360cb 100644
--- a/o3d/samples/o3d-webgl/draw_context.js
+++ b/o3d/samples/o3d-webgl/draw_context.js
@@ -42,6 +42,7 @@
* @constructor
*/
o3d.DrawContext = function(opt_view, opt_projection) {
+ o3d.NamedObject.call(this);
this.view = opt_view ||
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
this.projection = opt_projection ||
diff --git a/o3d/samples/o3d-webgl/draw_list.js b/o3d/samples/o3d-webgl/draw_list.js
index 537751b..a0cffca4 100644
--- a/o3d/samples/o3d-webgl/draw_list.js
+++ b/o3d/samples/o3d-webgl/draw_list.js
@@ -37,6 +37,7 @@
* @constructor
*/
o3d.DrawList = function() {
+ o3d.NamedObject.call(this);
this.list_ = [];
};
o3d.inherit('DrawList', 'NamedObject');
@@ -72,7 +73,6 @@ o3d.DrawList.BY_PRIORITY = 2;
*/
o3d.DrawList.prototype.render = function() {
// TODO(petersont): Add sort.
-
for (var i = 0; i < this.list_.length; ++i) {
var drawElementInfo = this.list_[i];
var world = drawElementInfo.world;
diff --git a/o3d/samples/o3d-webgl/draw_pass.js b/o3d/samples/o3d-webgl/draw_pass.js
index f3deea8..495e357 100644
--- a/o3d/samples/o3d-webgl/draw_pass.js
+++ b/o3d/samples/o3d-webgl/draw_pass.js
@@ -39,6 +39,7 @@
* @constructor
*/
o3d.DrawPass = function(opt_drawList, opt_sortMethod) {
+ o3d.RenderNode.call(this);
this.drawList = opt_drawList;
this.sortMethod = opt_sortMethod || o3d.DrawList.BY_PERFORMANCE;
};
diff --git a/o3d/samples/o3d-webgl/effect.js b/o3d/samples/o3d-webgl/effect.js
index 53d8882..f8d7dc5 100644
--- a/o3d/samples/o3d-webgl/effect.js
+++ b/o3d/samples/o3d-webgl/effect.js
@@ -89,6 +89,7 @@ o3d.EffectParameterInfo.prototype.sas_class_name = '';
* @constructor
*/
o3d.EffectStreamInfo = function(opt_semantic, opt_semantic_index) {
+ o3d.NamedObject.call(this);
if (!opt_semantic) {
opt_semantic = o3d.Stream.UNKNOWN_SEMANTIC;
}
@@ -176,6 +177,13 @@ o3d.Effect.prototype.loadShaderFromString = function(shaderString, type) {
var shader = this.gl.createShader(type);
this.gl.shaderSource(shader, shaderString);
this.gl.compileShader(shader);
+
+ var log = this.gl.getShaderInfoLog(shader);
+ if (log != '') {
+ this.gl.client.error_callback(
+ 'Shader compile failed with error log:\n' + log);
+ }
+
this.gl.attachShader(this.program_, shader);
};
@@ -245,24 +253,24 @@ o3d.Effect.prototype.createUniformParameters =
'worldView': true,
'worldProjection': true,
'worldViewProjection': true,
- 'worldI': true,
- 'viewI': true,
- 'projectionI': true,
- 'worldViewI': true,
- 'worldProjectionI': true,
- 'worldViewProjectionI': true,
- 'worldT': true,
- 'viewT': true,
- 'projectionT': true,
- 'worldViewT': true,
- 'worldProjectionT': true,
- 'worldViewProjectionT': true,
- 'worldIT': true,
- 'viewIT': true,
- 'projectionIT': true,
- 'worldViewIT': true,
- 'worldProjectionIT': true,
- 'worldViewProjectionIT': true};
+ 'worldInverse': true,
+ 'viewInverse': true,
+ 'projectionInverse': true,
+ 'worldViewInverse': true,
+ 'worldProjectionInverse': true,
+ 'worldViewProjectionInverse': true,
+ 'worldTranspose': true,
+ 'viewTranspose': true,
+ 'projectionTranspose': true,
+ 'worldViewTranspose': true,
+ 'worldProjectionTranspose': true,
+ 'worldViewProjectionTranspose': true,
+ 'worldInverseTranspose': true,
+ 'viewInverseTranspose': true,
+ 'projectionInverseTranspose': true,
+ 'worldViewInverseTranspose': true,
+ 'worldProjectionInverseTranspose': true,
+ 'worldViewProjectionInverseTranspose': true};
for (name in this.uniforms) {
var info = this.uniforms[name].info;
@@ -330,7 +338,7 @@ o3d.Effect.prototype.createSASParameters =
/**
* Gets info about the parameters this effect needs.
- * @returns {!Array.<!o3d.EffectParameterInfo>} an array of
+ * @return {!Array.<!o3d.EffectParameterInfo>} an array of
* EffectParameterInfo objects.
*/
o3d.Effect.prototype.getParameterInfo = function() {
@@ -341,7 +349,7 @@ o3d.Effect.prototype.getParameterInfo = function() {
/**
* Gets info about the streams this effect needs.
- * @returns {!Array.<!o3d.EffectStreamInfo>} an array of
+ * @return {!Array.<!o3d.EffectStreamInfo>} an array of
* EffectStreamInfo objects.
*/
o3d.Effect.prototype.getStreamInfo = function() {
@@ -390,6 +398,12 @@ o3d.Effect.prototype.searchForParams = function(object_list) {
}
}
}
+
+ for (name in this.uniforms) {
+ if (!filled_map[name]) {
+ throw ('Uniform param not filled: '+name);
+ }
+ }
};
diff --git a/o3d/samples/o3d-webgl/element.js b/o3d/samples/o3d-webgl/element.js
index 8a953a8..e42a788 100644
--- a/o3d/samples/o3d-webgl/element.js
+++ b/o3d/samples/o3d-webgl/element.js
@@ -164,7 +164,7 @@ o3d.Element.prototype.drawElements = [];
* pass null it will use the material on this Element. This allows you
* to easily setup the default (just draw as is) by passing null or
* setup a shadow pass by passing in a shadow material.
- * @returns {!o3d.DrawElement} The created draw element.
+ * @return {!o3d.DrawElement} The created draw element.
*/
o3d.Element.prototype.createDrawElement =
function(pack, material) {
@@ -183,7 +183,7 @@ o3d.Element.prototype.createDrawElement =
* @param {o3d.Cull} cull which side of the triangles to ignore.
* @param {!o3d.math.Point3} start position of start of ray in local space.
* @param {!o3d.math.Point3} end position of end of ray. in local space.
- * @returns {!o3d.RayIntersectionInfo} RayIntersectionInfo class. If valid()
+ * @return {!o3d.RayIntersectionInfo} RayIntersectionInfo class. If valid()
* is false then something was wrong, Check GetLastError(). If
* intersected() is true then the ray intersected a something. position()
* is the exact point of intersection.
@@ -198,7 +198,7 @@ o3d.Element.prototype.intersectRay =
* Computes the bounding box in same coordinate system as the specified
* POSITION stream.
* @param {number} position_stream_index Index of POSITION stream.
- * @returns {!o3d.BoundingBox} The boundingbox for this element in local space.
+ * @return {!o3d.BoundingBox} The boundingbox for this element in local space.
*/
o3d.Element.prototype.getBoundingBox =
function(position_stream_index) {
diff --git a/o3d/samples/o3d-webgl/event.js b/o3d/samples/o3d-webgl/event.js
index 91bfcbd..c928e23 100644
--- a/o3d/samples/o3d-webgl/event.js
+++ b/o3d/samples/o3d-webgl/event.js
@@ -35,7 +35,9 @@
* as an argument to event handlers triggered by the plugin.
* @constructor
*/
-o3d.Event = function() { };
+o3d.Event = function() {
+ o3d.ObjectBase.call(this);
+};
o3d.inherit('Event', 'ObjectBase');
@@ -233,7 +235,9 @@ o3d.Event.prototype.fullscreen = false;
* An Event that gets sent to the render callback.
* @constructor
*/
-o3d.RenderEvent = function() {};
+o3d.RenderEvent = function() {
+ o3d.Event.call(this);
+};
o3d.inherit('RenderEvent', 'Event');
@@ -248,7 +252,9 @@ o3d.RenderEvent.prototype.elapsedTime = 0;
* An Event that gets sent to the render callback.
* @constructor
*/
-o3d.TickEvent = function() {};
+o3d.TickEvent = function() {
+ o3d.Event.call(this);
+};
o3d.inherit('RenderEvent', 'Event');
diff --git a/o3d/samples/o3d-webgl/field.js b/o3d/samples/o3d-webgl/field.js
index 5f82237..23058bf 100644
--- a/o3d/samples/o3d-webgl/field.js
+++ b/o3d/samples/o3d-webgl/field.js
@@ -37,7 +37,9 @@
* Buffer the Field's buffer property will be set to null.
* @constructor
*/
-o3d.Field = function() { };
+o3d.Field = function() {
+ o3d.NamedObject.call(this);
+};
o3d.inherit('Field', 'NamedObject');
/**
@@ -101,7 +103,7 @@ o3d.Field.prototype.setAt =
*
* @param {number} start_index index of the first value to get.
* @param {number} num_elements number of elements to read from field.
- * @returns {number} The values of the field.
+ * @return {number} The values of the field.
*/
o3d.Field.prototype.getAt =
function(start_index, num_elements) {
@@ -114,21 +116,27 @@ o3d.Field.prototype.getAt =
* A field that contains floating point numbers.
* @constructor
*/
-o3d.FloatField = function() { };
+o3d.FloatField = function() {
+ o3d.Field.call(this);
+};
o3d.inherit('FloatField', 'Field');
/**
* A field that contains unsigned integers.
* @constructor
*/
-o3d.UInt32Field = function() { };
+o3d.UInt32Field = function() {
+ o3d.Field.call(this);
+};
o3d.inherit('UInt32Field', 'Field');
/**
* A field that contains unsigned bytes.
* @constructor
*/
-o3d.UByteNField = function() { };
+o3d.UByteNField = function() {
+ o3d.Field.call(this);
+};
o3d.inherit('UByteNField', 'Field');
diff --git a/o3d/samples/o3d-webgl/file_request.js b/o3d/samples/o3d-webgl/file_request.js
index 122364a..8c0d44c 100644
--- a/o3d/samples/o3d-webgl/file_request.js
+++ b/o3d/samples/o3d-webgl/file_request.js
@@ -133,6 +133,13 @@ o3d.FileRequest.prototype.done = false;
o3d.FileRequest.prototype.success = false;
+/**
+ * The image object if we are opening an image.
+ * @type {Image}
+ * @private
+ */
+o3d.FileRequest.prototype.image_ = null;
+
/**
* An error message.
@@ -143,17 +150,53 @@ o3d.FileRequest.prototype.success = false;
o3d.FileRequest.prototype.error = '';
+/**
+ * Guesses from a url whether the url is an image file.
+ * @param {string} url The URL.
+ * @private
+ */
+o3d.FileRequest.prototype.isImageUrl_ = function(url) {
+ var extension = url.substring(url.length - 4);
+ return (extension == '.png' || extension == '.jpg');
+};
+
+
+/**
+ * Called by the image class when the image file is loaded... if we're
+ * loading an image.
+ * @private
+ */
+o3d.FileRequest.prototype.imageLoaded_ = function() {
+ if (this.image_.complete) {
+ this.success = true;
+ this.done = true;
+ this.readyState = 4;
+ this.data = new o3d.RawData();
+ this.data.image_ = this.image_;
+ }
+ this.onreadystatechange.apply(this, arguments);
+};
+
/**
* Set up several of the request fields.
* @param {string} method "GET" is the only supported method at this time
* @param {string} uri the location of the file to fetch
- * @param {boolean} async true is the only legal value at this time
+ * @param {boolean} async true is the only legal value at this time.
*/
o3d.FileRequest.prototype.open =
function(method, uri, async) {
this.uri = uri;
- this.request_.open(method, uri, async);
+ if (this.isImageUrl_(uri)) {
+ this.image_ = new Image();
+ var that = this;
+ this.image_.onload = function() {
+ that.imageLoaded_.call(that);
+ }
+ this.image_.src = uri;
+ } else {
+ this.request_.open(method, uri, async);
+ }
};
@@ -163,7 +206,7 @@ o3d.FileRequest.prototype.open =
* matter what, with success or failure.
*/
o3d.FileRequest.prototype.send = function() {
- this.request_.send();
+ // This function left blank for compatability with o3djs.io.
};
diff --git a/o3d/samples/o3d-webgl/named_object.js b/o3d/samples/o3d-webgl/named_object.js
index ce6c871..0fd1ec2 100644
--- a/o3d/samples/o3d-webgl/named_object.js
+++ b/o3d/samples/o3d-webgl/named_object.js
@@ -31,29 +31,12 @@
/**
- * Takes the name of a class as an argument, and returns true if this object is
- * either an instance of that class or derives from that class.
- *
- * var t = pack.createObject('o3d.Transform');
- * t.isAClassName('o3d.Transform');
- * t.isAClassName('o3d.ParamObject');
- * t.isAClassName('o3d.Shape');
- *
- * @param {o3d.String} class_name Name of class to check for.
- * @returns {o3d.bool} true if this object is a or is derived from the given
- * class name.
- */
-o3d.ObjectBase.prototype.isAClassName =
- function(class_name) {
- o3d.notImplemented();
-};
-
-
-/**
* Base class for all objects that can have their name set.
* @constructor
*/
-o3d.NamedObject = function() { };
+o3d.NamedObject = function() {
+ o3d.NamedObjectBase.call(this);
+};
o3d.inherit('NamedObject', 'NamedObjectBase');
diff --git a/o3d/samples/o3d-webgl/named_object_base.js b/o3d/samples/o3d-webgl/named_object_base.js
index 5176426..b3b6858 100644
--- a/o3d/samples/o3d-webgl/named_object_base.js
+++ b/o3d/samples/o3d-webgl/named_object_base.js
@@ -34,7 +34,9 @@
* Base class for all objects that are identifiable by a name.
* @constructor
*/
-o3d.NamedObjectBase = function() { };
+o3d.NamedObjectBase = function() {
+ o3d.ObjectBase.call(this);
+};
o3d.inherit('NamedObjectBase', 'ObjectBase');
diff --git a/o3d/samples/o3d-webgl/object_base.js b/o3d/samples/o3d-webgl/object_base.js
index 42931eb..a0f81b9 100644
--- a/o3d/samples/o3d-webgl/object_base.js
+++ b/o3d/samples/o3d-webgl/object_base.js
@@ -54,14 +54,16 @@ o3d.ObjectBase.prototype.superClass = null;
/**
* Traverses the current object's class and all its superclasses and
* determines if any of them are of the given name.
- * returns {bool}
+ * @param {string} className The name of a class.
+ * @return {boolean} Whether this is counts as a className.
*/
-o3d.ObjectBase.isAClassName = function(o, className) {
- while (o != undefined) {
- if (o.className == 'className') {
+o3d.ObjectBase.prototype.isAClassName = function(className) {
+ var object = this;
+ while (object != undefined) {
+ if (object.className == className) {
return true;
}
- o = o.superClass.prototype;
+ object = object.superClass && object.superClass.prototype;
}
return false;
};
diff --git a/o3d/samples/o3d-webgl/pack.js b/o3d/samples/o3d-webgl/pack.js
index fc10e49..925e5f7 100644
--- a/o3d/samples/o3d-webgl/pack.js
+++ b/o3d/samples/o3d-webgl/pack.js
@@ -39,6 +39,7 @@
* @constructor
*/
o3d.Pack = function() {
+ o3d.NamedObject.call(this);
this.objects_ = [];
};
o3d.inherit('Pack', 'NamedObject');
@@ -105,22 +106,12 @@ o3d.Pack.prototype.destroy = function() {
* Now the last reference has been removed and myTransform will be freed.
*
* @param {o3d.ObjectBase} object Object to remove.
- * @returns {boolean} True if the object was successfully removed.
+ * @return {boolean} True if the object was successfully removed.
* False if the object is not part of this pack.
*/
o3d.Pack.prototype.removeObject =
function(object) {
- var i = 0;
- for (var j = 0; j < this.objects_.length; ++j) {
- if (this.objects_[i] == object) {
- j++;
- }
- this.objects_[j] = this.objects_[i];
- i++;
- }
- if (this.objects_.length > i) {
- this.objects_.pop();
- }
+ o3d.removeFromArray(this.objects_, object);
};
@@ -176,7 +167,7 @@ o3d.Pack.prototype.removeObject =
* ParamOp4FloatsToFloat4
* ParamOp16FloatsToMatrix4
* TRSToMatrix4
- * @returns {o3d.ObjectBase} The created object.
+ * @return {o3d.ObjectBase} The created object.
*/
o3d.Pack.prototype.createObject =
function(type_name) {
@@ -186,6 +177,7 @@ o3d.Pack.prototype.createObject =
}
var object = new foo();
object.gl = this.gl;
+ this.objects_.push(object);
return object;
};
@@ -204,11 +196,32 @@ o3d.Pack.prototype.createObject =
* compelete mipmap chain.
* @param {boolean} enable_render_surfaces If true, the texture object will
* expose RenderSurface objects through GetRenderSurface(...).
- * @returns {!o3d.Texture2D} The Texture2D object.
+ * @return {!o3d.Texture2D} The Texture2D object.
*/
o3d.Pack.prototype.createTexture2D =
function(width, height, format, levels, enable_render_surfaces) {
- o3d.notImplemented();
+ var texture = this.createObject('Texture2D');
+ texture.width = width;
+ texture.height = height;
+ texture.levels = levels;
+ texture.texture_ = this.gl.createTexture();
+
+ if (enable_render_surfaces) {
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture.texture_);
+ this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, width, height,
+ 0, this.gl.RGBA, this.gl.UNSIGNED_BYTE, null);
+
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
+ }
+
+ return texture;
};
@@ -225,7 +238,7 @@ o3d.Pack.prototype.createTexture2D =
* the compelete mipmap chain.
* @param {boolean} enable_render_surfaces If true, the texture object
* will expose RenderSurface objects through GetRenderSurface(...).
- * @returns {!o3d.TextureCUBE} The TextureCUBE object.
+ * @return {!o3d.TextureCUBE} The TextureCUBE object.
*/
o3d.Pack.prototype.createTextureCUBE =
function(edge_length, format, levels, enable_render_surfaces) {
@@ -241,11 +254,13 @@ o3d.Pack.prototype.createTextureCUBE =
*
* @param {number} width The width of the RenderSurface in pixels
* @param {number} height The height of the RenderSurface in pixels
- * @returns {!o3d.RenderDepthStencilSurface} The RenderSurface object.
+ * @return {!o3d.RenderDepthStencilSurface} The RenderSurface object.
*/
o3d.Pack.prototype.createDepthStencilSurface =
function(width, height) {
- o3d.notImplemented();
+ var surface = this.createObject("RenderDepthStencilSurface");
+ surface.initWithSize_(width, height);
+ return surface;
};
@@ -260,7 +275,7 @@ o3d.Pack.prototype.createDepthStencilSurface =
* @param {string} class_type_name the Class of the object. It is okay
* to pass base types for example "o3d.RenderNode" will return
* ClearBuffers, DrawPasses, etc...
- * @returns {!Array.<!o3d.ObjectBase>} Array of Objects.
+ * @return {!Array.<!o3d.ObjectBase>} Array of Objects.
*/
o3d.Pack.prototype.getObjects =
function(name, class_type_name) {
@@ -278,11 +293,24 @@ o3d.Pack.prototype.getObjects =
* @param {string} class_type_name the Class of the object. It is
* okay to pass base types for example "o3d.RenderNode" will return
* ClearBuffers, DrawPasses, etc...
- * @returns {!Array.<!o3d.ObjectBase>} Array of Objects.
+ * @return {!Array.<!o3d.ObjectBase>} Array of Objects.
*/
o3d.Pack.prototype.getObjectsByClassName =
function(class_type_name) {
- o3d.notImplemented();
+ if (class_type_name.substr(0, 4) == 'o3d.') {
+ class_type_name = class_type_name.substr(4);
+ }
+
+ var found = [];
+
+ for (var i = 0; i < this.objects_.length; ++i) {
+ var object = this.objects_[i];
+ if (object.isAClassName(class_type_name)) {
+ found.push(object);
+ }
+ }
+
+ return found;
};
@@ -311,7 +339,7 @@ o3d.Pack.prototype.objects_ = [];
* load a texture is to load a RawData, use that to create Bitmap, Massage
* the Bitmap to your liking the use that to create a Texture.
* @param {string} type Must be "TEXTURE" or "RAWDATA"
- * @returns {!o3d.FileRequest} a FileRequest
+ * @return {!o3d.FileRequest} a FileRequest
*/
o3d.Pack.prototype.createFileRequest =
function(type) {
@@ -328,18 +356,43 @@ o3d.Pack.prototype.createFileRequest =
*
* @param {!o3d.RawData} raw_data contains the bitmap data in a supported
* format.
- * @returns {!o3d.Bitmap} An Array of Bitmaps object.
+ * @return {!Array.<!o3d.Bitmap>} An Array of Bitmaps object.
*/
o3d.Pack.prototype.createBitmapsFromRawData =
function(raw_data) {
- o3d.notImplemented();
+ var bitmap = this.createObject('Bitmap')
+ if (!raw_data.image_) {
+ throw ('Cannot create bitmap from non-image data.');
+ return [];
+ }
+ bitmap.height = raw_data.image_.height;
+ bitmap.width = raw_data.image_.width;
+
+ var canvas = document.createElement('CANVAS');
+
+ canvas.width = bitmap.width;
+ canvas.height = bitmap.height;
+
+ bitmap.canvas_ = canvas;
+ var context = canvas.getContext('2d');
+ // Flip it.
+ context.translate(0, bitmap.height);
+ context.scale(1, -1);
+ context.drawImage(raw_data.image_,
+ 0, 0, bitmap.width, bitmap.height);
+
+ // TODO(petersont): I'm not sure how to get the format.
+ bitmap.format = o3d.Texture.ARGB8;
+ bitmap.numMipmaps = 1;
+
+ return [bitmap];
};
/**
* Create RawData given a data URL.
* @param {string} data_url The data URL from which to create the RawData.
- * @returns {!o3d.RawData} The RawData.
+ * @return {!o3d.RawData} The RawData.
*/
o3d.Pack.prototype.createRawDataFromDataURL =
function(data_url) {
diff --git a/o3d/samples/o3d-webgl/param.js b/o3d/samples/o3d-webgl/param.js
index 0bb28fe..3b23f58 100644
--- a/o3d/samples/o3d-webgl/param.js
+++ b/o3d/samples/o3d-webgl/param.js
@@ -79,13 +79,39 @@ o3d.Param.prototype.outputConnections = [];
o3d.Param.prototype.owner_ = null;
/**
+ * @type {Object} The value of the parameter.
+ */
+o3d.Param.prototype.value_ = null;
+
+o3d.Param.prototype.__defineSetter__('value',
+ function(v) {
+ if (this.inputConnection) {
+ throw ('Tried to set bound parameter.');
+ } else {
+ this.value_ = v;
+ }
+ }
+);
+
+o3d.Param.prototype.__defineGetter__('value',
+ function() {
+ if (this.inputConnection) {
+ return this.inputConnection.value;
+ } else {
+ return this.value_;
+ }
+ }
+);
+
+
+/**
* Directly binds two Param elements such that this parameter gets its value
* from the source parameter. The source must be compatible with this
* parameter.
*
* @param {o3d.Param} source_param The parameter that the value originates
* from. Passing in null will unbind any parameter currently bound.
- * @returns {boolean} True if the bind succeeded.
+ * @return {boolean} True if the bind succeeded.
*/
o3d.Param.prototype.bind =
function(source_param) {
@@ -130,20 +156,6 @@ o3d.Param.prototype.unbindOutputs = function() {
o3d.Param.prototype.read_only_ = false;
-
-/**
- * The input connection for this param.
- */
-o3d.Param.prototype.input_connection = null;
-
-
-
-/**
- * The output connections for this param.
- */
-o3d.Param.prototype.output_connections = [];
-
-
/**
* @constructor
*/
@@ -703,7 +715,7 @@ o3d.inherit('WorldViewProjectionInverseTransposeParamMatrix4',
* Called to specify the value of a uniform variable.
*/
o3d.ParamFloat.prototype.applyToLocation = function(gl, location) {
- gl.uniform4fv(location, this.value);
+ gl.uniform1f(location, this.value);
};
/**
@@ -736,6 +748,18 @@ o3d.ParamMatrix4.prototype.applyToLocation = function(gl, location) {
o3d.Transform.flattenMatrix4(this.value));
};
+/**
+ * Called to specify the value of a uniform variable.
+ */
+o3d.ParamSampler.prototype.applyToLocation = function(gl, location) {
+ var i = 0;
+ gl.activeTexture(gl.TEXTURE0 + i);
+ if (!this.value || !this.value.texture || !this.value.texture.texture_) {
+ throw ('Attempt to use texture parameter before texture value set.');
+ }
+ gl.bindTexture(gl.TEXTURE_2D, this.value.texture.texture_);
+ gl.uniform1i(location, i);
+};
/**
@@ -759,43 +783,43 @@ o3d.Param.SAS.createParam('viewProjection',
o3d.Param.SAS.createParam('worldViewProjection',
'WorldViewProjectionParamMatrix4');
-o3d.Param.SAS.createParam('worldI',
+o3d.Param.SAS.createParam('worldInverse',
'WorldInverseParamMatrix4');
-o3d.Param.SAS.createParam('viewI',
+o3d.Param.SAS.createParam('viewInverse',
'ViewInverseParamMatrix4');
-o3d.Param.SAS.createParam('projectionI',
+o3d.Param.SAS.createParam('projectionInverse',
'ProjectionInverseParamMatrix4');
-o3d.Param.SAS.createParam('worldViewI',
+o3d.Param.SAS.createParam('worldViewInverse',
'WorldViewInverseParamMatrix4');
-o3d.Param.SAS.createParam('viewProjectionI',
+o3d.Param.SAS.createParam('viewProjectionInverse',
'ViewProjectionInverseParamMatrix4');
-o3d.Param.SAS.createParam('worldViewProjectionI',
+o3d.Param.SAS.createParam('worldViewProjectionInverse',
'WorldViewProjectionInverseParamMatrix4');
-o3d.Param.SAS.createParam('worldT',
+o3d.Param.SAS.createParam('worldTranspose',
'WorldInverseParamMatrix4');
-o3d.Param.SAS.createParam('viewT',
+o3d.Param.SAS.createParam('viewTranspose',
'ViewTransposeParamMatrix4');
-o3d.Param.SAS.createParam('projectionT',
+o3d.Param.SAS.createParam('projectionTranspose',
'ProjectionTransposeParamMatrix4');
-o3d.Param.SAS.createParam('worldViewT',
+o3d.Param.SAS.createParam('worldViewTranspose',
'WorldViewTransposeParamMatrix4');
-o3d.Param.SAS.createParam('viewProjectionT',
+o3d.Param.SAS.createParam('viewProjectionTranspose',
'ViewProjectionTransposeParamMatrix4');
-o3d.Param.SAS.createParam('worldViewProjectionT',
+o3d.Param.SAS.createParam('worldViewProjectionTranspose',
'WorldViewProjectionTransposeParamMatrix4');
-o3d.Param.SAS.createParam('worldIT',
+o3d.Param.SAS.createParam('worldInverseTranspose',
'WorldInverseTransposeParamMatrix4');
-o3d.Param.SAS.createParam('viewIT',
+o3d.Param.SAS.createParam('viewInverseTranspose',
'ViewInverseTransposeParamMatrix4');
-o3d.Param.SAS.createParam('projectionIT',
+o3d.Param.SAS.createParam('projectionInverseTranspose',
'ProjectionInverseTransposeParamMatrix4');
-o3d.Param.SAS.createParam('worldViewIT',
+o3d.Param.SAS.createParam('worldViewInverseTranspose',
'WorldViewInverseTransposeParamMatrix4');
-o3d.Param.SAS.createParam('viewProjectionIT',
+o3d.Param.SAS.createParam('viewProjectionInverseTranspose',
'ViewProjectionInverseTransposeParamMatrix4');
-o3d.Param.SAS.createParam('worldViewProjectionIT',
+o3d.Param.SAS.createParam('worldViewProjectionInverseTranspose',
'WorldViewProjectionInverseTransposeParamMatrix4');
/**
diff --git a/o3d/samples/o3d-webgl/param_object.js b/o3d/samples/o3d-webgl/param_object.js
index 625f876..5c5ea89 100644
--- a/o3d/samples/o3d-webgl/param_object.js
+++ b/o3d/samples/o3d-webgl/param_object.js
@@ -36,6 +36,7 @@
* @constructor
*/
o3d.ParamObject = function() {
+ o3d.NamedObject.call(this);
this.params_ = {};
};
o3d.inherit('ParamObject', 'NamedObject');
@@ -95,7 +96,7 @@ o3d.inherit('ParamObject', 'NamedObject');
* 'WorldViewProjectionInverseParamMatrix4'
* 'WorldViewProjectionTransposeParamMatrix4'
* 'WorldViewProjectionInverseTransposeParamMatrix4'
- * @returns {!o3d.Param} The newly created Param or null on failure.
+ * @return {!o3d.Param} The newly created Param or null on failure.
*/
o3d.ParamObject.prototype.createParam =
function(param_name, param_type_name) {
@@ -113,7 +114,7 @@ o3d.ParamObject.prototype.createParam =
* Searches by name for a Param defined in the object.
*
* @param {string} param_name Name to search for.
- * @returns {!o3d.Param} The Param with the given name, or null otherwise.
+ * @return {!o3d.Param} The Param with the given name, or null otherwise.
*/
o3d.ParamObject.prototype.getParam =
function(param_name) {
@@ -128,7 +129,7 @@ o3d.ParamObject.prototype.getParam =
* or if the param is unremovable.
*
* @param {!o3d.Param} param param to remove.
- * @returns {boolean} True if the param was removed.
+ * @return {boolean} True if the param was removed.
*/
o3d.ParamObject.prototype.removeParam =
function(param) {
diff --git a/o3d/samples/o3d-webgl/raw_data.js b/o3d/samples/o3d-webgl/raw_data.js
index ab3c0f4..59a441c 100644
--- a/o3d/samples/o3d-webgl/raw_data.js
+++ b/o3d/samples/o3d-webgl/raw_data.js
@@ -44,7 +44,9 @@
* request.send();
* @constructor
*/
-o3d.RawData = function() { };
+o3d.RawData = function() {
+ o3d.NamedObject.call(this);
+};
o3d.inherit('RawData', 'NamedObject');
@@ -56,6 +58,13 @@ o3d.inherit('RawData', 'NamedObject');
o3d.RawData.prototype.string_value = '';
+/**
+ * The data as an image if it is an image.
+ * @type {Image}
+ * @private
+ */
+o3d.RawData.prototype.image_ = null;
+
/**
* The uri of the RawData.
diff --git a/o3d/samples/o3d-webgl/ray_intersection_info.js b/o3d/samples/o3d-webgl/ray_intersection_info.js
index ab317b4..db37c4d 100644
--- a/o3d/samples/o3d-webgl/ray_intersection_info.js
+++ b/o3d/samples/o3d-webgl/ray_intersection_info.js
@@ -36,6 +36,7 @@
* @constructor
*/
o3d.RayIntersectionInfo = function() {
+ o3d.NamedObject.call(this);
o3d.RayIntersectionInfo.prototype.position = [0, 0, 0];
};
o3d.inherit('RayIntersectionInfo', 'NamedObject');
diff --git a/o3d/samples/o3d-webgl/render_node.js b/o3d/samples/o3d-webgl/render_node.js
index d97b2e9..fd82868 100644
--- a/o3d/samples/o3d-webgl/render_node.js
+++ b/o3d/samples/o3d-webgl/render_node.js
@@ -41,6 +41,7 @@
* @constructor
*/
o3d.RenderNode = function(opt_priority, opt_active) {
+ o3d.ParamObject.call(this);
this.priority = opt_priority;
this.children = [];
};
@@ -77,8 +78,16 @@ o3d.RenderNode.prototype.parent = null;
o3d.RenderNode.prototype.__defineSetter__('parent',
function(p) {
+ if (this.parent_) {
+ this.parent_.removeChild(this);
+ }
this.parent_ = p;
- p.addChild(this);
+ if (this.parent_) {
+ if (!this.parent_.addChild) {
+ throw ('Parent of render node must be render node or null.');
+ }
+ this.parent_.addChild(this);
+ }
}
);
@@ -97,6 +106,14 @@ o3d.RenderNode.prototype.addChild = function(child) {
};
+/**
+ * Removes a child node.
+ * @param {o3d.RenderNode} child The child to add.
+ */
+o3d.RenderNode.prototype.removeChild = function(child) {
+ o3d.removeFromArray(this.children, child);
+};
+
/**
* The immediate children of this RenderNode.
@@ -146,7 +163,7 @@ o3d.RenderNode.prototype.getRenderNodesInTree =
* will affect them.
*
* @param {string} name Rendernode name to look for.
- * @returns {Array.<!o3d.RenderNode>} An array containing all nodes among
+ * @return {Array.<!o3d.RenderNode>} An array containing all nodes among
* this node and its decendants that have the given name.
*/
o3d.RenderNode.prototype.getRenderNodesByNameInTree =
@@ -164,7 +181,7 @@ o3d.RenderNode.prototype.getRenderNodesByNameInTree =
* will affect them.
*
* @param {string} class_name class name to look for.
- * @returns {Array.<!o3d.RenderNode>} An array containing all nodes among
+ * @return {Array.<!o3d.RenderNode>} An array containing all nodes among
* this node and its decendants whose type is class_name.
*/
o3d.RenderNode.prototype.getRenderNodesByClassNameInTree =
diff --git a/o3d/samples/o3d-webgl/render_surface.js b/o3d/samples/o3d-webgl/render_surface.js
index d3b3877..8012bea 100644
--- a/o3d/samples/o3d-webgl/render_surface.js
+++ b/o3d/samples/o3d-webgl/render_surface.js
@@ -41,6 +41,9 @@
*/
o3d.RenderSurfaceBase = function(width, height, texture) {
o3d.ParamObject.call(this);
+ this.width = width;
+ this.height = height;
+ this.texture = texture;
};
o3d.inherit('RenderSurfaceBase', 'ParamObject');
@@ -60,7 +63,6 @@ o3d.RenderSurfaceBase.prototype.width = 0;
o3d.RenderSurfaceBase.prototype.height = 0;
-
/**
* A RenderSurface encapsulates the notion of a renderable surface.
* When used in conjunction with a RenderSurfaceSet node in the render graph,
@@ -69,7 +71,9 @@ o3d.RenderSurfaceBase.prototype.height = 0;
* only be accessed through the texture getRenderSurface(...) interfaces.
* @constructor
*/
-o3d.RenderSurface = function() { };
+o3d.RenderSurface = function() {
+ o3d.RenderSurfaceBase.call(this);
+};
o3d.inherit('RenderSurface', 'RenderSurfaceBase');
@@ -80,10 +84,61 @@ o3d.RenderSurface.prototype.texture = null;
/**
+ * The mip level targeted by this render surface.
+ * @type {number}
+ */
+o3d.RenderSurface.level = 0;
+
+
+/**
+ * The underlying GL framebuffer object.
+ * @type {WebGLFramebuffer}
+ * @private
+ */
+o3d.RenderSurfaceBase.prototype.framebuffer_ = null;
+
+/**
+ * Initializes a render surface to render to the given texture.
+ * @param {o3d.Texture2D} texture The texture.
+ */
+o3d.RenderSurface.prototype.initWithTexture = function(texture, level) {
+ this.framebuffer_ = this.gl.createFramebuffer();
+ this.texture = texture;
+ this.level = level;
+ this.width = texture.width;
+ this.height = texture.height;
+};
+
+/**
* A RenderDepthStencilSurface represents a depth stencil render surface.
* @constructor
*/
-o3d.RenderDepthStencilSurface = function() { };
+o3d.RenderDepthStencilSurface = function() {
+ o3d.RenderSurfaceBase.call(this);
+};
o3d.inherit('RenderDepthStencilSurface', 'RenderSurfaceBase');
+/**
+ * The GL renderbuffer object for the depth buffer.
+ * @type {WebGLRenderbuffer}
+ * @private
+ */
+o3d.RenderDepthStencilSurface.prototype.depth_stencil_buffer_ = null;
+
+
+/**
+ * Allocates depth and stnecil buffers of the given size.
+ * @param {number} width
+ * @param {number} height
+ * @private
+ */
+o3d.RenderDepthStencilSurface.prototype.initWithSize_ =
+ function(width, height) {
+ this.depth_stencil_buffer_ = this.gl.createRenderbuffer();
+ this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, this.depth_stencil_buffer_);
+ this.gl.renderbufferStorage(
+ this.gl.RENDERBUFFER, this.gl.DEPTH_COMPONENT16, width, height);
+ this.width = width;
+ this.height = height;
+};
diff --git a/o3d/samples/o3d-webgl/render_surface_set.js b/o3d/samples/o3d-webgl/render_surface_set.js
index dfcd901..6b4bbec 100644
--- a/o3d/samples/o3d-webgl/render_surface_set.js
+++ b/o3d/samples/o3d-webgl/render_surface_set.js
@@ -36,8 +36,8 @@
* from the given RenderSurfaceSet node will operate on the contents of
* the bound depth and color buffers.
* Note the following usage constraints of this node:
- * 1) If both a color and depth surface is bound, then they must be of matching
- * dimensions.
+ * 1) If both a color and depth surface is bound, then they must be of
+ * matching dimensions.
* 2) At least one of render_surface and render_depth_surface must non-null.
*
* @param {o3d.RenderSurface} opt_renderSurface The render surface to set.
@@ -45,7 +45,9 @@
* depth stencil render surface to set.
* @constructor
*/
-o3d.RenderSurfaceSet = function() {
+o3d.RenderSurfaceSet =
+ function(opt_renderSurface, opt_renderDepthStencilSurface) {
+ o3d.RenderNode.call(this);
o3d.RenderSurfaceSet.prototype.renderSurface =
opt_renderSurface;
o3d.RenderSurfaceSet.prototype.renderDepthStencilSurface =
@@ -62,7 +64,6 @@ o3d.inherit('RenderSurfaceSet', 'RenderNode');
o3d.RenderSurfaceSet.prototype.renderSurface = null;
-
/**
* The render depth stencil surface to which the depth contents of all
* RenderNode children should be drawn.
@@ -70,5 +71,95 @@ o3d.RenderSurfaceSet.prototype.renderSurface = null;
*/
o3d.RenderSurfaceSet.prototype.renderDepthStencilSurface = null;
+/**
+ * Helper function to set the framebuffer back to the default one.
+ * @private
+ */
+o3d.RenderSurfaceSet.prototype.clearFramebufferObjects_ =
+ function() {
+ this.gl.bindFramebuffer(
+ this.gl.FRAMEBUFFER, this.renderSurface.framebuffer_);
+
+ this.gl.framebufferRenderbuffer(
+ this.gl.FRAMEBUFFER,
+ this.gl.COLOR_ATTACHMENT0,
+ this.gl.RENDERBUFFER,
+ 0);
+
+ this.gl.framebufferRenderbuffer(
+ this.gl.FRAMEBUFFER,
+ this.gl.DEPTH_STENCIL_ATTACHMENT,
+ this.gl.RENDERBUFFER,
+ 0);
+
+ this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, 0);
+};
+
+
+/**
+ * Helper function to set up both the color and depth-stencil targets.
+ * @private
+ */
+o3d.RenderSurfaceSet.prototype.installFramebufferObjects_ =
+ function() {
+ // Reset the bound attachments to the current framebuffer object.
+ this.clearFramebufferObjects_();
+
+ this.gl.bindFramebuffer(
+ this.gl.FRAMEBUFFER, this.renderSurface.framebuffer_);
+
+ if (this.renderSurface) {
+ var texture = this.renderSurface.texture.texture_;
+ var level = this.renderSurface.level;
+
+ // TODO(petersont): If it's a cube, this call should be different.
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
+ this.gl.framebufferTexture2D(
+ this.gl.FRAMEBUFFER,
+ this.gl.COLOR_ATTACHMENT0,
+ this.gl.TEXTURE_2D,
+ texture,
+ level);
+ }
+
+ if (this.renderDepthStencilSurface) {
+ var depth_stencil_buffer =
+ this.renderDepthStencilSurface.depth_stencil_buffer_;
+
+ // TODO(petersont): In the WebGL spec, there is a depth-stencil
+ // attachment, but it hasn't been implemented yet, once it is,
+ // this should use one of those.
+ this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, depth_stencil_buffer);
+ this.gl.framebufferRenderbuffer(
+ this.gl.FRAMEBUFFER,
+ this.gl.DEPTH_ATTACHMENT,
+ this.gl.RENDERBUFFER,
+ depth_stencil_buffer);
+ }
+};
+
+
+/**
+ * Called during the rendergraph traversal before the children are rendered.
+ * @private
+ */
+o3d.RenderSurfaceSet.prototype.before = function() {
+ this.installFramebufferObjects_();
+ this.previousHeight = this.gl.displayInfo.height;
+ this.previousWidth = this.gl.displayInfo.width;
+ this.gl.displayInfo.height = this.renderSurface.height;
+ this.gl.displayInfo.width = this.renderSurface.width;
+};
+
+
+/**
+ * Called during the rendergraph traversal after the children are rendered.
+ * @private
+ */
+o3d.RenderSurfaceSet.prototype.after = function() {
+ this.clearFramebufferObjects_();
+ this.gl.displayInfo.height = this.previousHeight;
+ this.gl.displayInfo.width = this.previousWidth;
+};
diff --git a/o3d/samples/o3d-webgl/sampler.js b/o3d/samples/o3d-webgl/sampler.js
new file mode 100644
index 0000000..1748d83
--- /dev/null
+++ b/o3d/samples/o3d-webgl/sampler.js
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+/**
+ * Sampler is the base of all texture samplers. Texture samplers encapsulate
+ * a texture reference with a set of states that define how the texture
+ * gets applied to a surface. Sampler states are set either via Params defined
+ * on the Sampler object or directly via one the convenience methods defined
+ * on the Sampler. The following states are supported (default values are in
+ * parenthesis):
+ * \li 'addressModeU' (WRAP)
+ * \li 'addressModeV' (WRAP)
+ * \li 'addressModeW' (WRAP)
+ * \li 'magFilter' (LINEAR)
+ * \li 'minFilter' (LINEAR)
+ * \li 'mipFilter' (POINT)
+ * \li 'borderColor' ([0,0,0,0])
+ * \li 'maxAnisotropy' (1)
+ */
+o3d.Sampler = function() {
+ o3d.ParamObject.call(this);
+ this.borderColor = [0, 0, 0, 0];
+};
+o3d.inherit('Sampler', 'ParamObject');
+
+
+
+/**
+ * @type {number}
+ */
+o3d.Sampler.AddressMode = goog.typedef;
+
+
+/**
+ * AddressMode,
+ * Controls what happens with texture coordinates outside the [0..1] range.
+ * WRAP
+ * MIRROR
+ * CLAMP
+ * BORDER
+ */
+o3d.Sampler.WRAP = 0;
+o3d.Sampler.MIRROR = 1;
+o3d.Sampler.CLAMP = 2;
+o3d.Sampler.BORDER = 3;
+
+
+/**
+ * @type {number}
+ */
+o3d.Sampler.FilterType = goog.typedef;
+
+/**
+ * FilterType,
+ * Texture filtering types.
+ * NONE
+ * POINT
+ * LINEAR
+ * ANISOTROPIC
+ */
+o3d.Sampler.NONE = 0;
+o3d.Sampler.POINT = 1;
+o3d.Sampler.LINEAR = 2;
+o3d.Sampler.ANISOTROPIC = 3;
+
+
+/**
+ * The texture address mode for the u coordinate.
+ * @type {!o3d.Sampler.AddressMode}
+ */
+o3d.Sampler.prototype.addressModeU = o3d.Sampler.WRAP;
+
+
+
+/**
+ * The texture address mode for the v coordinate.
+ * @type {!o3d.Sampler.AddressMode}
+ */
+o3d.Sampler.prototype.addressModeV = o3d.Sampler.WRAP;
+
+
+
+/**
+ * The texture address mode for the w coordinate.
+ * @type {!o3d.Sampler.AddressMode}
+ */
+o3d.Sampler.prototype.addressModeW = o3d.Sampler.WRAP;
+
+
+
+/**
+ * The magnification filter. Valid values for the mag filter are: POINT and
+ * @type {!o3d.Sampler.FilterType}
+ */
+o3d.Sampler.prototype.magFilter = o3d.Sampler.LINEAR;
+
+
+
+/**
+ * The minification filter. Valid values for the min filter are: POINT, LINEAR
+ * and ANISOTROPIC.
+ * @type {!o3d.Sampler.FilterType}
+ */
+o3d.Sampler.prototype.minFilter = o3d.Sampler.LINEAR;
+
+
+
+/**
+ * The mipmap filter used during minification. Valid values for the mip filter
+ * are: NONE, POINT and LINEAR.
+ * @type {!o3d.Sampler.FilterType}
+ */
+o3d.Sampler.prototype.mipFilter = o3d.Sampler.LINEAR;
+
+
+
+/**
+ * Color returned for texture coordinates outside the [0,1] range when the
+ * address mode is set to BORDER.
+ * @type {!Array.<number>}
+ */
+o3d.Sampler.prototype.borderColor = [0, 0, 0, 0];
+
+
+
+/**
+ * Degree of anisotropy used when the ANISOTROPIC filter type is used.
+ * @type {number}
+ */
+o3d.Sampler.prototype.maxAnisotropy = 1;
+
+
+
+/**
+ * The Texture object used by this Sampler.
+ * @type {o3d.Texture}
+ */
+o3d.Sampler.prototype.texture = null;
+
+
+
diff --git a/o3d/samples/o3d-webgl/shape.js b/o3d/samples/o3d-webgl/shape.js
index 4754869..ab47b2f 100644
--- a/o3d/samples/o3d-webgl/shape.js
+++ b/o3d/samples/o3d-webgl/shape.js
@@ -37,6 +37,7 @@
* @constructor
*/
o3d.Shape = function() {
+ o3d.ParamObject.call(this);
this.elements = [];
};
o3d.inherit('Shape', 'ParamObject');
@@ -72,7 +73,10 @@ o3d.Shape.prototype.elements = [];
*/
o3d.Shape.prototype.createDrawElements =
function(pack, material) {
- o3d.notImplemented();
+ var elements = this.elements;
+ for (var i = 0; i < elements.length; ++i) {
+ elements[i].createDrawElement(pack, material);
+ }
};
diff --git a/o3d/samples/o3d-webgl/state_set.js b/o3d/samples/o3d-webgl/state_set.js
index 8fe1881..054b5a8 100644
--- a/o3d/samples/o3d-webgl/state_set.js
+++ b/o3d/samples/o3d-webgl/state_set.js
@@ -39,7 +39,7 @@
* @constructor
*/
o3d.StateSet = function(opt_state) {
- o3d.ParamObject.call(this);
+ o3d.RenderNode.call(this);
this.state = opt_state || null;
};
o3d.inherit('StateSet', 'RenderNode');
diff --git a/o3d/samples/o3d-webgl/stream.js b/o3d/samples/o3d-webgl/stream.js
index 0a3cf19..6a96aa1 100644
--- a/o3d/samples/o3d-webgl/stream.js
+++ b/o3d/samples/o3d-webgl/stream.js
@@ -35,6 +35,7 @@
* @constructor
*/
o3d.Stream = function(semantic, semantic_index, field, start_index) {
+ o3d.NamedObject.call(this);
this.semantic = semantic;
this.semanticIndex = semantic_index;
this.field = field;
diff --git a/o3d/samples/o3d-webgl/stream_bank.js b/o3d/samples/o3d-webgl/stream_bank.js
index b6c032a..8329709 100644
--- a/o3d/samples/o3d-webgl/stream_bank.js
+++ b/o3d/samples/o3d-webgl/stream_bank.js
@@ -35,6 +35,7 @@
* @constructor
*/
o3d.StreamBank = function() {
+ o3d.NamedObject.call(this);
this.vertexStreams = [];
};
o3d.inherit('StreamBank', 'NamedObject');
@@ -53,7 +54,7 @@ o3d.StreamBank.prototype.vertexStreams = [];
* @param {number} semantic_index Which index of a particular semantic to use.
* @param {o3d.Field} field The field containing information for this stream.
* @param {number} start_index The first element to use.
- * @returns {boolean} True if successful.
+ * @return {boolean} True if successful.
*/
o3d.StreamBank.prototype.setVertexStream =
function(semantic, semantic_index, field, start_index) {
@@ -71,7 +72,7 @@ o3d.StreamBank.prototype.setVertexStream =
* @param {o3d.Stream.Semantic} semantic The particular use of this stream.
* @param {o3d.Stream.Semantic} semantic_index Which index of a particular
* semantic to use.
- * @returns {o3d.Stream} The found stream or null if it does not exist.
+ * @return {o3d.Stream} The found stream or null if it does not exist.
*/
o3d.StreamBank.prototype.getVertexStream =
function(semantic, semantic_index) {
@@ -87,7 +88,7 @@ o3d.StreamBank.prototype.getVertexStream =
* @param {o3d.Stream.Semantic} semantic The particular use of this stream.
* @param {o3d.Stream.Semantic} semantic_index Which index of a particular
* semantic to use.
- * @returns {boolean} true if the specified stream existed.
+ * @return {boolean} true if the specified stream existed.
*/
o3d.StreamBank.prototype.removeVertexStream =
function(semantic, semantic_index) {
diff --git a/o3d/samples/o3d-webgl/texture.js b/o3d/samples/o3d-webgl/texture.js
index 767e608..7c5367b 100644
--- a/o3d/samples/o3d-webgl/texture.js
+++ b/o3d/samples/o3d-webgl/texture.js
@@ -105,7 +105,7 @@ o3d.Texture.prototype.format = o3d.Texture.UNKNOWN_FORMAT;
/**
* The number of mipmap levels used by the texture.
- * type {number}
+ * @type {number}
*/
o3d.Texture.prototype.levels = 1;
@@ -113,11 +113,18 @@ o3d.Texture.prototype.levels = 1;
/**
* True if all the alpha values in the texture are 1.0
- * type {boolean}
+ * @type {boolean}
*/
o3d.Texture.prototype.alphaIsOne = true;
+/**
+ * The the associated gl texture.
+ * @type {WebGLTexture}
+ * @private
+ */
+o3d.Texture.prototype.texture_ = null;
+
/**
* Generates Mips.
@@ -126,7 +133,8 @@ o3d.Texture.prototype.alphaIsOne = true;
*/
o3d.Texture.prototype.generateMips =
function(source_level, num_levels) {
- o3d.notImplemented();
+ this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture_);
+ this.gl.generateMipmap(this.gl.TEXTURE_2D);
};
@@ -138,9 +146,16 @@ o3d.Texture.prototype.generateMips =
* @param {number} opt_height The height of this texture in pixels.
* @constructor
*/
-o3d.Texture2D = function() {
+o3d.Texture2D = function(opt_width, opt_height) {
+ o3d.Texture.call(this);
this.width = opt_width || 0;
this.height = opt_height || 0;
+
+ /**
+ * The cache of rendersurface objects.
+ * @private
+ */
+ this.renderSurfaces_ = [];
};
o3d.inherit('Texture2D', 'Texture');
@@ -160,18 +175,22 @@ o3d.Texture2D.prototype.width = 0;
o3d.Texture2D.prototype.height = 0;
-
/**
* Returns a RenderSurface object associated with a mip_level of a texture.
*
* @param {number} mip_level The mip-level of the surface to be returned.
- * @param {number} opt_pack pack This parameter is no longer used.
- * The surface exists as long as the texture it came from exists.
- * @returns {o3d.RenderSurface} The RenderSurface object.
+ * @return {o3d.RenderSurface} The RenderSurface object.
*/
o3d.Texture2D.prototype.getRenderSurface =
- function(mip_level, opt_pack) {
- o3d.notImplemented();
+ function(mip_level) {
+ if (!this.renderSurfaces_[mip_level]) {
+ var renderSurface = new o3d.RenderSurface();
+ renderSurface.gl = this.gl;
+ renderSurface.initWithTexture(this, mip_level);
+ this.renderSurfaces_[mip_level] = renderSurface;
+ }
+
+ return this.renderSurfaces_[mip_level];
};
@@ -244,7 +263,7 @@ o3d.Texture2D.prototype.setRect =
* @param {number} y The y coordinate of the area in the texture to retrieve.
* @param {number} width The width of the area to retrieve.
* @param {number} height The height of the area to retrieve.
- * @returns {number} Array of pixel values.
+ * @return {number} Array of pixel values.
*/
o3d.Texture2D.prototype.getRect =
function(level, x, y, width, height) {
@@ -260,7 +279,24 @@ o3d.Texture2D.prototype.getRect =
*/
o3d.Texture2D.prototype.setFromBitmap =
function(bitmap) {
- o3d.notImplemented();
+ this.gl.bindTexture(this.gl.TEXTURE_2D, this.texture_);
+ this.gl.texImage2D(this.gl.TEXTURE_2D,
+ 0, // Level.
+ bitmap.canvas_,
+ bitmap.defer_flip_verically_to_texture_);
+
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
+ this.gl.texParameteri(this.gl.TEXTURE_2D,
+ this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
+
+ if (bitmap.defer_mipmaps_to_texture_) {
+ this.generateMips();
+ }
};
@@ -301,7 +337,9 @@ o3d.Texture2D.prototype.drawImage =
* @param {number} edgeLength The length of any edge of this texture
* @constructor
*/
-o3d.TextureCUBE = function() { };
+o3d.TextureCUBE = function() {
+ o3d.Texture.call(this);
+};
o3d.inherit('TextureCUBE', 'Texture');
@@ -346,7 +384,7 @@ o3d.TextureCUBE.prototype.edge_length = 0;
* @param {o3d.Pack} pack This parameter is no longer used. The surface exists
* as long as the texture it came from exists.
* @param {number} mip_level The mip-level of the surface to be returned.
- * @returns {o3d.RenderSurface} The RenderSurface object.
+ * @return {o3d.RenderSurface} The RenderSurface object.
*/
o3d.TextureCUBE.prototype.getRenderSurface =
function(face, mip_level, opt_pack) {
@@ -410,7 +448,7 @@ o3d.TextureCUBE.prototype.setRect =
* @param {number} y The y coordinate of the area in the texture to retrieve.
* @param {number} width The width of the area to retrieve.
* @param {number} height The height of the area to retrieve.
- * @returns {number} Array of pixel values.
+ * @return {number} Array of pixel values.
*/
o3d.TextureCUBE.prototype.getRect =
function(face, level, x, y, width, height) {
diff --git a/o3d/samples/o3d-webgl/transform.js b/o3d/samples/o3d-webgl/transform.js
index 2ef5d21..ff72076 100644
--- a/o3d/samples/o3d-webgl/transform.js
+++ b/o3d/samples/o3d-webgl/transform.js
@@ -51,6 +51,7 @@
o3d.Transform =
function(opt_localMatrix, opt_worldMatrix, opt_visible, opt_boundingBox,
opt_cull) {
+ o3d.ParamObject.call(this);
this.localMatrix = opt_localMatrix ||
[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]];
this.worldMatrix = opt_worldMatrix ||
@@ -149,7 +150,7 @@ o3d.Transform.prototype.getTransformsInTree =
* will affect them.
*
* @param {string} name Transform name to look for.
- * @returns {Array.<o3d.Transform>} An array containing the transforms of the
+ * @return {Array.<o3d.Transform>} An array containing the transforms of the
* under and including this transform matching the given name.
*/
o3d.Transform.prototype.getTransformsByNameInTree =
@@ -182,12 +183,12 @@ o3d.Transform.prototype.addShape =
/**
* Removes a shape from this transform.
* @param {o3d.Shape} shape Shape to remove.
- * @returns {boolean} true if successful, false if shape was not in
+ * @return {boolean} true if successful, false if shape was not in
* this transform.
*/
o3d.Transform.prototype.removeShape =
function(shape) {
-
+ o3d.notImplemented();
};
@@ -211,6 +212,7 @@ o3d.Transform.prototype.shapes = [];
+
/**
* Walks the tree of transforms starting with this transform and creates
* draw elements. If an Element already has a DrawElement that uses material a
@@ -353,7 +355,7 @@ o3d.Transform.compose = function(a, b, opt_target) {
*
* @param {!Array.<!Array.<number>>} a A matrix.
* @param {!Array.<!Array.<number>>} b Another matrix.
- * @returns {boolean} Whether they are equal.
+ * @return {boolean} Whether they are equal.
*/
o3d.Transform.matricesEqual = function(a, b) {
if (a==b) {
@@ -416,7 +418,7 @@ o3d.Transform.transpose = function(m, opt_target) {
* inverse of a.
*/
o3d.Transform.inverse = function(m, opt_target) {
- var t = opt_target || a;
+ var t = opt_target || m;
var m0 = m[0];
var m1 = m[1];
var m2 = m[2];
@@ -897,7 +899,7 @@ o3d.Transform.prototype.scale =
* Utility function to flatten an o3djs-style matrix
* (which is an array of arrays) into one array of entries.
* @param {Array.<Array.<number> >} m The o3djs-style matrix.
- * @returns {Array.<number>} The flattened matrix.
+ * @return {Array.<number>} The flattened matrix.
*/
o3d.Transform.flattenMatrix4 = function(m) {
var m0 = m[0];
diff --git a/o3d/samples/o3d-webgl/tree_traversal.js b/o3d/samples/o3d-webgl/tree_traversal.js
index 5a5dbb6..c92f601 100644
--- a/o3d/samples/o3d-webgl/tree_traversal.js
+++ b/o3d/samples/o3d-webgl/tree_traversal.js
@@ -42,8 +42,9 @@
* @constructor
*/
o3d.TreeTraversal = function(opt_transform) {
+ o3d.RenderNode.call(this);
this.transform = opt_transform;
- this.drawLists = [];
+ this.drawLists_ = [];
this.drawListsToReset_ = [];
};
o3d.inherit('TreeTraversal', 'RenderNode');
@@ -90,7 +91,7 @@ o3d.TreeTraversal.prototype.registerDrawList =
/**
* Unregisters a DrawList with this TreeTraversal.
* @param {o3d.DrawList} draw_list DrawList to unregister.
- * @returns {boolean} true if unregistered. false if this draw_list was
+ * @return {boolean} true if unregistered. false if this draw_list was
* not registered.
*/
o3d.TreeTraversal.prototype.unregisterDrawList =
diff --git a/o3d/samples/o3d-webgl/viewport.js b/o3d/samples/o3d-webgl/viewport.js
index 6c082c0..70e1386 100644
--- a/o3d/samples/o3d-webgl/viewport.js
+++ b/o3d/samples/o3d-webgl/viewport.js
@@ -44,6 +44,7 @@
* @constructor
*/
o3d.Viewport = function(opt_viewport, opt_depthRange) {
+ o3d.RenderNode.call(this);
this.viewport = opt_viewport || [0.0, 0.0, 1.0, 1.0];
this.depthRange = opt_depthRange || [0.0, 1.0];
};
@@ -66,7 +67,6 @@ o3d.inherit('Viewport', 'RenderNode');
o3d.Viewport.prototype.viewport = [0.0, 0.0, 1.0, 1.0];
-
/**
* The min Z and max Z depth range in [min Z, max Z] format.
* Default = [0.0, 1.0].
@@ -81,16 +81,17 @@ o3d.Viewport.prototype.depthRange = [0.0, 1.0];
* scissor region in gl.
*/
o3d.Viewport.prototype.before = function() {
- var x = this.viewport[0] * this.gl.canvas.width;
- var y = this.viewport[1] * this.gl.canvas.height;
- var width = this.viewport[2] * this.gl.canvas.width;
- var height = this.viewport[3] * this.gl.canvas.height;
+ var x = this.viewport[0] * this.gl.displayInfo.width;
+ var y = this.viewport[1] * this.gl.displayInfo.height;
+ var width = this.viewport[2] * this.gl.displayInfo.width;
+ var height = this.viewport[3] * this.gl.displayInfo.height;
+
this.gl.viewport(x, y, width, height);
if (x != 0 || y != 0 || this.viewport[2] != 1 || this.viewport[3] != 1) {
this.gl.enable(this.gl.SCISSOR_TEST);
this.gl.scissor(x, y, width, height);
} else {
-
+ this.gl.disable(this.gl.SCISSOR_TEST);
}
};
diff --git a/o3d/samples/o3djs/webgl.js b/o3d/samples/o3djs/webgl.js
index 6940660..1bbe168 100644
--- a/o3d/samples/o3djs/webgl.js
+++ b/o3d/samples/o3djs/webgl.js
@@ -82,31 +82,70 @@ o3djs.webgl.makeClients = function(callback,
/**
+ * Adds a wrapper object to single gl function context that checks for errors
+ * before the call.
+ * @param {WebGLContext} context
+ * @param {string} fname The name of the function.
+ * @return {}
+ */
+o3djs.webgl.createGLErrorWrapper = function(context, fname) {
+ return function() {
+ var rv = context[fname].apply(context, arguments);
+ var err = context.getError();
+ if (err != 0)
+ throw "GL error " + err + " in " + fname;
+ return rv;
+ };
+};
+
+/**
+ * Adds a wrapper object to a webgl context that checks for errors
+ * before each function call.
+ */
+o3djs.webgl.addDebuggingWrapper = function(context) {
+ // Thanks to Ilmari Heikkinen for the idea on how to implement this
+ // so elegantly.
+ var wrap = {};
+ for (var i in context) {
+ if (typeof context[i] == 'function') {
+ wrap[i] = createGLErrorWrapper(context, i);
+ } else {
+ wrap[i] = context[i];
+ }
+ }
+ wrap.getError = function() {
+ return context.getError();
+ };
+ return wrap;
+};
+
+
+/**
* Creates a canvas under the given parent element and an o3d.Client
* under that.
+ *
+ * @ param {!Element} element The element under which to insert the client.
+ * @ param {string} opt_features Features to turn on.
+ * @ param {boolean} opt_debug Whether gl debugging features should be
+ * enabled.
*/
-o3djs.webgl.createClient = function(element, opt_features) {
+o3djs.webgl.createClient = function(element, opt_features, opt_debug) {
opt_features = opt_features || '';
+ opt_debug = opt_debug || false;
- // TODO(petersont): Not sure what to do with the features object.
var canvas;
canvas = document.createElement('canvas');
canvas.setAttribute('width', element.getAttribute('width'));
canvas.setAttribute('height', element.getAttribute('height'));
+
canvas.client = new o3d.Client;
+ canvas.client.initWithCanvas(canvas);
canvas.o3d = o3d;
- var gl;
- try {gl = canvas.getContext("experimental-webgl") } catch(e) { }
- if (!gl)
- try {gl = canvas.getContext("moz-webgl") } catch(e) { }
- if (!gl) {
- alert("No WebGL context found");
- return null;
+ if (opt_debug) {
+ client.gl = o3djs.webgl.addDebuggingWrapper(client.gl);
}
- canvas.client.gl = gl;
-
element.appendChild(canvas);
return canvas;
};
diff --git a/o3d/samples/primitives.html b/o3d/samples/primitives.html
index e61cdae..27763d1 100644
--- a/o3d/samples/primitives.html
+++ b/o3d/samples/primitives.html
@@ -155,7 +155,7 @@ function createShapes() {
createMaterial([1,0,0,1]),
1.0, // Radius of the sphere.
30, // Number of meridians.
- 20); // Number of parallels.
+ 20); // Number of parallels.
var cylinder = o3djs.primitives.createCylinder(
g_pack,