diff options
Diffstat (limited to 'o3d/samples/scatter-chart.html')
-rw-r--r-- | o3d/samples/scatter-chart.html | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/o3d/samples/scatter-chart.html b/o3d/samples/scatter-chart.html new file mode 100644 index 0000000..d6d72527d --- /dev/null +++ b/o3d/samples/scatter-chart.html @@ -0,0 +1,426 @@ +<!-- +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. +--> + +<!-- +Scatter Chart Example + +This sample demonstrates how to plot a 3d scatter chart and how to rotate and zoom it +--> +<!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> +3D Scatter Chart +</title> +<script type="text/javascript" src="o3djs/base.js"></script> +<script type="text/javascript" src="assets/teapot_vertices.js"></script> + +<script type="text/javascript"> +o3djs.require('o3djs.util'); +o3djs.require('o3djs.math'); +o3djs.require('o3djs.quaternions'); +o3djs.require('o3djs.rendergraph'); +o3djs.require('o3djs.effect'); +o3djs.require('o3djs.primitives'); +o3djs.require('o3djs.arcball'); +o3djs.require('o3djs.event'); + +// 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_quaternions; +var g_pack; +var g_viewInfo; +var g_modelRoot; +var g_eyeView; +var g_cubeShape; +var g_material; +var g_aball; +var g_thisRot; +var g_lastRot; +var g_zoomFactor; +var g_dragging; +var g_finished = false; // for selenium testing. + +/** + * Creates the client area. + */ +function initClient() { + o3djs.util.makeClients(main); +} + +/** + * Initializes global variables, positions camera, draws the 3D chart. + * @param {Array} clientElements Array of o3d object elements. + */ +function main(clientElements) { + // Init global variables. + initGlobals(clientElements); + + // Set up the view and projection transformations. + initContext(); + + // Setup rendering on demand only. + g_client.renderMode = g_o3d.Client.RENDERMODE_ON_DEMAND; + + // Add the 3D chart model to the transform hierarchy. + create3dChartModel(); + + // Start rendering. + g_client.render(); + + // Execute keyPressed(..) when we detect a keypress on the window or + // on the o3d object. + window.document.onkeypress = keyPressed; + g_o3dElement.onkeypress = keyPressed; + + o3djs.event.addEventListener(g_o3dElement, 'mousedown', startDragging); + o3djs.event.addEventListener(g_o3dElement, 'mousemove', drag); + o3djs.event.addEventListener(g_o3dElement, 'mouseup', stopDragging); + o3djs.event.addEventListener(g_o3dElement, 'wheel', scrollMe); + + g_finished = true; // for selenium testing. +} + +/** + * Initializes global variables and libraries. + */ +function initGlobals(clientElements) { + // init o3d globals. + g_o3dElement = clientElements[0]; + g_client = g_o3dElement.client; + g_o3d = g_o3dElement.o3d; + g_math = o3djs.math; + g_quaternions = o3djs.quaternions; + + // Create an arcball. + g_aball = o3djs.arcball.create(g_o3dElement.clientWidth, + g_o3dElement.clientHeight); + + // Create a pack to manage the objects created. + g_pack = g_client.createPack(); + + // Create a transform node to act as the 'root' of the model. + // Attach it to the root of the transform graph. + g_modelRoot = g_pack.createObject('Transform'); + g_modelRoot.parent = g_client.root; + + // Create the render graph for the view. + var clearColor = [.98, .98, .98, 1]; + g_viewInfo = o3djs.rendergraph.createBasicView( + g_pack, + g_client.root, + g_client.renderGraphRoot, + clearColor); + + // Create a material for the objects rendered. + g_material = createPhongMaterial([1, 1, 1, 1]); + + // Create a cube shape to simulate the scatter points. + g_cubeShape = o3djs.primitives.createCube( + g_pack, + g_material, + 1); +} + +/** + * Initialize the original view of the model. + */ +function initContext() { + g_eyeView = [-35, 60, 140]; + g_zoomFactor = 1.03; + g_dragging = false; + g_modelRoot.identity(); + g_lastRot = g_math.matrix4.identity(); + g_thisRot = g_math.matrix4.identity(); + + // Set up a perspective transformation for the projection. + g_viewInfo.drawContext.projection = g_math.matrix4.perspective( + g_math.degToRad(40), // 30 degree frustum. + g_o3dElement.clientWidth / g_o3dElement.clientHeight, // Aspect ratio. + 1, // Near plane. + 10000); // Far plane. + + // Set up our view transformation to look towards the axes origin. + g_viewInfo.drawContext.view = g_math.matrix4.lookAt( + g_eyeView, // eye + [0, 0, 0], // target + [0, 1, 0]); // up +} + +/** + * Reset to the original view of the model. + */ +function resetView() { + initContext(); + g_client.render(); +} + +/** + * Creates a phong material based on the given single color. + * @param {Array} baseColor An array with 4 entries, the R,G,B, and A components + * of a color. + * @return {!o3d.Material} A phong material whose overall pigment is baseColor. + */ +function createPhongMaterial(baseColor) { + // Create a new, empty Material object. + var material = g_pack.createObject('Material'); + + var lightPosition = [1000, 2000, 3000]; + o3djs.effect.attachStandardShader( + g_pack, material, lightPosition, 'phong'); + + material.drawList = g_viewInfo.performanceDrawList; + + // Assign parameters to the phong material. + material.getParam('emissive').value = [0, 0, 0, 1]; + material.getParam('ambient').value = + [.1 * baseColor[0], .1 * baseColor[1], .1 * baseColor[2], 1]; + material.getParam('diffuse').value = + [.9 * baseColor[0], .9 * baseColor[1], .9 * baseColor[2], 1]; + material.getParam('specular').value = [.5, .5, .5, 1]; + material.getParam('shininess').value = 50; + material.getParam('lightColor').value = [1, 1, 1, 1]; + + return material; +} + +/** + * Create a 3D Scatter object by plotting each data point on a 3D model. + */ +function createScatterObject() { + // size of a scatter point (represented as a small cube). + var pointSize = 0.5; + + for (var i = 0; i < g_teapotVertices.length; i += 3) { + var varX = g_teapotVertices[i]; + var varY = g_teapotVertices[i+2]; + var varZ = g_teapotVertices[i+1]; + + // create the transform for the cube. + var transform = g_pack.createObject('Transform'); + transform.parent = g_modelRoot; + transform.addShape(g_cubeShape); + // translate and scale the point correctly relative to origin + transform.translate(varX, varY, varZ); + transform.scale(pointSize, pointSize, pointSize); + transform.createParam('diffuse', 'ParamFloat4').value = [1, 0, 0, 1]; + } +} + +/** + * Creates a 3D chart model. + */ +function create3dChartModel() { + // create the x,y,z axes - use the cylinder primitive. + var cylinder_length = 90; + var cylinder_radius = 0.15; + var cylinder_subdivisions = 6; + + var cylinder = o3djs.primitives.createCylinder( + g_pack, + g_material, + cylinder_radius, // Radius. + cylinder_length, // Depth. + cylinder_subdivisions, // Number of subdivisions. + 1); + + var cylinder_x = g_pack.createObject('Transform'); + cylinder_x.parent = g_modelRoot; + cylinder_x.addShape(cylinder); + cylinder_x.createParam('diffuse', 'ParamFloat4').value = [1, 0.2, 0.2, 1]; + cylinder_x.rotateZ(Math.PI / 2); + + var cylinder_y = g_pack.createObject('Transform'); + cylinder_y.parent = g_modelRoot; + cylinder_y.addShape(cylinder); + cylinder_y.createParam('diffuse', 'ParamFloat4').value = [0.2, 1, 0.2, 1]; + cylinder_y.rotateX(Math.PI / 2); + + var cylinder_z = g_pack.createObject('Transform'); + cylinder_z.parent = g_modelRoot; + cylinder_z.addShape(cylinder); + cylinder_z.createParam('diffuse', 'ParamFloat4').value = [0.2, 0.2, 1, 1]; + + // Create the scatter object. + createScatterObject(); +} + +/** + * Callback for the keypress event. + * Rotates the 3D model along the x, y or z-axes based on key pressed. + * Zooms in and out by moving the viewpoint. + * @param {event} event keyPress event passed to us by javascript. + */ +function keyPressed(event) { + event = event || window.event; + + // Ignore accelerator key messages. + if (event.metaKey) + return; + var keyChar = String.fromCharCode(o3djs.event.getEventKeyChar(event)); + keyChar = keyChar.toLowerCase(); + + var delta = 0.03; // rotation delta. + // Create an array associating the keystroke to an axis about which to rotate. + // Then dereference that array to get the axis. + + switch(keyChar) { + case 'a': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationY(-delta)); + break; + case 'd': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationY(delta)); + break; + case 'w': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationX(-delta)); + break; + case 's': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationX(delta)); + break; + case 'l': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationZ(-delta)); + break; + case 'k': + g_modelRoot.localMatrix = + g_math.matrix4.mul(g_modelRoot.localMatrix, + g_math.matrix4.rotationZ(delta)); + break; + case 'i': + ZoomInOut(g_zoomFactor); + break; + case 'o': + ZoomInOut(1.0 / g_zoomFactor); + break; + } + + o3djs.event.cancel(event); + + g_client.render(); +} + +/** + * Zooms the model in / out by changing the viewpoint. + * @param {number} zoom zooming factor. + */ +function ZoomInOut(zoom) { + for (i = 0; i < g_eyeView.length; i += 1) { + g_eyeView[i] = g_eyeView[i] / zoom; + } + + g_viewInfo.drawContext.view = g_math.matrix4.lookAt( + g_eyeView, // eye + [0, 0, 0], // target + [0, 1, 0]); // up +} + +/** + * Start mouse dragging. + * @param {event} e event. + */ +function startDragging(e) { + g_lastRot = g_thisRot; + g_aball.click([e.x, e.y]); + g_dragging = true; +} + +/** + * Use the arcball to rotate the model. + * Computes the rotation matrix. + * @param {event} e event. + */ +function drag(e) { + if (g_dragging) { + var rotationQuat = g_aball.drag([e.x, e.y]); + var rot_mat = g_quaternions.quaternionToRotation(rotationQuat); + g_thisRot = g_math.matrix4.mul(g_lastRot, rot_mat); + var m = g_modelRoot.localMatrix; + g_math.matrix4.setUpper3x3(m, g_thisRot); + g_modelRoot.localMatrix = m; + + g_client.render(); + } +} + +/** + * Stop dragging. + * @param {event} e event. + */ +function stopDragging(e) { + g_dragging = false; +} + +/** + * Using the mouse wheel zoom in and out of the model. + * @param {event} e event. + */ +function scrollMe(e) { + var zoom = (e.deltaY < 0) ? 1 / g_zoomFactor : g_zoomFactor; + ZoomInOut(zoom); + g_client.render(); +} + +</script> +</head> + +<body> +<h2>Scatter Chart - rotate & zoom with mouse or keyboard</h2> +<!-- Start of O3D plugin --> +<div id="o3d" style="width: 600px; height: 600px;"></div> +<!-- End of O3D plugin --> +<form name="default_form" action="#" method="get" > +<div style="font-size:10"> +Rotate: (W, S), (A, D), (K, L) +Zoom: (I, O) +<input type="button" value="Reset View" onclick="resetView()" +style="font-size:10"/> +</div> +</form> + +</body> +</html> |