summaryrefslogtreecommitdiffstats
path: root/o3d/samples/o3djs
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/samples/o3djs')
-rw-r--r--o3d/samples/o3djs/manipulators.js157
-rw-r--r--o3d/samples/o3djs/primitives.js151
2 files changed, 274 insertions, 34 deletions
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,