summaryrefslogtreecommitdiffstats
path: root/o3d/samples/stencil_example.html
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/samples/stencil_example.html')
-rw-r--r--o3d/samples/stencil_example.html439
1 files changed, 439 insertions, 0 deletions
diff --git a/o3d/samples/stencil_example.html b/o3d/samples/stencil_example.html
new file mode 100644
index 0000000..824f76a
--- /dev/null
+++ b/o3d/samples/stencil_example.html
@@ -0,0 +1,439 @@
+<!--
+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.
+-->
+
+<!--
+O3D Stencil Example
+
+In this example I load 9 scene files. One file contains 3 rings and 3 circles.
+I find the circles and draw them into the stencil buffer with different Ids.
+The rings and the circles are drawn with an orthographic camera. The circles
+are manually added to a separate DrawList used by a separate DrawPass so that
+they get drawn last. Then I load 4 scenes, the teapot, torus, pyramid and pipe
+and for each one a skydome. I set a state on each of those so they will get
+masked by the stencils and for each pair I give them a different
+drawContext(viewand projection matrix)
+
+The result is 4 separate 3d scenes on the same screen with irregular shaped
+"windows" into them.
+-->
+<!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>
+Stencil Example
+</title>
+<!-- Include sample javascript library functions -->
+<script type="text/javascript" src="o3djs/base.js"></script>
+
+<!-- Our javascript code -->
+<script type="text/javascript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.pack');
+o3djs.require('o3djs.camera');
+o3djs.require('o3djs.material');
+o3djs.require('o3djs.scene');
+
+// Events
+// init() once the page has finished loading.
+// unload() when the page is unloaded.
+window.onload = init;
+window.onunload = unload;
+
+// global variables
+var g_o3d;
+var g_math;
+var g_client;
+var g_viewInfo;
+var g_stencilPack;
+var g_stencilRoot;
+var g_treeTraversal;
+var g_scenePack = new Array();
+var g_o3dWidth; // width of our client area
+var g_o3dHeight; // height of our client area
+var g_sceneStates = new Array(); // States of stuff inside the stencils
+var G_NUM_SCENES = 4;
+var g_clock = 0;
+var g_timeMult = 1
+var g_finished = false; // for selenium testing
+
+var g_locators = new Array(); // the locator for each shape
+
+/**
+ * Loads a scene into the transform graph.
+ * @param {!o3d.Pack} pack Pack to load scene into.
+ * @param {string} fileName filename of the scene.
+ * @param {!o3d.Transform} parent parent node in the transform graph to
+ * which to load the scene into.
+ * @param {function(!o3d.Pack, !o3d.Transform, boolean): void} callback Function
+ * to call when scene loads.
+ */
+function loadScene(pack, fileName, parent, callback) {
+ // Get our full path to the scene
+ var scenePath = o3djs.util.getCurrentURI() + fileName;
+
+ // Load the scene given the full path, and call the callback function
+ // when its done loading.
+ o3djs.scene.loadScene(g_client, pack, parent, scenePath, callback);
+}
+
+function onrender(renderEvent) {
+ var elapsedTime = renderEvent.elapsedTime;
+
+ g_clock += elapsedTime * g_timeMult;
+
+ for (var ii = 0; ii < g_locators.length; ii++) {
+ var locator = g_locators[ii];
+ var rotation =
+ g_math.matrix4.rotationX(Math.sin(g_clock * (ii + 1)) * 0.5);
+ var translation = g_math.matrix4.getTranslation(locator.localMatrix);
+
+ locator.localMatrix =
+ g_math.matrix4.setTranslation(rotation, translation);
+ }
+
+ var rotation = g_math.matrix4.rotationZ(g_clock);
+ var translation = g_stencilRoot.localMatrix[3];
+
+ g_stencilRoot.localMatrix =
+ g_math.matrix4.setTranslation(rotation, translation);
+}
+
+/**
+ * Creates the client area.
+ */
+function init() {
+ o3djs.util.makeClients(initStep2);
+}
+
+/**
+ * Initializes O3D and loads the scenes.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function initStep2(clientElements) {
+ // Initialize global variables and libraries.
+ var o3dElement = clientElements[0];
+ g_o3d = o3dElement.o3d;
+ g_math = o3djs.math;
+ g_client = o3dElement.client;
+
+ // Creates packs to manage our resources/assets
+ g_stencilPack = g_client.createPack();
+
+ // Create the render graph for a view.
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_stencilPack,
+ g_client.root,
+ g_client.renderGraphRoot);
+
+ // Get the tree traversal so we can register more DrawLists.
+ g_treeTraversal = g_viewInfo.treeTraversal;
+
+ // Get the width and height of our client area. We will need this to create
+ // a projection matrix.
+ g_o3dWidth = g_client.width;
+ g_o3dHeight = g_client.height;
+
+ // Set clear color to blue
+ g_viewInfo.clearBuffer.clearColor = [0.1, 0.1, 1.0, 1.0];
+
+ // Creates transforms to put our data on.
+ g_stencilRoot = g_stencilPack.createObject('Transform');
+ // Connects our roots to the client's root.
+ g_stencilRoot.parent = g_client.root;
+
+ var mySceneRoot = new Array();
+ var myLocalDrawPass = new Array();
+ for (var mm = 0; mm < G_NUM_SCENES; mm++) {
+ g_scenePack[mm] = g_client.createPack();
+ mySceneRoot[mm] = g_scenePack[mm].createObject('Transform');
+ mySceneRoot[mm].parent = g_client.root;
+ var localDrawList = g_scenePack[mm].createObject('DrawList');
+ var localDrawPass = g_stencilPack.createObject('DrawPass');
+ var localStateSet = g_stencilPack.createObject('StateSet');
+ var localState = g_stencilPack.createObject('State');
+ localStateSet.priority = 4;
+ localStateSet.state = localState;
+ // make a state that passes only for a particular stencil value
+ localState.getStateParam('StencilEnable').value = true;
+ localState.getStateParam('StencilReference').value = mm;
+ localState.getStateParam('StencilComparisonFunction').value =
+ g_o3d.State.CMP_EQUAL;
+ localStateSet.parent = g_viewInfo.viewport;
+ localDrawPass.drawList = localDrawList;
+ localDrawPass.parent = localStateSet;
+ myLocalDrawPass[mm] = localDrawPass;
+ }
+
+ // Load the scene into the transform graph as a child my_data_root
+ loadScene(g_stencilPack, 'assets/stencil_frame.o3dtgz', g_stencilRoot,
+ setupStencilsAndOverlay);
+
+ /**
+ * Our callback is called once the scene has been loaded into memory
+ * from the web or locally.
+ */
+ function setupStencilsAndOverlay() {
+ // Get a cameraInfo (a view and projection matrix)
+ // using our javascript library function
+ var cameraInfo = o3djs.camera.getViewAndProjectionFromCameras(
+ g_stencilRoot,
+ g_o3dWidth,
+ g_o3dHeight);
+
+ var backDrawContext = g_stencilPack.createObject('DrawContext');
+ backDrawContext.view = cameraInfo.view;
+ backDrawContext.projection = cameraInfo.projection;
+
+ // create 2 DrawPasses that uses this context to draw things as in the
+ // stencil_frame.o3dtgz file which I already setup with an orthographic
+ // projection matrix. Each one needs a draw list as well. Also create a
+ // StateSet to set the stencil render states for everything drawn
+ // by the back DrawPass.
+
+ // first one to draw the 3 circles into the stencil.
+ var backDrawList = g_stencilPack.createObject('DrawList');
+ var backDrawPass = g_stencilPack.createObject('DrawPass');
+ var backStateSet = g_stencilPack.createObject('StateSet');
+ var backState = g_stencilPack.createObject('State');
+ backDrawPass.parent = backStateSet;
+ backDrawPass.drawList = backDrawList;
+ // after tree_traversal, before opaque
+ backStateSet.priority = g_viewInfo.treeTraversal.priority + 0.5;
+ backStateSet.parent = g_viewInfo.viewport;
+ backStateSet.state = backState;
+ g_treeTraversal.registerDrawList(backDrawList, backDrawContext, true);
+ backState.getStateParam('StencilEnable').value = true;
+ backState.getStateParam('StencilPassOperation').value =
+ g_o3d.State.STENCIL_REPLACE;
+ backState.getStateParam('StencilComparisonFunction').value =
+ g_o3d.State.CMP_ALWAYS;
+ backState.getStateParam('ZEnable').value = false;
+ backState.getStateParam('ZWriteEnable').value = false;
+ backState.getStateParam('ColorWriteEnable').value = 0;
+
+ // Next one to draw the 3 rings in front of everything
+ var frontDrawList = g_stencilPack.createObject('DrawList');
+ var frontDrawPass = g_stencilPack.createObject('DrawPass');
+ frontDrawPass.drawList = frontDrawList;
+ frontDrawPass.priority = 9001; // after our special clear.
+ frontDrawPass.parent = g_viewInfo.viewport;
+ g_treeTraversal.registerDrawList(frontDrawList, backDrawContext, true);
+
+ // find all the pCylinder1 Transforms (the stencil discs)
+ var stencils = g_stencilRoot.getTransformsByNameInTree('pCylinder1');
+
+ // put each stencils at the beginning of the render graph
+ for (var ss = 0; ss < stencils.length; ss++) {
+ // there should be only one shape under each pCylinder1
+ var shape = stencils[ss].shapes[0];
+
+ // make a new material.
+ var material = g_stencilPack.createObject('Material');
+
+ // copy the old material's params.
+ material.copyParams(shape.elements[0].material);
+
+ // tell things drawn with this material to get drawn in the back draw
+ // list.
+ material.drawList = backDrawList;
+
+ // create DrawElements using this material.
+ shape.createDrawElements(g_stencilPack, material);
+
+ o3djs.material.attachStandardEffect(g_stencilPack,
+ material,
+ g_viewInfo,
+ 'phong');
+
+ // make state that renders into the stencil only
+ var state = g_stencilPack.createObject('State');
+ material.state = state;
+ state.getStateParam('StencilReference').value = ss + 1;
+ }
+
+ // clear the zbuffer before drawing the circles
+ var clearBuffer = g_stencilPack.createObject('ClearBuffer');
+ clearBuffer.clearColorFlag = false;
+ clearBuffer.clearStencilFlag = false;
+ clearBuffer.priority = 9000;
+ clearBuffer.parent = g_viewInfo.viewport;
+
+ // put each circle at the end of the render graph
+
+ // find all the pPipe? Transforms
+ var circles = o3djs.util.getTransformsInTreeByPrefix(g_stencilRoot,
+ 'pPipe');
+ for (var cc = 0; cc < circles.length; cc++) {
+ var transform = circles[cc];
+ // there should be only one shape under each pPipe
+ var shape = transform.shapes[0];
+ // there should be only one element in each shape.
+ var primitive = shape.elements[0];
+ // set it's material to draw in the front draw list.
+ primitive.material.drawList = frontDrawList;
+ o3djs.material.attachStandardEffect(g_stencilPack,
+ primitive.material,
+ g_viewInfo,
+ 'phong');
+
+ // generate draw elements for it.
+ shape.createDrawElements(g_stencilPack,
+ null);
+ }
+
+ loadScene(g_scenePack[0], 'assets/teapot.o3dtgz', mySceneRoot[0],
+ setupScene0);
+ }
+
+ function setupScene0() {
+ loadScene(g_scenePack[0], 'assets/dome1.o3dtgz', mySceneRoot[0],
+ setupDome0);
+ }
+
+ function setupDome0() {
+ // Stencil 0 is the center.
+ setupScene(g_scenePack[0], mySceneRoot[0], 0);
+ loadScene(g_scenePack[1], 'assets/part1.o3dtgz', mySceneRoot[1],
+ setupScene1);
+ }
+
+ function setupScene1() {
+ loadScene(g_scenePack[1], 'assets/dome2.o3dtgz', mySceneRoot[1],
+ setupDome1);
+ }
+
+ function setupDome1() {
+ // stencil 3 is the top left.
+ setupScene(g_scenePack[1], mySceneRoot[1], 3);
+ loadScene(g_scenePack[2], 'assets/part2.o3dtgz', mySceneRoot[2],
+ setupScene2);
+ }
+
+ function setupScene2() {
+ loadScene(g_scenePack[2], 'assets/dome3.o3dtgz', mySceneRoot[2],
+ setupDome2);
+ }
+
+ function setupDome2() {
+ // stencil 2 is the top right.
+ setupScene(g_scenePack[2], mySceneRoot[2], 2);
+ loadScene(g_scenePack[3], 'assets/part3.o3dtgz', mySceneRoot[3],
+ setupScene3);
+ }
+
+ function setupScene3() {
+ loadScene(g_scenePack[3], 'assets/dome4.o3dtgz', mySceneRoot[3],
+ setupDome3);
+ }
+
+ function setupDome3() {
+ // stencil 1 is the bottom.
+ setupScene(g_scenePack[3], mySceneRoot[3], 1);
+
+ g_client.setRenderCallback(onrender);
+ g_finished = true; // for selenium testing.
+ }
+
+ function setupScene(pack, root, stencil_id) {
+ // Get a cameraInfo (a Transform with a view and projection matrix)
+ // using our javascript library function
+ var cameraInfo = o3djs.camera.getViewAndProjectionFromCameras(
+ root,
+ g_o3dWidth,
+ g_o3dHeight);
+
+ // Create a new draw context and set it to use the camera from the scene
+ // we just loaded.
+ var sceneContext = pack.createObject('DrawContext');
+ sceneContext.view = cameraInfo.view;
+ sceneContext.projection = cameraInfo.projection;
+
+ g_treeTraversal.registerDrawList(myLocalDrawPass[stencil_id].drawList,
+ sceneContext,
+ true);
+
+ // save off the locators. Our shapes are parented to the so we can rotate
+ // them for animation
+ var locators = o3djs.util.getTransformsInTreeByPrefix(root,
+ 'locator');
+ g_locators[g_locators.length] = root;
+
+ // get all the shapes in the pack we just loaded.
+ var shapes = pack.getObjectsByClassName('o3d.Shape');
+ for (var ss = 0; ss < shapes.length; ss++) {
+ var shape = shapes[ss];
+ var elements = shape.elements;
+ for (var ee = 0; ee < elements.length; ++ee) {
+ var element = elements[ee];
+ element.material.drawList = myLocalDrawPass[stencil_id].drawList;
+ o3djs.material.attachStandardEffect(g_stencilPack,
+ element.material,
+ g_viewInfo,
+ 'phong');
+ }
+ }
+
+ root.createDrawElements(pack, null);
+ }
+}
+
+/**
+ * Removes any callbacks so they don't get called after the page has unloaded.
+ */
+function unload() {
+ if (g_client) {
+ g_client.cleanup();
+ }
+}
+</script>
+</head>
+<body>
+<h1>Stencil Example</h1>
+Shows 4 &quot;Views&quot; using 4 stencils, and 9 scene files.
+4 shapes, 4 skydomes, 1 frame drawn with an orthographic projection.
+<br/>
+<!-- Start of O3D plugin -->
+<!--
+NOTE: Because we are using cameras directly from the loaded scene and
+beacuse we are using an orthographic camera the dimensions of our client
+area must have the same aspect ratio as the original scene in Maya otherwise
+we will not get the same results.
+
+The original scene size was 1280x720
+-->
+<div id="o3d" style="width: 800px; height: 450px"></div>
+<!-- End of O3D plugin -->
+</body>
+</html>