summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 02:38:29 +0000
committergman@google.com <gman@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-07-28 02:38:29 +0000
commitfd78ee7284351ee6284299fcf57559a78da3b48a (patch)
treec6415495a590e3d6823b0bef9c562289a0b9822f
parentb6f148453fcbdcf777f71f26da8674ede5b81dce (diff)
downloadchromium_src-fd78ee7284351ee6284299fcf57559a78da3b48a.zip
chromium_src-fd78ee7284351ee6284299fcf57559a78da3b48a.tar.gz
chromium_src-fd78ee7284351ee6284299fcf57559a78da3b48a.tar.bz2
Changes to picking example to show how to get
the surface normal for the spot picked. Apparently no screenshots are taken for picking so no deps files need up be updated Review URL: http://codereview.chromium.org/159442 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@21805 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--o3d/samples/o3djs/element.js68
-rw-r--r--o3d/samples/o3djs/picking.js38
-rw-r--r--o3d/samples/picking.html57
3 files changed, 148 insertions, 15 deletions
diff --git a/o3d/samples/o3djs/element.js b/o3d/samples/o3djs/element.js
index aedcacb..0c4593b 100644
--- a/o3d/samples/o3djs/element.js
+++ b/o3d/samples/o3djs/element.js
@@ -141,4 +141,72 @@ o3djs.element.duplicateElement = function(pack, sourceElement) {
return newElement;
};
+/**
+ * Gets the normal for specific triangle in a Primitive in that Primitive's
+ * local space.
+ *
+ * NOTE: THIS FUNCTION IS SLOW! If you want to do collisions you should use a
+ * different solution.
+ *
+ * @param {!o3d.Primitive} primitive Primitive to get normal from. The
+ * primitive MUST be a TRIANGLELIST or a TRIANGLESTRIP and it must have a
+ * POSITION,0 stream.
+ * @param {number} index Index of triangle.
+ * @param {boolean} opt_winding The winding of the triangles of the
+ * Primitive. False = Clockwise, True = Counterclockwise. The default is
+ * false. This is only used for Primitives that have no normals.
+ * @return {!o3djs.math.Vector3} The normal for the triangle.
+ */
+o3djs.element.getNormalForTriangle = function(primitive, index, opt_winding) {
+ // Check that we can do this
+ var primitiveType = primitive.primitiveType;
+ if (primitiveType != o3djs.base.o3d.Primitive.TRIANGLELIST &&
+ primitiveType != o3djs.base.o3d.Primitive.TRIANGLESTRIP) {
+ throw 'primitive is not a TRIANGLELIST or TRIANGLESTRIP';
+ }
+
+ var indexBuffer = primitive.indexBuffer;
+ var vertexIndex = (primitiveType == o3djs.base.o3d.Primitive.TRIANGLELIST) ?
+ (index * 3) : (index + 2);
+ var vertexIndices;
+ if (indexBuffer) {
+ var indexField = indexBuffer.fields[0];
+ vertexIndices = indexField.getAt(vertexIndex, 3);
+ } else {
+ vertexIndices = [vertexIndex, vertexIndex + 1, vertexIndex + 2]
+ }
+
+ var normalStream = primitive.streamBank.getVertexStream(
+ o3djs.base.o3d.Stream.NORMAL, 0);
+ if (normalStream) {
+ var normalField = normalStream.field;
+ // Look up the 3 normals that make the triangle.
+ var summedNormal = [0, 0, 0];
+ for (var ii = 0; ii < 3; ++ii) {
+ var normal = normalField.getAt(vertexIndices[ii], 1);
+ summedNormal = o3djs.math.addVector(summedNormal, normal);
+ }
+ return o3djs.math.normalize(summedNormal);
+ } else {
+ var positionStream = primitive.streamBank.getVertexStream(
+ o3djs.base.o3d.Stream.POSITION, 0);
+ if (!positionStream) {
+ throw 'no POSITION,0 stream in primitive';
+ }
+ var positionField = positionStream.field;
+ // Lookup the 3 positions that make the triangle.
+ var positions = [];
+ for (var ii = 0; ii < 3; ++ii) {
+ positions[ii] = positionField.getAt(vertexIndices[ii], 1);
+ }
+
+ // Compute a face normal from the positions.
+ var v0 = o3djs.math.normalize(o3djs.math.subVector(positions[1],
+ positions[0]));
+ var v1 = o3djs.math.normalize(o3djs.math.subVector(positions[2],
+ positions[1]));
+ return opt_winding ? o3djs.math.cross(v1, v0) : o3djs.math.cross(v0, v1);
+ }
+};
+
diff --git a/o3d/samples/o3djs/picking.js b/o3d/samples/o3djs/picking.js
index a40eb5d..06e3765 100644
--- a/o3d/samples/o3djs/picking.js
+++ b/o3d/samples/o3djs/picking.js
@@ -70,18 +70,20 @@ o3djs.picking.Ray = goog.typedef;
/**
* Creates a new PickInfo.
- * @param {!o3djs.picking.ShapeInfo} shapeInfo The ShapeInfo that
- * was picked.
- * @param {!o3d.RayIntersectionInfo} rayIntersectionInfo Information
- * about the pick.
- * @param {!o3djs.math.Vector3} worldIntersectionPosition
- * world position of intersection.
+ * @param {!o3d.Element} element The Element that was picked.
+ * @param {!o3djs.picking.ShapeInfo} shapeInfo The ShapeInfo that was picked.
+ * @param {!o3d.RayIntersectionInfo} rayIntersectionInfo Information about the
+ * pick.
+ * @param {!o3djs.math.Vector3} worldIntersectionPosition world position of
+ * intersection.
* @return {!o3djs.picking.PickInfo} The new PickInfo.
*/
-o3djs.picking.createPickInfo = function(shapeInfo,
+o3djs.picking.createPickInfo = function(element,
+ shapeInfo,
rayIntersectionInfo,
worldIntersectionPosition) {
- return new o3djs.picking.PickInfo(shapeInfo,
+ return new o3djs.picking.PickInfo(element,
+ shapeInfo,
rayIntersectionInfo,
worldIntersectionPosition);
};
@@ -219,17 +221,24 @@ o3djs.picking.dumpRayIntersectionInfo = function(label,
/**
* Creates a new PickInfo. Used to return picking information.
* @constructor
- * @param {!o3djs.picking.ShapeInfo} shapeInfo The ShapeInfo that
- * was picked.
- * @param {!o3d.RayIntersectionInfo} rayIntersectionInfo Information
- * about the pick.
+ * @param {!o3d.Element} element The Element that was picked.
+ * @param {!o3djs.picking.ShapeInfo} shapeInfo The ShapeInfo that was picked.
+ * @param {!o3d.RayIntersectionInfo} rayIntersectionInfo Information about the
+ * pick.
* @param {!o3djs.math.Vector3} worldIntersectionPosition world position of
* intersection.
*/
-o3djs.picking.PickInfo = function(shapeInfo,
+o3djs.picking.PickInfo = function(element,
+ shapeInfo,
rayIntersectionInfo,
worldIntersectionPosition) {
/**
+ * The Element that was picked (Primitive).
+ * @type {!o3d.Element}
+ */
+ this.element = element;
+
+ /**
* The ShapeInfo that was picked.
* @type {!o3djs.picking.ShapeInfo}
*/
@@ -335,7 +344,8 @@ o3djs.picking.ShapeInfo.prototype.pick = function(worldRay) {
if (rayIntersectionInfo.intersected) {
var worldIntersectionPosition = o3djs.math.matrix4.transformPoint(
worldMatrix, rayIntersectionInfo.position);
- return o3djs.picking.createPickInfo(this,
+ return o3djs.picking.createPickInfo(element,
+ this,
rayIntersectionInfo,
worldIntersectionPosition);
}
diff --git a/o3d/samples/picking.html b/o3d/samples/picking.html
index cd9ddd1..ae62ebd 100644
--- a/o3d/samples/picking.html
+++ b/o3d/samples/picking.html
@@ -56,7 +56,7 @@ O3D Picking Example.
<!-- Include default javascript library functions-->
<script type="text/javascript" src="o3djs/base.js"></script>
<!-- Our javascript code -->
-<script type="text/javascript">
+<script type="text/javascript" id="o3d">
o3djs.require('o3djs.util');
o3djs.require('o3djs.math');
o3djs.require('o3djs.rendergraph');
@@ -64,6 +64,7 @@ o3djs.require('o3djs.pack');
o3djs.require('o3djs.camera');
o3djs.require('o3djs.picking');
o3djs.require('o3djs.scene');
+o3djs.require('o3djs.debug');
// Events
// init() once the page has finished loading.
@@ -71,6 +72,9 @@ o3djs.require('o3djs.scene');
window.onload = init;
window.onunload = unload;
+// constants
+var NORMAL_SCALE_FACTOR = 2.0;
+
// global variables
var g_o3d;
var g_math;
@@ -79,6 +83,9 @@ var g_pack;
var g_viewInfo;
var g_treeInfo; // information about the transform graph.
var g_pickInfoElem;
+var g_debugHelper;
+var g_debugLineGroup;
+var g_debugLine;
var g_selectedInfo = null;
var g_flashTimer = 0;
var g_highlightMaterial;
@@ -135,13 +142,53 @@ function pick(e) {
unSelectAll();
// Update the entire tree in case anything moved.
+ // NOTE: This function is very SLOW!
+ // If you really want to use picking you should manually update only those
+ // transforms and shapes that moved, were added, or deleted by writing your
+ // own picking library. You should also make sure that you are only
+ // considering things that are pickable. By that I mean if you have a scene of
+ // a meadow with trees, grass, bushes, and animals and the only thing the user
+ // can pick is the animals then put the animals on their own sub branch of the
+ // transform graph and only pick against that subgraph.
+ // Even better, make a separate transform graph with only cubes on it to
+ // represent the animals and use that instead of the actual animals.
g_treeInfo.update();
var pickInfo = g_treeInfo.pick(worldRay);
if (pickInfo) {
select(pickInfo);
g_pickInfoElem.innerHTML = pickInfo.shapeInfo.shape.name;
+
+ // Display the normal
+ // NOTE: Lookup the normal with this function is very SLOW!!
+ // If you need performance, for a game or something, you should consider
+ // other methods.
+ var normal = o3djs.element.getNormalForTriangle(
+ pickInfo.element,
+ pickInfo.rayIntersectionInfo.primitiveIndex);
+
+ // Convert the normal from local to world space.
+ normal = g_math.matrix4.transformNormal(
+ pickInfo.shapeInfo.parent.transform.worldMatrix,
+ normal);
+
+ // Remove the scale from the normal.
+ normal = g_math.normalize(normal);
+
+ // Get the world position of the collision.
+ var worldPosition = pickInfo.worldIntersectionPosition;
+
+ // Add the normal to it to get a point in space above it with some
+ // multiplier to scale it.
+ var normalSpot = g_math.addVector(
+ worldPosition,
+ g_math.mulVectorScalar(normal, NORMAL_SCALE_FACTOR));
+
+ // Move our debug line to show the normal
+ g_debugLine.setVisible(true);
+ g_debugLine.setEndPoints(worldPosition, normalSpot);
} else {
+ g_debugLine.setVisible(false);
g_pickInfoElem.innerHTML = '--nothing--';
}
}
@@ -238,6 +285,14 @@ function initStep2(clientElements) {
g_client.root,
g_client.renderGraphRoot);
+ // Use the debug library to create a line we can position to show
+ // the normal.
+ g_debugHelper = o3djs.debug.createDebugHelper(g_client.createPack(),
+ g_viewInfo);
+ g_debugLineGroup = g_debugHelper.createDebugLineGroup(g_client.root);
+ g_debugLine = g_debugLineGroup.addLine();
+ g_debugLine.setColor([0,1,0,1]);
+
// Create a material for highlighting.
g_highlightMaterial = g_pack.createObject('Material');
g_highlightMaterial.drawList = g_viewInfo.performanceDrawList;