diff options
author | simonrad@chromium.org <simonrad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-03 23:15:18 +0000 |
---|---|---|
committer | simonrad@chromium.org <simonrad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-03 23:15:18 +0000 |
commit | df2c7403503b45467d3d76ddc2f42296fa53ac50 (patch) | |
tree | a2d84c70b3cd37fb645fb8d5c5bcfab638c9d392 /o3d/samples/o3djs | |
parent | 89d6e6e3456280a12b4b806de8cbe3d049476df6 (diff) | |
download | chromium_src-df2c7403503b45467d3d76ddc2f42296fa53ac50.zip chromium_src-df2c7403503b45467d3d76ddc2f42296fa53ac50.tar.gz chromium_src-df2c7403503b45467d3d76ddc2f42296fa53ac50.tar.bz2 |
Creates a CameraController class, and makes the Rotate1 manipulator use line geometry.
- Creates a basic CameraController class. It allows the user to rotate the camera around a center position using the mouse, and outputs a view matrix.
- Changes the Rotate1 manipulator to display as line geometry. Adds a line ring primitive and a special shader.
- Merges changes to Rotate1 sample into Translate1+2 samples as well. We probably should refactor the samples so we don't have duplicate code.
R=gman,kbr
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/465023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33747 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples/o3djs')
-rw-r--r-- | o3d/samples/o3djs/cameracontroller.js | 208 | ||||
-rw-r--r-- | o3d/samples/o3djs/lineprimitives.js | 100 | ||||
-rw-r--r-- | o3d/samples/o3djs/manipulators.js | 219 |
3 files changed, 471 insertions, 56 deletions
diff --git a/o3d/samples/o3djs/cameracontroller.js b/o3d/samples/o3djs/cameracontroller.js new file mode 100644 index 0000000..9dcb980 --- /dev/null +++ b/o3d/samples/o3djs/cameracontroller.js @@ -0,0 +1,208 @@ +/* + * 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. + */ + + +/** + * @fileoverview This file contains sample code for controlling the camera + * (ie view matrix) using the mouse and keyboard. + */ + +o3djs.provide('o3djs.cameracontroller'); + +o3djs.require('o3djs.math'); + +/** + * A Module for user control of the camera / view matrix. + * @namespace + */ +o3djs.cameracontroller = o3djs.cameracontroller || {}; + +/** + * Creates a CameraController. + * @param {!o3djs.math.Vector3} centerPos The position that the camera is + * looking at and rotating around; or if backpedal is zero, the location + * of the camera. In world space. + * @param {number} backpedal The distance the camera moves back from the + * centerPos. + * @param {number} heightAngle The angle the camera rotates up or down + * (about the x axis that passes through the centerPos). In radians. + * @param {number} rotationAngle The angle the camera rotates left or right + * (about the y axis that passes through the centerPos). In radians. + * @param {function(!o3djs.cameracontroller.CameraController): void} + * opt_onchange Pointer to a callback to call when the camera changes. + * @return {!o3djs.cameracontroller.CameraController} The created + * CameraController. + */ +o3djs.cameracontroller.createCameraController = function(centerPos, + backpedal, + heightAngle, + rotationAngle, + opt_onchange) { + return new o3djs.cameracontroller.CameraController(centerPos, + backpedal, + heightAngle, + rotationAngle, + opt_onchange); +}; + +/** + * Class to hold user-controlled camera information and handle user events. + * @constructor + * @param {!o3djs.math.Vector3} centerPos The position that the camera is + * looking at and rotating around; or if backpedal is zero, the location + * of the camera. In world space. + * @param {number} backpedal The distance the camera moves back from the + * centerPos. + * @param {number} heightAngle The angle the camera rotates up or down + * (about the x axis that passes through the centerPos). In radians. + * @param {number} rotationAngle The angle the camera rotates left or right + * (about the y axis that passes through the centerPos). In radians. + * @param {function(!o3djs.cameracontroller.CameraController): void} + * opt_onchange Pointer to a callback to call when the camera changes. + */ +o3djs.cameracontroller.CameraController = function(centerPos, + backpedal, + heightAngle, + rotationAngle, + opt_onchange) { + /** + * The position that the camera is looking at and rotating around. + * Or if backpedal is zero, the location of the camera. In world space. + * @type {!o3djs.math.Vector3} + */ + this.centerPos = centerPos; + + /** + * The distance the camera moves back from the centerPos. + * @type {number} + */ + this.backpedal = backpedal; + + /** + * The angle the camera rotates up or down. + * @type {number} + */ + this.heightAngle = heightAngle; + + /** + * The angle the camera rotates left or right. + * @type {number} + */ + this.rotationAngle = rotationAngle; + + + /** + * Points to a callback to call when the camera changes. + * @type {function(!o3djs.cameracontroller.CameraController): void} + */ + this.onchange = opt_onchange || null; + + /** + * Whether the mouse is currently being dragged to control the camera. + * @private + * @type {boolean} + */ + this.dragging_ = false; + + /** + * The last X coordinate of the mouse. + * @private + * @type {number} + */ + this.mouseX_ = 0; + + /** + * The last Y coordinate of the mouse. + * @private + * @type {number} + */ + this.mouseY_ = 0; + + /** + * Controls how quickly the mouse moves the camera. + * @type {number} + */ + this.dragScaleFactor = 300.0; +}; + +/** + * Calculates the view matrix for this camera. + * @return {!o3djs.math.Matrix4} The view matrix. + */ +o3djs.cameracontroller.CameraController.prototype.calculateViewMatrix = function() { + var matrix4 = o3djs.math.matrix4; + var view = matrix4.translation(o3djs.math.negativeVector(this.centerPos)); + view = matrix4.mul(view, matrix4.rotationY(this.rotationAngle)); + view = matrix4.mul(view, matrix4.rotationX(this.heightAngle)); + view = matrix4.mul(view, matrix4.translation([0, 0, -this.backpedal])); + return view; +}; + +/** + * Method which should be called by end user code upon receiving a + * mouse-down event. + * @param {!o3d.Event} ev The event. + */ +o3djs.cameracontroller.CameraController.prototype.mousedown = function(ev) { + this.dragging_ = true; + this.mouseX_ = ev.x; + this.mouseY_ = ev.y; +}; + +/** + * Method which should be called by end user code upon receiving a + * mouse-up event. + * @param {!o3d.Event} ev The event. + */ +o3djs.cameracontroller.CameraController.prototype.mouseup = function(ev) { + this.dragging_ = false; +}; + +/** + * Method which should be called by end user code upon receiving a + * mouse-move event. + * @param {!o3d.Event} ev The event. + */ +o3djs.cameracontroller.CameraController.prototype.mousemove = function(ev) { + if (this.dragging_) { + var curX = ev.x; + var curY = ev.y; + var deltaX = (curX - this.mouseX_) / this.dragScaleFactor; + var deltaY = (curY - this.mouseY_) / this.dragScaleFactor; + this.mouseX_ = curX; + this.mouseY_ = curY; + this.rotationAngle += deltaX; + this.heightAngle += deltaY; + if (this.onchange != null) { + this.onchange(this); + } + } +}; diff --git a/o3d/samples/o3djs/lineprimitives.js b/o3d/samples/o3djs/lineprimitives.js index 8a5d1d6..8e4d923 100644 --- a/o3d/samples/o3djs/lineprimitives.js +++ b/o3d/samples/o3djs/lineprimitives.js @@ -129,10 +129,10 @@ o3djs.lineprimitives.createLineVertexInfo = function() { }; /** - * Creates the vertices and indices for a cube of lines. The - * cube will be created around the origin. (-size / 2, size / 2) + * Creates the vertices and indices for a cube of lines. + * The cube will be created around the origin (-size / 2, size / 2). * The created cube has a position stream only and can therefore only be used - * with shaders that support those a position stream. + * with appropriate shaders. * * @param {number} size Width, height and depth of the cube. * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all @@ -188,8 +188,12 @@ o3djs.lineprimitives.createLineCubeVertices = function(size, opt_matrix) { /** * Creates a cube of lines. - * @param {!o3d.Pack} pack Pack to create sphere elements in. - * @param {!o3d.Material} material to use. + * The cube will be created around the origin (-size / 2, size / 2). + * The created cube has a position stream only and can therefore only be used + * with appropriate shaders. + * + * @param {!o3d.Pack} pack Pack to create cube elements in. + * @param {!o3d.Material} material Material to use. * @param {number} size Width, height and depth of the cube. * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all * the vertices. @@ -208,11 +212,11 @@ o3djs.lineprimitives.createLineCube = function( /** * Creates sphere vertices. * The created sphere has a position stream only and can therefore only be - * used with shaders that support those a position stream. + * used with appropriate shaders. * * @param {number} radius radius of the sphere. * @param {number} subdivisionsAxis number of steps around the sphere. - * @param {number} subdivisionsHeight number of vertically on the sphere. + * @param {number} subdivisionsHeight number of steps vertically on the sphere. * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all * the vertices. * @return {!o3djs.lineprimitives.LineVertexInfo} The created sphere vertices. @@ -274,15 +278,14 @@ o3djs.lineprimitives.createLineSphereVertices = function( /** * Creates a sphere. - * The created sphere has position, normal, uv and vertex color streams only - * and can therefore only be used with shaders that support those 4 - * streams. + * The created sphere has a position stream only and can therefore only be + * used with appropriate shaders. * * @param {!o3d.Pack} pack Pack to create sphere elements in. - * @param {!o3d.Material} material to use. + * @param {!o3d.Material} material Material to use. * @param {number} radius radius of the sphere. * @param {number} subdivisionsAxis number of steps around the sphere. - * @param {number} subdivisionsHeight number of vertically on the sphere. + * @param {number} subdivisionsHeight number of steps vertically on the sphere. * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all * the vertices. * @return {!o3d.Shape} The created sphere. @@ -306,3 +309,76 @@ o3djs.lineprimitives.createLineSphere = function( return vertexInfo.createShape(pack, material); }; +/** + * Creates ring vertices. + * The ring is a circle in the XZ plane, centered at the origin. + * The created ring has a position stream and a normal stream. + * The normals point outwards from the center of the ring. + * + * @param {number} radius Radius of the ring. + * @param {number} subdivisions Number of steps around the ring. + * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all + * the vertices. + * @return {!o3djs.lineprimitives.LineVertexInfo} The created ring vertices. + */ +o3djs.lineprimitives.createLineRingVertices = function( + radius, + subdivisions, + opt_matrix) { + if (subdivisions < 3) { + throw Error('subdivisions must be >= 3'); + } + + var vertexInfo = o3djs.lineprimitives.createLineVertexInfo(); + var positionStream = vertexInfo.addStream( + 3, o3djs.base.o3d.Stream.POSITION); + var normalStream = vertexInfo.addStream( + 3, o3djs.base.o3d.Stream.NORMAL); + + // Generate the individual vertices in our vertex buffer. + for (var i = 0; i < subdivisions; i++) { + var theta = 2 * Math.PI * i / subdivisions; + positionStream.addElement(radius * Math.cos(theta), 0, + radius * Math.sin(theta)); + normalStream.addElement(Math.cos(theta), 0, Math.sin(theta)); + } + + // Connect the vertices by simple lines. + for (var i = 0; i < subdivisions; i++) { + vertexInfo.addLine(i, (i+1) % subdivisions); + } + + if (opt_matrix) { + vertexInfo.reorient(opt_matrix); + } + return vertexInfo; +}; + +/** + * Creates a ring. + * The ring is a circle in the XZ plane, centered at the origin. + * The created ring has a position stream only and can therefore only be + * used with appropriate shaders. + * + * @param {!o3d.Pack} pack Pack to create ring elements in. + * @param {!o3d.Material} material Material to use. + * @param {number} radius Radius of the ring. + * @param {number} subdivisions Number of steps around the ring. + * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply all + * the vertices. + * @return {!o3d.Shape} The created ring. + */ +o3djs.lineprimitives.createLineRing = function( + pack, + material, + radius, + subdivisions, + opt_matrix) { + var vertexInfo = o3djs.lineprimitives.createLineRingVertices( + radius, + subdivisions, + opt_matrix); + + return vertexInfo.createShape(pack, material); +}; + diff --git a/o3d/samples/o3djs/manipulators.js b/o3d/samples/o3djs/manipulators.js index 85fb611..76db16c 100644 --- a/o3d/samples/o3djs/manipulators.js +++ b/o3d/samples/o3djs/manipulators.js @@ -37,6 +37,8 @@ o3djs.provide('o3djs.manipulators'); +o3djs.require('o3djs.lineprimitives'); + o3djs.require('o3djs.material'); o3djs.require('o3djs.math'); @@ -491,18 +493,17 @@ o3djs.manipulators.Manager = function(pack, this.lightPosition = [10, 10, 10]; /** - * The default material for manipulators (used when not highlighted). + * A constant-shaded material, useful for line geometry in some manipulators. + * + * TODO(simonrad): This is currently used for Translate1+2 polygon geometry. + * We should change polygon geometry back to using phong shader. We should + * use this constant shader for Translate1+2 line geometry, if we add it. + * Rotate1 line geometry uses a different, special shader. + * * @type {!o3d.Material} */ - this.defaultMaterial = - this.createMaterial_(o3djs.manipulators.DEFAULT_COLOR); - /** - * The material used for manipulators when they are highlighted. - * (TODO(simonrad): This is not currently used; only defaultMaterial is used. Remove this?) - * @type {!o3d.Material} - */ - this.highlightedMaterial = - this.createMaterial_(o3djs.manipulators.HIGHLIGHTED_COLOR); + this.constantMaterial = + this.createConstantMaterial_(o3djs.manipulators.DEFAULT_COLOR); /** * A map from the manip's parent Transform clientId to the manip. @@ -512,10 +513,9 @@ o3djs.manipulators.Manager = function(pack, /** * A PickManager to manage picking for the manipulators. - * @type {!o3djs.picking.TransformInfo} + * @type {!o3djs.picking.PickManager} */ - this.pickManager = - o3djs.picking.createPickManager(this.parentTransform); + this.pickManager = o3djs.picking.createPickManager(this.parentTransform); /** * The currently-highlighted manipulator. @@ -532,19 +532,24 @@ o3djs.manipulators.Manager = function(pack, } /** - * Creates a material based on the given single color. + * Creates a constant-shaded material based on the given single color. * @private * @param {!o3djs.math.Vector4} baseColor A vector with 4 entries, the * R,G,B, and A components of a color. - * @return {!o3d.Material} A phong material whose overall pigment is baseColor. + * @return {!o3d.Material} A constant material whose overall pigment is baseColor. */ -o3djs.manipulators.Manager.prototype.createMaterial_ = +o3djs.manipulators.Manager.prototype.createConstantMaterial_ = function(baseColor) { - // Create a new, empty Material object. return o3djs.material.createConstantMaterialEx( this.pack, this.drawList, baseColor); } +// TODO(simonrad): Add phong shader back in. We need it for the solid cones +// of the Translate1+2 manipulators. Note that for highlighting, the phong +// shader uses diffuse param and the constant shader uses emissive param, so +// we'll need to either change that or split them onto separate transforms. +// Probably the former would be better. + /** * Creates a new Translate1 manipulator. A Translate1 moves along the * X axis in its local coordinate system. @@ -586,8 +591,6 @@ o3djs.manipulators.Manager.prototype.createRotate1 = function() { o3djs.manipulators.Manager.prototype.add_ = function(manip) { // Generate draw elements for the manipulator's transform manip.getTransform().createDrawElements(this.pack, null); - // Add the manipulator's transform to the parent transform - manip.getBaseTransform_().parent = this.parentTransform; // Add the manipulator into our managed list this.manipsByClientId[manip.getTransform().clientId] = manip; } @@ -628,8 +631,13 @@ o3djs.manipulators.Manager.prototype.handleMouse_ = function(x, // Find which manipulator we picked. // NOTE this assumes some things about the transform graph // structure of the manipulators. + // We may need to index by the parent-parent transform instead, since the + // shape could be attached to the manip's invisibleTransform_, which is a + // child of the localTransform_. var manip = - this.manipsByClientId[pickResult.shapeInfo.parent.transform.clientId]; + this.manipsByClientId[pickResult.shapeInfo.parent.transform.clientId] || + this.manipsByClientId[ + pickResult.shapeInfo.parent.parent.transform.clientId]; func(this, pickResult, manip); } else { func(this, null, null); @@ -808,9 +816,28 @@ o3djs.manipulators.Manip = function(manager) { */ this.baseTransform_ = pack.createObject('Transform'); + /** + * This child transform is used only to hold any invisible shapes + * we may want. Invisible shapes can be useful for picking. Visibility is + * controlled by the transform, which is why we need this transform. + * The local matrix of this transform should only be the identity matrix. + * @private + * @type {!o3d.Transform} + */ + this.invisibleTransform_ = pack.createObject('Transform'); + this.invisibleTransform_.visible = false; + // Hook up these transforms + this.invisibleTransform_.parent = this.localTransform_; this.localTransform_.parent = this.offsetTransform_; this.offsetTransform_.parent = this.baseTransform_; + this.baseTransform_.parent = manager.parentTransform; + + // Make the invisible transform pickable even though it's invisible + manager.pickManager.update(); + var invisibleTransformInfo = manager.pickManager.getTransformInfo( + this.invisibleTransform_); + invisibleTransformInfo.pickableEvenIfInvisible = true; /** * This is the transform in the scene graph to which this @@ -833,10 +860,19 @@ o3djs.manipulators.Manip = function(manager) { * Adds shapes to the internal transform of this manipulator. * @private * @param {!Array.<!o3d.Shape>} shapes Array of shapes to add. + * @param {boolean} opt_visible Whether the added shapes should be visible. + * Default = true. Invisible geometry can be useful for picking. */ -o3djs.manipulators.Manip.prototype.addShapes_ = function(shapes) { +o3djs.manipulators.Manip.prototype.addShapes_ = function(shapes, opt_visible) { + if (opt_visible == undefined) { + opt_visible = true; + } for (var ii = 0; ii < shapes.length; ii++) { - this.localTransform_.addShape(shapes[ii]); + if(opt_visible) { + this.localTransform_.addShape(shapes[ii]); + } else { + this.invisibleTransform_.addShape(shapes[ii]); + } } } @@ -1145,7 +1181,7 @@ o3djs.manipulators.Translate1 = function(manager) { o3djs.manipulators.Manip.call(this, manager); var pack = manager.pack; - var material = manager.defaultMaterial; + var material = manager.constantMaterial; var shape = manager.translate1Shape_; if (!shape) { @@ -1159,10 +1195,6 @@ o3djs.manipulators.Translate1 = function(manager) { this.addShapes_([ shape ]); - this.transformInfo = manager.pickManager.createTransformInfo( - this.getTransform(), - manager.transformInfo); - /** * A parameter added to our transform to be able to change the * material's color for highlighting. @@ -1254,7 +1286,7 @@ o3djs.manipulators.Translate2 = function(manager) { o3djs.manipulators.Manip.call(this, manager); var pack = manager.pack; - var material = manager.defaultMaterial; + var material = manager.constantMaterial; var shape = manager.Translate2Shape_; if (!shape) { @@ -1271,10 +1303,6 @@ o3djs.manipulators.Translate2 = function(manager) { this.addShapes_([ shape ]); - this.transformInfo = manager.pickManager.createTransformInfo( - this.getTransform(), - manager.transformInfo); - /** * A parameter added to our transform to be able to change the * material's color for highlighting. @@ -1367,27 +1395,40 @@ o3djs.manipulators.Rotate1 = function(manager) { o3djs.manipulators.Manip.call(this, manager); var pack = manager.pack; - var material = manager.defaultMaterial; - var shape = manager.Rotate1Shape_; - if (!shape) { - // Create the geometry for the manipulator, which looks like + if (!manager.lineRingMaterial) { + manager.lineRingMaterial = o3djs.manipulators.createLineRingMaterial( + pack, manager.drawList, [1, 1, 1, 1], [1, 1, 1, 0.4]); + } + + var pickShape = manager.Rotate1PickShape_; + if (!pickShape) { + // Create the polygon geometry for picking the manipulator, which looks like // a torus centered at the origin, with the X axis as its vertical axis. var verts = o3djs.primitives.createTorusVertices( 1.0, 0.1, - 32, - 8, + 16, + 6, o3djs.math.matrix4.rotationZ(Math.PI / 2)); - shape = verts.createShape(pack, material); - manager.Rotate1Shape_ = shape; + pickShape = verts.createShape(pack, manager.constantMaterial); + manager.Rotate1PickShape_ = pickShape; } - this.addShapes_([ shape ]); + var visibleShape = manager.Rotate1VisibleShape_; + if (!visibleShape) { + // Create the line geometry for displaying the manipulator, which looks like + // a ring centered at the origin, with the X axis as its vertical axis. + var verts = o3djs.lineprimitives.createLineRingVertices( + 1.0, + 32, + o3djs.math.matrix4.rotationZ(Math.PI / 2)); + visibleShape = verts.createShape(pack, manager.lineRingMaterial); + manager.Rotate1VisibleShape_ = visibleShape; + } - this.transformInfo = manager.pickManager.createTransformInfo( - this.getTransform(), - manager.transformInfo); + this.addShapes_([ pickShape ], false); // Invisible + this.addShapes_([ visibleShape ]); /** * A parameter added to our transform to be able to change the @@ -1508,3 +1549,93 @@ o3djs.manipulators.Rotate1.prototype.drag = function(startPoint, this.getTransform().localMatrix = o3djs.math.matrix4.rotationX(-angle); this.updateAttachedTransformFromLocalTransform_(); } + + +// The shader and material for the Rotate1 manipulator's line ring. +// TODO(simonrad): Find a better place for these? + +/** + * The name of the Rotate1 manipulator's line ring effect. + * @type {string} + */ +o3djs.manipulators.LINE_RING_EFFECT_NAME = + 'o3djs.manipulators.lineRingEffect'; + +/** + * An effect string for the Rotate1 manipulator's line ring. + * @type {string} + */ +o3djs.manipulators.LINE_RING_FXSTRING = '' + + 'float4x4 worldViewProjection : WORLDVIEWPROJECTION;\n' + + 'float4x4 worldViewProjectionInverseTranspose :\n' + + ' WORLDVIEWPROJECTIONINVERSETRANSPOSE;\n' + + 'float4 color1;\n' + + 'float4 color2;\n' + + 'float4 emissive; // Used for highlighting.\n' + + '\n' + + 'struct VertexShaderInput {\n' + + ' float4 position : POSITION;\n' + + ' float4 normal : NORMAL;\n' + + '};\n' + + '\n' + + 'struct PixelShaderInput {\n' + + ' float4 position : POSITION;\n' + + ' float3 normal : TEXCOORD0;\n' + + '};\n' + + '\n' + + 'PixelShaderInput vertexShaderFunction(VertexShaderInput input) {\n' + + ' PixelShaderInput output;\n' + + '\n' + + ' output.position = mul(input.position, worldViewProjection);\n' + + ' output.normal = mul(input.normal,\n' + + ' worldViewProjectionInverseTranspose).xyz;\n' + + ' return output;\n' + + '}\n' + + '\n' + + 'float4 pixelShaderFunction(PixelShaderInput input): COLOR {\n' + + ' if (input.normal.z < 0) {\n' + + ' return color1 * emissive;\n' + + ' } else {\n' + + ' return color2 * emissive;\n' + + ' }\n' + + '}\n' + + '\n' + + '// #o3d VertexShaderEntryPoint vertexShaderFunction\n' + + '// #o3d PixelShaderEntryPoint pixelShaderFunction\n' + + '// #o3d MatrixLoadOrder RowMajor\n'; + +/** + * Creates the Rotate1 manipulator's line ring material. + * + * @param {!o3d.Pack} pack The pack to create the effect and material in. + * @param {!o3d.DrawList} drawList The draw list against which + * the material is created. + * @param {!o3djs.math.Vector4} color1 A color in the format [r, g, b, a]. + * @param {!o3djs.math.Vector4} color2 A color in the format [r, g, b, a]. + * @return {!o3d.Material} The created material. + */ +o3djs.manipulators.createLineRingMaterial = function(pack, + drawList, + color1, + color2) { + var material = pack.createObject('Material'); + material.effect = pack.createObject('Effect'); + material.effect.loadFromFXString(o3djs.manipulators.LINE_RING_FXSTRING); + material.effect.name = o3djs.manipulators.LINE_RING_EFFECT_NAME; + material.drawList = drawList; + material.createParam('color1', 'ParamFloat4').value = color1; + material.createParam('color2', 'ParamFloat4').value = color2; + + // Set up the state to allow alpha blending + material.state = pack.createObject('State'); + material.state.getStateParam('AlphaBlendEnable').value = true; + material.state.getStateParam('SourceBlendFunction').value = + o3djs.base.o3d.State.BLENDFUNC_SOURCE_ALPHA; + material.state.getStateParam('DestinationBlendFunction').value = + o3djs.base.o3d.State.BLENDFUNC_INVERSE_SOURCE_ALPHA; + material.state.getStateParam('AlphaTestEnable').value = true; + material.state.getStateParam('AlphaComparisonFunction').value = + o3djs.base.o3d.State.CMP_GREATER; + + return material; +}; |