summaryrefslogtreecommitdiffstats
path: root/o3d/samples
diff options
context:
space:
mode:
authorsimonrad@chromium.org <simonrad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-20 03:42:41 +0000
committersimonrad@chromium.org <simonrad@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-11-20 03:42:41 +0000
commit021c6aacd0cfc3f5f8b24af3361dac0205c6fb04 (patch)
tree0fa532e139cfce113f7c1a1ac61f4721c24dd576 /o3d/samples
parent109f7236ba8d73e42841760cefe5a3e1539bbc1e (diff)
downloadchromium_src-021c6aacd0cfc3f5f8b24af3361dac0205c6fb04.zip
chromium_src-021c6aacd0cfc3f5f8b24af3361dac0205c6fb04.tar.gz
chromium_src-021c6aacd0cfc3f5f8b24af3361dac0205c6fb04.tar.bz2
Added torus primitive and Rotate1 manipulator.
BUG=none TEST=none Review URL: http://codereview.chromium.org/395012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@32596 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/samples')
-rw-r--r--o3d/samples/manipulators/rotate1.html282
-rw-r--r--o3d/samples/o3djs/manipulators.js157
-rw-r--r--o3d/samples/o3djs/primitives.js151
3 files changed, 556 insertions, 34 deletions
diff --git a/o3d/samples/manipulators/rotate1.html b/o3d/samples/manipulators/rotate1.html
new file mode 100644
index 0000000..226001e
--- /dev/null
+++ b/o3d/samples/manipulators/rotate1.html
@@ -0,0 +1,282 @@
+<!--
+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.
+-->
+
+<!--
+Translate2 manipulator
+
+This sample shows how to use the o3djs.manipulators.Translate2 class
+to interactively drag objects around the scene.
+-->
+<!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>
+Translate2 Manipulator
+</title>
+<script type="text/javascript" src="../o3djs/base.js"></script>
+<script type="text/javascript" id="o3dscript">
+o3djs.require('o3djs.util');
+o3djs.require('o3djs.math');
+o3djs.require('o3djs.quaternions');
+o3djs.require('o3djs.rendergraph');
+o3djs.require('o3djs.primitives');
+o3djs.require('o3djs.manipulators');
+o3djs.require('o3djs.effect');
+
+// global variables
+var g_o3dElement;
+var g_client;
+var g_o3d;
+var g_math;
+var g_pack;
+var g_viewInfo;
+
+var g_lightPosition = [5, 5, 7];
+var g_eyePosition = [1, 5, 23];
+
+var g_primitives = [];
+var g_manager;
+
+/**
+ * Creates the client area.
+ */
+function initClient() {
+ window.g_finished = false; // for selenium testing.
+
+ // Runs the sample in V8. Comment out this line to run it in the browser
+ // JavaScript engine, for example if you want to debug it.
+ // TODO(kbr): we need to investigate why turning this on is
+ // significantly slower than leaving it disabled.
+ // o3djs.util.setMainEngine(o3djs.util.Engine.V8);
+
+ o3djs.util.makeClients(main);
+}
+
+/**
+ * Initializes global variables, positions camera, draws shapes.
+ * @param {Array} clientElements Array of o3d object elements.
+ */
+function main(clientElements) {
+ var o3dElement = clientElements[0];
+
+ // Init global variables.
+ initGlobals(clientElements);
+
+ // Set up the view and projection transformations.
+ initContext();
+
+ // Add the shapes to the transform heirarchy.
+ createShapes();
+
+ // Add the manipulators to the transform hierarchy.
+ createManipulators();
+
+ // Start picking; it won't do anything until the scene finishes loading.
+ o3djs.event.addEventListener(o3dElement, 'mousedown', onMouseDown);
+ o3djs.event.addEventListener(o3dElement, 'mousemove', onMouseMove);
+ o3djs.event.addEventListener(o3dElement, 'mouseup', onMouseUp);
+
+ window.g_finished = true; // for selenium testing.
+}
+
+function onMouseDown(e) {
+ g_manager.mousedown(e.x, e.y,
+ g_viewInfo.drawContext.view,
+ g_viewInfo.drawContext.projection,
+ g_client.width,
+ g_client.height);
+}
+
+function onMouseMove(e) {
+ g_manager.mousemove(e.x, e.y,
+ g_viewInfo.drawContext.view,
+ g_viewInfo.drawContext.projection,
+ g_client.width,
+ g_client.height);
+ g_manager.updateInactiveManipulators();
+}
+
+function onMouseUp(e) {
+ g_manager.mouseup();
+ g_manager.updateInactiveManipulators();
+}
+
+/**
+ * Initializes global variables and libraries.
+ */
+function initGlobals(clientElements) {
+ g_o3dElement = clientElements[0];
+ window.g_client = 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();
+
+ // Create the render graph for a view.
+ g_viewInfo = o3djs.rendergraph.createBasicView(
+ g_pack,
+ g_client.root,
+ g_client.renderGraphRoot);
+}
+
+/**
+ * Sets up reasonable view and projection matrices.
+ */
+function initContext() {
+ // Set up a perspective transformation for the projection.
+ g_viewInfo.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
+ // primitives are located.
+ g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
+ g_eyePosition, // eye
+ [0, 2, 0], // target
+ [0, 1, 0]); // up
+}
+
+/**
+ * Creates shapes using the primitives utility library, and adds them to the
+ * transform graph at the root node.
+ */
+function createShapes() {
+ // Create a little tree-like hierarchy of cubes
+ createCubeTree(2, 1.5, [0, 0, 0], g_client.root);
+}
+
+/**
+ * Creates a small tree of cubes to demonstrate interaction with a
+ * hierarchy of shapes.
+ */
+function createCubeTree(depth, edgeLength, translation, parent) {
+ var cur = createCube(edgeLength, translation, parent);
+ if (depth > 0) {
+ createCubeTree(depth - 1,
+ edgeLength / 1.5,
+ o3djs.math.addVector(translation,
+ [-1.2 * edgeLength,
+ 1.0 * edgeLength,
+ 0]),
+ cur);
+ createCubeTree(depth - 1,
+ edgeLength / 1.5,
+ o3djs.math.addVector(translation,
+ [1.2 * edgeLength,
+ 1.0 * edgeLength,
+ 0]),
+ cur);
+ }
+ return cur;
+}
+
+/**
+ * Creates a cube shape using the primitives utility library, with an
+ * optional translation and parent. Returns the newly-created
+ * transform for the cube.
+ */
+function createCube(edgeLength, opt_translation, opt_parent) {
+ var cube = o3djs.primitives.createCube(
+ g_pack,
+ // A green phong-shaded material.
+ o3djs.material.createBasicMaterial(g_pack,
+ g_viewInfo,
+ [0, 1, 0, 1]),
+ edgeLength);
+ var transform = g_pack.createObject('Transform');
+ transform.addShape(cube);
+ if (opt_translation) {
+ transform.translate(opt_translation);
+ }
+ if (opt_parent) {
+ transform.parent = opt_parent;
+ } else {
+ transform.parent = g_client.root;
+ }
+ g_primitives.push(transform);
+ return transform;
+}
+
+/**
+ * Creates manipulators attached to the objects we've just created.
+ */
+function createManipulators() {
+ g_manager = o3djs.manipulators.createManager(g_pack,
+ g_viewInfo.performanceDrawList,
+ g_client.root,
+ null,
+ 0);
+ var jj = 2;
+ for (var ii = 0; ii < g_primitives.length; ii++) {
+ var manip1 = g_manager.createRotate1();
+ var manip2 = g_manager.createRotate1();
+ var manip3 = g_manager.createRotate1();
+ manip1.attachTo(g_primitives[ii]);
+ manip2.attachTo(g_primitives[ii]);
+ manip3.attachTo(g_primitives[ii]);
+ manip1.setOffsetTranslation([0, -1.5, 0]);
+ manip2.setOffsetTranslation([0, -1.5, 0]);
+ manip3.setOffsetTranslation([0, -1.5, 0]);
+ manip2.setOffsetRotation(o3djs.quaternions.rotationY(Math.PI / 2));
+ manip3.setOffsetRotation(o3djs.quaternions.rotationZ(Math.PI / 2));
+ // Demonstrate that we can drag along arbitrary directions.
+ if ((++jj % 4) == 0) {
+ manip1.setOffsetRotation(o3djs.quaternions.rotationY(Math.PI / 4));
+ manip2.setOffsetRotation(o3djs.quaternions.rotationY(Math.PI * 3.0 / 4));
+ }
+ }
+}
+
+/**
+ * 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 onload="initClient()" onunload="unload()">
+<h1>Translate2 Manipulator Sample</h1>
+This example shows how to move objects around the scene using the
+Translate2 manipulator.
+<br/>
+<!-- Start of O3D plugin -->
+<div id="o3d" style="width: 600px; height: 600px;"></div>
+<!-- End of O3D plugin -->
+</body>
+</html>
diff --git a/o3d/samples/o3djs/manipulators.js b/o3d/samples/o3djs/manipulators.js
index c38089c..db44344 100644
--- a/o3d/samples/o3djs/manipulators.js
+++ b/o3d/samples/o3djs/manipulators.js
@@ -582,6 +582,17 @@ o3djs.manipulators.Manager.prototype.createTranslate2 = function() {
}
/**
+ * Creates a new Rotate1 manipulator. A Rotate1 rotates about the
+ * X axis in its local coordinate system.
+ * @return {!o3djs.manipulators.Rotate1} A new Rotate1 manipulator.
+ */
+o3djs.manipulators.Manager.prototype.createRotate1 = function() {
+ var manip = new o3djs.manipulators.Rotate1(this);
+ this.add_(manip);
+ return manip;
+}
+
+/**
* Adds a manipulator to this manager's set.
* @private
* @param {!o3djs.manipulators.Manip} manip The manipulator to add.
@@ -1026,17 +1037,16 @@ o3djs.manipulators.Manip.prototype.updateAttachedTransformFromLocalTransform_ =
if (this.attachedTransform_ != null) {
// Compute the composition of the base and local transforms.
// The offset transform is skipped except for transforming the
- // local matrix's translation by the rotation component of the
- // offset transform.
+ // effect of the local matrix through the offset transform.
var base = this.baseTransform_.worldMatrix;
+ var offset = this.offsetTransform_.localMatrix;
var local = this.localTransform_.localMatrix;
- var xlate = o3djs.math.matrix4.getTranslation(local);
- var transformedXlate =
- o3djs.math.matrix4.transformDirection(
- this.offsetTransform_.localMatrix,
- o3djs.math.matrix4.getTranslation(local));
- o3djs.math.matrix4.setTranslation(local, transformedXlate);
- var totalMat = o3djs.math.matrix4.mul(base, local);
+ var offsetInv = o3djs.math.matrix4.inverse(offset);
+ // We want totalMat = offsetInv * local * offset * base.
+ var totalMat = o3djs.math.matrix4.mul(offsetInv, local);
+ totalMat = o3djs.math.matrix4.mul(totalMat, offset);
+ totalMat = o3djs.math.matrix4.mul(totalMat, base);
+
// Set this into the attached transform, taking into account its
// parent's transform, if any.
@@ -1045,11 +1055,11 @@ o3djs.manipulators.Manip.prototype.updateAttachedTransformFromLocalTransform_ =
var attWorld = this.attachedTransform_.worldMatrix;
var attLocal = this.attachedTransform_.localMatrix;
var attParentMat =
- o3djs.math.matrix4.mul(attWorld,
- o3djs.math.matrix4.inverse(attLocal));
+ o3djs.math.matrix4.mul(o3djs.math.matrix4.inverse(attLocal),
+ attWorld);
// Now we can take the inverse of this matrix
var attParentMatInv = o3djs.math.matrix4.inverse(attParentMat);
- totalMat = o3djs.math.matrix4.mul(attParentMatInv, totalMat);
+ totalMat = o3djs.math.matrix4.mul(totalMat, attParentMatInv);
this.attachedTransform_.localMatrix = totalMat;
}
}
@@ -1125,6 +1135,7 @@ o3djs.manipulators.createArrowVertices_ = function(matrix) {
/**
* A manipulator allowing an object to be dragged along a line.
+ * A Translate1 moves along the X axis in its local coordinate system.
* @constructor
* @extends {o3djs.manipulators.Manip}
* @param {!o3djs.manipulators.Manager} manager The manager for the
@@ -1226,6 +1237,7 @@ o3djs.manipulators.Translate1.prototype.drag = function(startPoint,
/**
* A manipulator allowing an object to be dragged around a plane.
+ * A Translate2 moves around the XY plane in its local coordinate system.
* @constructor
* @extends {o3djs.manipulators.Manip}
* @param {!o3djs.manipulators.Manager} manager The manager for the
@@ -1327,3 +1339,124 @@ o3djs.manipulators.Translate2.prototype.drag = function(startPoint,
diffVector));
this.updateAttachedTransformFromLocalTransform_();
}
+
+
+/**
+ * A manipulator allowing an object to be rotated about a single axis.
+ * A Rotate1 rotates about the X axis in its local coordinate system.
+ * @constructor
+ * @extends {o3djs.manipulators.Manip}
+ * @param {!o3djs.manipulators.Manager} manager The manager for the
+ * new Rotate1 manipulator.
+ */
+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
+ // 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,
+ o3djs.math.matrix4.rotationZ(Math.PI / 2));
+ shape = verts.createShape(pack, material);
+ manager.Rotate1Shape_ = shape;
+ }
+
+ this.addShapes_([ shape ]);
+
+ this.transformInfo = o3djs.picking.createTransformInfo(this.getTransform(),
+ manager.transformInfo);
+
+ /**
+ * A parameter added to our transform to be able to change the
+ * material's color for highlighting.
+ * @private
+ * @type {!o3d.ParamFloat4}
+ */
+ this.colorParam_ = this.getTransform().createParam('diffuse', 'ParamFloat4');
+ this.clearHighlight();
+
+ /**
+ * Plane around which we are dragging.
+ * @private
+ * @type {!o3djs.manipulators.Plane_}
+ */
+ this.dragPlane_ = new o3djs.manipulators.Plane_();
+}
+
+o3djs.base.inherit(o3djs.manipulators.Rotate1, o3djs.manipulators.Manip);
+
+o3djs.manipulators.Rotate1.prototype.highlight = function(pickResult) {
+ // We can use instanced geometry for the entire Rotate1 since its
+ // entire color changes during highlighting.
+ // TODO(kbr): support custom user geometry and associated callbacks.
+ this.colorParam_.value = o3djs.manipulators.HIGHLIGHTED_COLOR;
+}
+
+o3djs.manipulators.Rotate1.prototype.clearHighlight = function() {
+ this.colorParam_.value = o3djs.manipulators.DEFAULT_COLOR;
+}
+
+o3djs.manipulators.Rotate1.prototype.makeActive = function(pickResult) {
+ o3djs.manipulators.Manip.prototype.makeActive.call(this, pickResult);
+ this.highlight(pickResult);
+ var worldMatrix = this.getTransform().worldMatrix;
+ this.dragPlane_.setNormal(
+ o3djs.math.matrix4.transformDirection(worldMatrix,
+ o3djs.manipulators.X_AXIS));
+ this.dragPlane_.setPoint(pickResult.worldIntersectionPosition);
+}
+
+o3djs.manipulators.Rotate1.prototype.makeInactive = function() {
+ o3djs.manipulators.Manip.prototype.makeInactive.call(this);
+ this.clearHighlight();
+ this.updateAttachedTransformFromLocalTransform_();
+ this.updateBaseTransformFromAttachedTransform_();
+}
+
+o3djs.manipulators.Rotate1.prototype.drag = function(startPoint,
+ endPoint) {
+ // Algorithm: Find intersection of ray with dragPlane_. Transform
+ // everything from world to local coordinates. Find angle of the
+ // initial and final plane intersection points about the rotation
+ // axis. Subtract these to find the rotation angle.
+ var worldIntersectPoint = this.dragPlane_.intersectRay(startPoint,
+ o3djs.math.subVector(endPoint, startPoint));
+ if (worldIntersectPoint == null) {
+ // Drag plane is parallel to ray. Punt.
+ return;
+ }
+
+ // We don't want the current drag state to affect our world-to-local
+ // transform, since we are calculating the drag from scratch.
+ this.getTransform().localMatrix = o3djs.math.matrix4.identity();
+
+ // Need to do a world-to-local transformation on all the points.
+ var worldToLocal =
+ o3djs.math.matrix4.inverse(this.getTransform().worldMatrix);
+
+ // All of these are in local space.
+ var dragStart = o3djs.math.matrix4.transformPoint(worldToLocal,
+ this.dragPlane_.getPoint());
+ var dragEnd = o3djs.math.matrix4.transformPoint(worldToLocal,
+ worldIntersectPoint);
+ // Since this should all be happening in a YZ plane, we can discard
+ // the X components.
+ dragStart[0] = 0;
+ dragEnd[0] = 0;
+
+ // The point that we are rotating around is the origin (in local space).
+
+ var diffAngle = Math.atan2(dragEnd[1], dragEnd[2]) -
+ Math.atan2(dragStart[1], dragStart[2]);
+
+ this.getTransform().localMatrix = o3djs.math.matrix4.rotationX(-diffAngle);
+ this.updateAttachedTransformFromLocalTransform_();
+}
diff --git a/o3d/samples/o3djs/primitives.js b/o3d/samples/o3djs/primitives.js
index 0a062f8..e2177dc 100644
--- a/o3d/samples/o3djs/primitives.js
+++ b/o3d/samples/o3djs/primitives.js
@@ -1281,8 +1281,8 @@ o3djs.primitives.createTruncatedConeVertices = function(bottomRadius,
radialSubdivisions,
verticalSubdivisions,
opt_matrix) {
- if (radialSubdivisions < 1) {
- throw Error('radialSubdivisions must be 1 or greater');
+ if (radialSubdivisions < 3) {
+ throw Error('radialSubdivisions must be 3 or greater');
}
if (verticalSubdivisions < 1) {
@@ -1297,8 +1297,6 @@ o3djs.primitives.createTruncatedConeVertices = function(bottomRadius,
var texCoordStream = vertexInfo.addStream(
2, o3djs.base.o3d.Stream.TEXCOORD, 0);
- var indices = [];
- var vertices = [];
var vertsAroundEdge = radialSubdivisions + 1;
// The slant of the cone is constant across its surface
@@ -1317,7 +1315,7 @@ o3djs.primitives.createTruncatedConeVertices = function(bottomRadius,
} else if (yy > verticalSubdivisions) {
y = height;
v = 1;
- ringRadius = topRadius;
+ ringRadius = topRadius;
} else {
ringRadius = bottomRadius +
(topRadius - bottomRadius) * (yy / verticalSubdivisions);
@@ -1339,7 +1337,6 @@ o3djs.primitives.createTruncatedConeVertices = function(bottomRadius,
}
}
- var trisAround = radialSubdivisions * 2;
for (var yy = 0; yy < verticalSubdivisions + 4; ++yy) {
for (var ii = 0; ii < radialSubdivisions; ++ii) {
vertexInfo.addTriangle(vertsAroundEdge * (yy + 0) + 0 + ii,
@@ -1362,8 +1359,8 @@ o3djs.primitives.createTruncatedConeVertices = function(bottomRadius,
* that it has different top and bottom radii. A truncated cone can
* also be used to create cylinders, by setting the bottom and top
* radii equal, and cones, by setting either the top or bottom radius
- * to 0. The truncated cone will be created with the bottom face in
- * the xz plane, and the y axis in the center. The created cone has
+ * to 0. The truncated cone will be created centered about the origin,
+ * with the y axis as its vertical axis. The created cone has
* position, normal and uv streams.
*
* @param {!o3d.Pack} pack Pack in which to create the truncated cone.
@@ -1398,6 +1395,117 @@ o3djs.primitives.createTruncatedCone = function(pack,
};
/**
+ * Creates vertices for a torus. The torus will be created centered about the
+ * origin, with the y axis as its vertical axis. The created torus has
+ * position, normal and uv streams.
+ *
+ * @param {number} torusRadius Distance from the center of the tube to
+ * the center of the torus.
+ * @param {number} tubeRadius Radius of the tube.
+ * @param {number} tubeLengthSubdivisions The number of subdivisions around the
+ * vertical axis of the torus, i.e. along the length of the tube.
+ * @param {number} circleSubdivisions The number of subdivisions in the circle
+ * that is rotated about the vertical axis to create the torus.
+ * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply
+ * all the vertices.
+ * @return {!o3djs.primitives.VertexInfo} The created torus vertices.
+ */
+o3djs.primitives.createTorusVertices = function(torusRadius,
+ tubeRadius,
+ tubeLengthSubdivisions,
+ circleSubdivisions,
+ opt_matrix) {
+ if (tubeLengthSubdivisions < 3) {
+ throw Error('tubeLengthSubdivisions must be 3 or greater');
+ }
+
+ if (circleSubdivisions < 3) {
+ throw Error('circleSubdivisions must be 3 or greater');
+ }
+
+ var vertexInfo = o3djs.primitives.createVertexInfo();
+ var positionStream = vertexInfo.addStream(
+ 3, o3djs.base.o3d.Stream.POSITION);
+ var normalStream = vertexInfo.addStream(
+ 3, o3djs.base.o3d.Stream.NORMAL);
+ var texCoordStream = vertexInfo.addStream(
+ 2, o3djs.base.o3d.Stream.TEXCOORD, 0);
+
+ for (var uu = 0; uu < tubeLengthSubdivisions; ++uu) {
+ var u = (uu / tubeLengthSubdivisions) * 2 * Math.PI;
+ for (var vv = 0; vv < circleSubdivisions; ++vv) {
+ var v = (vv / circleSubdivisions) * 2 * Math.PI;
+ var sinu = Math.sin(u);
+ var cosu = Math.cos(u);
+ var sinv = Math.sin(v);
+ var cosv = Math.cos(v);
+ positionStream.addElement((torusRadius + tubeRadius * cosv) * cosu,
+ tubeRadius * sinv,
+ (torusRadius + tubeRadius * cosv) * sinu);
+ normalStream.addElement(cosv * cosu,
+ sinv,
+ cosv * sinu);
+ texCoordStream.addElement(uu / tubeLengthSubdivisions,
+ vv / circleSubdivisions);
+ }
+ }
+
+ for (var uu = 0; uu < tubeLengthSubdivisions; ++uu) {
+ for (var vv = 0; vv < circleSubdivisions; ++vv) {
+ // We want to wrap the indices around at the seams.
+ var uuPlusOne = (uu + 1) % tubeLengthSubdivisions;
+ var vvPlusOne = (vv + 1) % circleSubdivisions;
+ // The indices of four points forming a quad.
+ var a = circleSubdivisions * uu + vv;
+ var b = circleSubdivisions * uuPlusOne + vv;
+ var c = circleSubdivisions * uu + vvPlusOne;
+ var d = circleSubdivisions * uuPlusOne + vvPlusOne;
+ vertexInfo.addTriangle(a, d, b);
+ vertexInfo.addTriangle(a, c, d);
+ }
+ }
+
+ if (opt_matrix) {
+ vertexInfo.reorient(opt_matrix);
+ }
+ return vertexInfo;
+};
+
+/**
+ * Creates a torus shape. The torus will be created centered about the
+ * origin, with the y axis as its vertical axis. The created torus has
+ * position, normal and uv streams.
+ *
+ * @param {!o3d.Pack} pack Pack in which to create the torus.
+ * @param {!o3d.Material} material to use.
+ * @param {number} torusRadius Distance from the center of the tube to
+ * the center of the torus.
+ * @param {number} tubeRadius Radius of the tube.
+ * @param {number} tubeLengthSubdivisions The number of subdivisions around the
+ * vertical axis of the torus, i.e. along the length of the tube.
+ * @param {number} circleSubdivisions The number of subdivisions in the circle
+ * that is rotated about the vertical axis to create the torus.
+ * @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply
+ * all the vertices.
+ * @return {!o3d.Shape} The created torus.
+ */
+o3djs.primitives.createTorus = function(pack,
+ material,
+ torusRadius,
+ tubeRadius,
+ tubeLengthSubdivisions,
+ circleSubdivisions,
+ opt_matrix) {
+ var vertexInfo = o3djs.primitives.createTorusVertices(
+ torusRadius,
+ tubeRadius,
+ tubeLengthSubdivisions,
+ circleSubdivisions,
+ opt_matrix);
+ return vertexInfo.createShape(pack, material);
+};
+
+/**
* Creates wedge vertices, wedge being an extruded triangle. The wedge will be
* created around the 3 2d points passed in and extruded along the z axis. The
* created wedge has position, normal and uv streams.
@@ -1407,7 +1515,7 @@ o3djs.primitives.createTruncatedCone = function(pack,
* @param {number} depth The depth to extrude the triangle.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply
* all the vertices.
- * @return {!o3djs.primitives.VertexInfo} The created cylinder vertices.
+ * @return {!o3djs.primitives.VertexInfo} The created wedge vertices.
*/
o3djs.primitives.createWedgeVertices = function(inPoints, depth,
opt_matrix) {
@@ -1424,7 +1532,6 @@ o3djs.primitives.createWedgeVertices = function(inPoints, depth,
var z1 = -depth * 0.5;
var z2 = depth * 0.5;
var face = [];
- var indices = [];
var points = [[inPoints[0][0], inPoints[0][1]],
[inPoints[1][0], inPoints[1][1]],
[inPoints[2][0], inPoints[2][1]]];
@@ -1506,14 +1613,14 @@ o3djs.primitives.createWedgeVertices = function(inPoints, depth,
normalStream.addElement(face[2][0], face[2][1], face[2][2]);
texCoordStream.addElement(1, 1);
- var indices = [0, 2, 1,
- 3, 4, 5,
- 6, 7, 8,
- 6, 8, 9,
- 10, 11, 12,
- 10, 12, 13,
- 14, 15, 16,
- 14, 16, 17];
+ vertexInfo.addTriangle(0, 2, 1);
+ vertexInfo.addTriangle(3, 4, 5);
+ vertexInfo.addTriangle(6, 7, 8);
+ vertexInfo.addTriangle(6, 8, 9);
+ vertexInfo.addTriangle(10, 11, 12);
+ vertexInfo.addTriangle(10, 12, 13);
+ vertexInfo.addTriangle(14, 15, 16);
+ vertexInfo.addTriangle(14, 16, 17);
if (opt_matrix) {
vertexInfo.reorient(opt_matrix);
@@ -1559,10 +1666,10 @@ o3djs.primitives.createWedge = function(pack,
*
* @param {!Array.<!Array.<number>>} points Array of 2d points in the format
* [[x1, y1], [x2, y2], [x3, y3],...] that describe a 2d polygon.
- * @param {number} depth The depth to extrude the triangle.
+ * @param {number} depth The depth to extrude the polygon.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply
* all the vertices.
- * @return {!o3djs.primitives.VertexInfo} The created cylinder vertices.
+ * @return {!o3djs.primitives.VertexInfo} The created prism vertices.
*/
o3djs.primitives.createPrismVertices = function(points,
depth,
@@ -1690,10 +1797,10 @@ o3djs.primitives.createPrismVertices = function(points,
* @param {!o3d.Material} material to use.
* @param {!Array.<!Array.<number>>} points Array of 2d points in the format:
* [[x1, y1], [x2, y2], [x3, y3],...] that describe a 2d polygon.
- * @param {number} depth The depth to extrude the triangle.
+ * @param {number} depth The depth to extrude the polygon.
* @param {!o3djs.math.Matrix4} opt_matrix A matrix by which to multiply
* all the vertices.
- * @return {!o3d.Shape} The created wedge.
+ * @return {!o3d.Shape} The created prism.
*/
o3djs.primitives.createPrism = function(pack,
material,