summaryrefslogtreecommitdiffstats
path: root/o3d/samples/hellocube-textures.html
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/samples/hellocube-textures.html')
-rw-r--r--o3d/samples/hellocube-textures.html445
1 files changed, 445 insertions, 0 deletions
diff --git a/o3d/samples/hellocube-textures.html b/o3d/samples/hellocube-textures.html
new file mode 100644
index 0000000..16522b2
--- /dev/null
+++ b/o3d/samples/hellocube-textures.html
@@ -0,0 +1,445 @@
+<!--
+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="o3djs/base.js"></script>
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+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.util.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.
+ var path = window.location.href;
+ var index = path.lastIndexOf('/');
+ path = path.substring(0, index+1) + '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 shaderString = document.getElementById('effect').value;
+ cubeEffect.loadFromFXString(shaderString);
+
+ // 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" style="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="effect">
+ // World View Projection matrix that will transform the input vertices
+ // to screen space.
+ float4x4 worldViewProjection : WorldViewProjection;
+
+ // The texture sampler is used to access the texture bitmap in the fragment
+ // shader.
+ sampler texSampler0;
+
+ // input parameters for our vertex shader
+ struct VertexShaderInput {
+ float4 position : POSITION;
+ float2 tex : TEXCOORD0; // Texture coordinates
+ };
+
+ // input parameters for our pixel shader
+ struct PixelShaderInput {
+ float4 position : POSITION;
+ float2 tex : TEXCOORD0; // Texture coordinates
+ };
+
+ /**
+ * The vertex shader simply transforms the input vertices to screen space.
+ */
+ PixelShaderInput vertexShaderFunction(VertexShaderInput input) {
+ PixelShaderInput output;
+
+ // Multiply the vertex positions by the worldViewProjection matrix to
+ // transform them to screen space.
+ output.position = mul(input.position, worldViewProjection);
+
+ output.tex = input.tex;
+ return output;
+ }
+
+ /**
+ * Given the texture coordinates, our pixel shader grabs the corresponding
+ * color from the texture.
+ */
+ float4 pixelShaderFunction(PixelShaderInput input): COLOR {
+ return tex2D(texSampler0, input.tex);
+ }
+
+ // Here we tell our effect file *which* functions are
+ // our vertex and pixel shaders.
+
+ // #o3d VertexShaderEntryPoint vertexShaderFunction
+ // #o3d PixelShaderEntryPoint pixelShaderFunction
+ // #o3d MatrixLoadOrder RowMajor
+</textarea>
+<!-- End of effect -->
+</div>
+</body>
+</html>