summaryrefslogtreecommitdiffstats
path: root/o3d
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-03 00:30:36 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-03 00:30:36 +0000
commit8dc465e39dd10bd23a4f24481d2bf146404596a7 (patch)
treee0da44eaee7bd4402a9844e1b68c50149cd290dd /o3d
parentacaae862120b887d04432fd81e2c2c47cbd1256c (diff)
downloadchromium_src-8dc465e39dd10bd23a4f24481d2bf146404596a7.zip
chromium_src-8dc465e39dd10bd23a4f24481d2bf146404596a7.tar.gz
chromium_src-8dc465e39dd10bd23a4f24481d2bf146404596a7.tar.bz2
Updates the picking library to have a PickManager and
support both not picking invisible objects and the option to pick even if invisible. The idea is you can do something like this // Make a picking manager var pm = o3djs.picking.createPickManager(rootTransform); ... // add a bunch of transforms. // generate picking objects. pm.update(); // Get the picking object that was created for some specific transform var info = pm.getTransformInfo(someTransform); // Set properties on that object related to picking info.pickEvenIfInvisible = true; I think this is just a first step. How an object should be defined as pickable is up for debate. As it is, you can basically override info.isPickable. as in info.isPickable = function() { // do something custom. } You can also start adding things easier like info.onPick = function() { // do something. } and then write code like info = pm.pick(worldRay); if (info) { info.onPick(); } While you could have done that before there was no easy way to find a the TransformInfo for a specific Transform. Now you can use PickManager.getTransformInfo Review URL: http://codereview.chromium.org/452027 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r--o3d/samples/checkers.html16
-rw-r--r--o3d/samples/home-configurators/deletetool.js6
-rw-r--r--o3d/samples/home-configurators/movetool.js8
-rw-r--r--o3d/samples/home-configurators/rotatetool.js6
-rw-r--r--o3d/samples/home-configurators/viewer.js3
-rw-r--r--o3d/samples/o3djs/manipulators.js25
-rw-r--r--o3d/samples/o3djs/picking.js348
-rw-r--r--o3d/samples/picking.html23
8 files changed, 307 insertions, 128 deletions
diff --git a/o3d/samples/checkers.html b/o3d/samples/checkers.html
index 219bc6f..9275bfe 100644
--- a/o3d/samples/checkers.html
+++ b/o3d/samples/checkers.html
@@ -74,7 +74,7 @@ var g_thisRot;
var g_lastRot;
var g_zoomFactor;
var g_dragging = false;
-var g_treeInfo; // information about the transform graph.
+var g_pickManager; // information about the transform graph.
var g_statusInfoElem;
// Animation globals.
@@ -354,7 +354,7 @@ function createCheckersBoard() {
}
// Update our tree info.
- updateTreeInfo();
+ updateg_pickManager();
// update status.
updateStatus('Game starting... RED moves first.', true);
@@ -391,11 +391,11 @@ function checkAndUpdateKing(x, y) {
/**
* Updates the transform tree info.
*/
-function updateTreeInfo() {
- if (!g_treeInfo) {
- g_treeInfo = o3djs.picking.createTransformInfo(g_client.root, null);
+function updateg_pickManager() {
+ if (!g_pickManager) {
+ g_pickManager = o3djs.picking.createPickManager(g_client.root);
}
- g_treeInfo.update();
+ g_pickManager.update();
}
/**
@@ -577,7 +577,7 @@ function detectSelection(e) {
g_client.height);
// check if we picked any objects.
- var pickInfo = g_treeInfo.pick(worldRay);
+ var pickInfo = g_pickManager.pick(worldRay);
if (pickInfo) {
// get the parent transform of this object.
var pickTrans = pickInfo.shapeInfo.parent.transform;
@@ -774,7 +774,7 @@ function moveSelectedPiece(elapsedTime) {
g_moveTimer = 0;
// update the tree info.
- updateTreeInfo();
+ updateg_pickManager();
// check if current player can jump again.
if (wasJump && pieceCanJump(g_board[x1][y1])) {
diff --git a/o3d/samples/home-configurators/deletetool.js b/o3d/samples/home-configurators/deletetool.js
index 616303bb..022d65f 100644
--- a/o3d/samples/home-configurators/deletetool.js
+++ b/o3d/samples/home-configurators/deletetool.js
@@ -38,7 +38,7 @@
function DeleteTool(context, root) {
this.context = context;
this.root = root;
- this.transformInfo = o3djs.picking.createTransformInfo(root, null);
+ this.pickManager = g_pickManager;
this.selectedObject = null;
}
@@ -48,8 +48,8 @@ DeleteTool.prototype.getPickedObject = function(e) {
this.context,
g_client.width,
g_client.height);
- this.transformInfo.update();
- var pickInfo = this.transformInfo.pick(worldRay);
+ this.pickManager.update();
+ var pickInfo = this.pickManager.pick(worldRay);
var picked_object_root = null;
if (pickInfo) {
pickedObject = pickInfo.shapeInfo.parent;
diff --git a/o3d/samples/home-configurators/movetool.js b/o3d/samples/home-configurators/movetool.js
index d0db043..5d0e190 100644
--- a/o3d/samples/home-configurators/movetool.js
+++ b/o3d/samples/home-configurators/movetool.js
@@ -40,7 +40,7 @@ function MoveTool(context, root) {
this.lastMove = null;
this.context = context;
this.root = root;
- this.transformInfo = o3djs.picking.createTransformInfo(root, null);
+ this.pickManager = g_pickManager;
this.movePlane = [0.0, 0.0, 1.0];
this.downPoint = null;
this.selectedObject = null;
@@ -51,7 +51,7 @@ function MoveTool(context, root) {
* (the same node as would be found by our picking code)
*/
MoveTool.prototype.initializeWithShape = function(transform_node) {
- this.transformInfo.update();
+ this.pickManager.update();
translation = g_math.matrix4.getTranslation(
transform_node.getUpdatedWorldMatrix());
this.downPoint = translation;
@@ -65,9 +65,9 @@ MoveTool.prototype.handleMouseDown = function(e) {
this.context,
g_client.width,
g_client.height);
- this.transformInfo.update();
+ this.pickManager.update();
this.selectedObject = null;
- var pickInfo = this.transformInfo.pick(worldRay);
+ var pickInfo = this.pickManager.pick(worldRay);
if (pickInfo) {
pickedObject = pickInfo.shapeInfo.parent;
while (pickedObject.parent != null &&
diff --git a/o3d/samples/home-configurators/rotatetool.js b/o3d/samples/home-configurators/rotatetool.js
index 9bf852b..2a78a2a4 100644
--- a/o3d/samples/home-configurators/rotatetool.js
+++ b/o3d/samples/home-configurators/rotatetool.js
@@ -42,7 +42,7 @@ function RotateTool(context, root) {
this.context = context;
this.selectedObject = null;
this.root = root;
- this.transformInfo = o3djs.picking.createTransformInfo(root, null);
+ this.pickManager = g_pickManager;
this.rotateAxis = [0.0, 0.0, 1.0];
this.rotateCenter = null;
}
@@ -56,8 +56,8 @@ RotateTool.prototype.handleMouseDown = function(e) {
this.context,
window_width,
window_height);
- this.transformInfo.update();
- var pickInfo = this.transformInfo.pick(worldRay);
+ this.pickManager.update();
+ var pickInfo = this.pickManager.pick(worldRay);
if (pickInfo) {
pickedObject = pickInfo.shapeInfo.parent;
while (pickedObject.parent != null &&
diff --git a/o3d/samples/home-configurators/viewer.js b/o3d/samples/home-configurators/viewer.js
index 69c4fb7..2e334f4 100644
--- a/o3d/samples/home-configurators/viewer.js
+++ b/o3d/samples/home-configurators/viewer.js
@@ -54,6 +54,7 @@ var g_lastRot;
var g_pack = null;
var g_mainPack;
var g_viewInfo;
+var g_pickManager;
var g_lightPosParam;
var g_currentTool = null;
var g_floorplanRoot = null;
@@ -428,6 +429,8 @@ function loadFile(context, path) {
// Put the object we're loading on the floorplan.
new_object_root = g_floorplanRoot;
+ g_pickManager = o3djs.picking.createPickManager(g_placedModelsRoot);
+
// Create our set of tools that can be activated.
// Note: Currently only the Delete, Move, Rotate, Orbit, Pan and Zoom
// tools are implemented. The last four icons in the toolbar are unused.
diff --git a/o3d/samples/o3djs/manipulators.js b/o3d/samples/o3djs/manipulators.js
index 7bea7a5..85fb611 100644
--- a/o3d/samples/o3djs/manipulators.js
+++ b/o3d/samples/o3djs/manipulators.js
@@ -511,11 +511,11 @@ o3djs.manipulators.Manager = function(pack,
this.manipsByClientId = [];
/**
- * Presumably we need a TransformInfo for the parentTransform.
+ * A PickManager to manage picking for the manipulators.
* @type {!o3djs.picking.TransformInfo}
*/
- this.transformInfo =
- o3djs.picking.createTransformInfo(this.parentTransform, null);
+ this.pickManager =
+ o3djs.picking.createPickManager(this.parentTransform);
/**
* The currently-highlighted manipulator.
@@ -614,7 +614,7 @@ o3djs.manipulators.Manager.prototype.handleMouse_ = function(x,
width,
height,
func) {
- this.transformInfo.update();
+ this.pickManager.update();
// Create the world ray
var worldRay =
@@ -623,7 +623,7 @@ o3djs.manipulators.Manager.prototype.handleMouse_ = function(x,
width, height);
// Pick against all of the manipulators' geometry
- var pickResult = this.transformInfo.pick(worldRay);
+ var pickResult = this.pickManager.pick(worldRay);
if (pickResult != null) {
// Find which manipulator we picked.
// NOTE this assumes some things about the transform graph
@@ -1159,8 +1159,9 @@ o3djs.manipulators.Translate1 = function(manager) {
this.addShapes_([ shape ]);
- this.transformInfo = o3djs.picking.createTransformInfo(this.getTransform(),
- manager.transformInfo);
+ this.transformInfo = manager.pickManager.createTransformInfo(
+ this.getTransform(),
+ manager.transformInfo);
/**
* A parameter added to our transform to be able to change the
@@ -1270,8 +1271,9 @@ o3djs.manipulators.Translate2 = function(manager) {
this.addShapes_([ shape ]);
- this.transformInfo = o3djs.picking.createTransformInfo(this.getTransform(),
- manager.transformInfo);
+ this.transformInfo = manager.pickManager.createTransformInfo(
+ this.getTransform(),
+ manager.transformInfo);
/**
* A parameter added to our transform to be able to change the
@@ -1383,8 +1385,9 @@ o3djs.manipulators.Rotate1 = function(manager) {
this.addShapes_([ shape ]);
- this.transformInfo = o3djs.picking.createTransformInfo(this.getTransform(),
- manager.transformInfo);
+ this.transformInfo = manager.pickManager.createTransformInfo(
+ this.getTransform(),
+ manager.transformInfo);
/**
* A parameter added to our transform to be able to change the
diff --git a/o3d/samples/o3djs/picking.js b/o3d/samples/o3djs/picking.js
index 409104d..a67de17 100644
--- a/o3d/samples/o3djs/picking.js
+++ b/o3d/samples/o3djs/picking.js
@@ -89,27 +89,6 @@ o3djs.picking.createPickInfo = function(element,
};
/**
- * Creates a new ShapeInfo.
- * @param {!o3d.Shape} shape Shape to keep info about.
- * @param {!o3djs.picking.TransformInfo} parent Parent transform of the shape.
- * @return {!o3djs.picking.ShapeInfo} The new ShapeInfo.
- */
-o3djs.picking.createShapeInfo = function(shape, parent) {
- return new o3djs.picking.ShapeInfo(shape, parent);
-};
-
-/**
- * Creates a new TransformInfo.
- * @param {!o3d.Transform} transform Transform to keep info about.
- * @param {o3djs.picking.TransformInfo} parent Parent transform of the
- * transform. Can be null.
- * @return {!o3djs.picking.TransformInfo} The new TransformInfo.
- */
-o3djs.picking.createTransformInfo = function(transform, parent) {
- return new o3djs.picking.TransformInfo(transform, parent);
-};
-
-/**
* Convert a pixel position relative to the top left corner of the client area
* into the corresponding ray through the frustum in world space.
* @param {number} clientXPosition x position relative to client area.
@@ -205,9 +184,10 @@ o3djs.picking.dprintBoundingBox = function(label,
*/
o3djs.picking.dumpRayIntersectionInfo = function(label,
rayIntersectionInfo) {
- o3djs.picking.dprint(label + ' : valid = ' +
- rayIntersectionInfo.valid + ' : intersected = ' +
- rayIntersectionInfo.intersected);
+ o3djs.picking.dprint(
+ label + ' : valid = ' +
+ rayIntersectionInfo.valid + ' : intersected = ' +
+ rayIntersectionInfo.intersected);
if (rayIntersectionInfo.intersected) {
o3djs.picking.dprint(
' : pos: ' +
@@ -258,12 +238,16 @@ o3djs.picking.PickInfo = function(element,
};
/**
- * Creates a new ShapeInfo. Used to store information about Shapes.
+ * Creates a new ShapeInfo. Used to store information about Shapes. Note, even
+ * though Shapes can be instanced, ShapeInfos can not so if a Shape is instanced
+ * there will be more than one ShapeInfo for it.
* @constructor
* @param {!o3d.Shape} shape Shape to keep info about.
* @param {!o3djs.picking.TransformInfo} parent Parent transform of the shape.
+ * @param {!o3djs.picking.PickManager} pickManager The PickManager this
+ * ShapeInfo belongs to.
*/
-o3djs.picking.ShapeInfo = function(shape, parent) {
+o3djs.picking.ShapeInfo = function(shape, parent, pickManager) {
/**
* The Shape for this ShapeInfo
* @type {!o3d.Shape}
@@ -282,10 +266,24 @@ o3djs.picking.ShapeInfo = function(shape, parent) {
*/
this.boundingBox = null;
+ /**
+ * The PickManager this ShapeInfo belongs to.
+ * @type {!o3djs.picking.PickManager}
+ */
+ this.pickManager = pickManager;
+
this.update();
};
/**
+ * Returns whether or not this ShapeInfo is pickable.
+ * @return {boolean} Whether or not this ShapeInfo is pickable.
+ */
+o3djs.picking.ShapeInfo.prototype.isPickable = function() {
+ return true;
+}
+
+/**
* Gets the BoundingBox of the Shape in this ShapeInfo.
* @return {o3d.BoundingBox} The Shape's BoundingBox.
*/
@@ -314,40 +312,42 @@ o3djs.picking.ShapeInfo.prototype.update = function() {
* null if the ray did not intersect any triangles.
*/
o3djs.picking.ShapeInfo.prototype.pick = function(worldRay) {
- var worldMatrix = this.parent.transform.getUpdatedWorldMatrix()
- var inverseWorldMatrix = o3djs.math.inverse(worldMatrix);
- var relativeNear = o3djs.math.matrix4.transformPoint(
- inverseWorldMatrix, worldRay.near);
- var relativeFar = o3djs.math.matrix4.transformPoint(
- inverseWorldMatrix, worldRay.far);
- var rayIntersectionInfo =
- this.boundingBox.intersectRay(relativeNear,
- relativeFar);
-
- o3djs.picking.dumpRayIntersectionInfo('SHAPE(box): ' + this.shape.name,
- rayIntersectionInfo);
+ if (this.isPickable()) {
+ var worldMatrix = this.parent.transform.getUpdatedWorldMatrix()
+ var inverseWorldMatrix = o3djs.math.inverse(worldMatrix);
+ var relativeNear = o3djs.math.matrix4.transformPoint(
+ inverseWorldMatrix, worldRay.near);
+ var relativeFar = o3djs.math.matrix4.transformPoint(
+ inverseWorldMatrix, worldRay.far);
+ var rayIntersectionInfo =
+ this.boundingBox.intersectRay(relativeNear,
+ relativeFar);
- if (rayIntersectionInfo.intersected) {
- var elements = this.shape.elements;
- for (var e = 0; e < elements.length; e++) {
- var element = elements[e];
- rayIntersectionInfo = element.intersectRay(
- 0,
- o3djs.base.o3d.State.CULL_CCW,
- relativeNear,
- relativeFar);
- o3djs.picking.dumpRayIntersectionInfo(
- 'SHAPE(tris): ' + this.shape.name + ' : element ' + element.name,
- rayIntersectionInfo);
-
- // TODO: get closest element not just first element.
- if (rayIntersectionInfo.intersected) {
- var worldIntersectionPosition = o3djs.math.matrix4.transformPoint(
- worldMatrix, rayIntersectionInfo.position);
- return o3djs.picking.createPickInfo(element,
- this,
- rayIntersectionInfo,
- worldIntersectionPosition);
+ o3djs.picking.dumpRayIntersectionInfo('SHAPE(box): ' + this.shape.name,
+ rayIntersectionInfo);
+
+ if (rayIntersectionInfo.intersected) {
+ var elements = this.shape.elements;
+ for (var e = 0; e < elements.length; e++) {
+ var element = elements[e];
+ rayIntersectionInfo = element.intersectRay(
+ 0,
+ o3djs.base.o3d.State.CULL_CCW,
+ relativeNear,
+ relativeFar);
+ o3djs.picking.dumpRayIntersectionInfo(
+ 'SHAPE(tris): ' + this.shape.name + ' : element ' + element.name,
+ rayIntersectionInfo);
+
+ // TODO: get closest element not just first element.
+ if (rayIntersectionInfo.intersected) {
+ var worldIntersectionPosition = o3djs.math.matrix4.transformPoint(
+ worldMatrix, rayIntersectionInfo.position);
+ return o3djs.picking.createPickInfo(element,
+ this,
+ rayIntersectionInfo,
+ worldIntersectionPosition);
+ }
}
}
}
@@ -356,9 +356,10 @@ o3djs.picking.ShapeInfo.prototype.pick = function(worldRay) {
/**
* Dumps info about a ShapeInfo
- * @param {string} prefix optional prefix for indenting.
+ * @param {string} opt_prefix optional prefix for indenting.
*/
-o3djs.picking.ShapeInfo.prototype.dump = function(prefix) {
+o3djs.picking.ShapeInfo.prototype.dump = function(opt_prefix) {
+ var prefix = opt_prefix || '';
o3djs.picking.dprint(prefix + 'SHAPE: ' + this.shape.name + '\n');
o3djs.picking.dprintPoint3('bb min',
this.boundingBox.minExtent,
@@ -374,21 +375,55 @@ o3djs.picking.ShapeInfo.prototype.dump = function(prefix) {
* @param {!o3d.Transform} transform Transform to keep info about.
* @param {o3djs.picking.TransformInfo} parent Parent transformInfo of the
* transform. Can be null.
+ * @param {!o3djs.picking.PickManager} pickManager The PickManager this
+ * ShapeInfo belongs to.
*/
-o3djs.picking.TransformInfo = function(transform, parent) {
- this.childTransformInfos = {}; // Object of TransformInfo by id
- this.shapeInfos = {}; // Object of ShapeInfo by id
+o3djs.picking.TransformInfo = function(transform, parent, pickManager) {
+ /**
+ * TransformInfos for children by client id.
+ * @type {!Object.<number, !o3djs.picking.TransformInfo>}
+ */
+ this.childTransformInfos = {};
+
+ /**
+ * ShapeInfos for shape of this transform by client id.
+ * @type {!Object.<number, !o3djs.picking.ShapeInfo>}
+ */
+ this.shapeInfos = {};
+
/**
* The transform of this transform info.
* @type {!o3d.Transform}
*/
this.transform = transform;
+
/**
* The parent of this transform info.
* @type {o3djs.picking.TransformInfo}
*/
this.parent = parent;
+
+ /**
+ * The bounding box of this transform info.
+ * @type {o3d.BoundingBox}
+ */
this.boundingBox = null;
+
+ /**
+ * The PickManager this TransformInfo belongs to.
+ * @type {!o3djs.picking.PickManager}
+ */
+ this.pickManager = pickManager;
+
+ /**
+ * Whether or not this object is pickable when invisible.
+ * This is useful for collision geometry that is not visible.
+ * Of course it might argubly be better to store collision geometry
+ * in a separate graph from visible geometry but sometimes it's useful
+ * to have them in the same graph.
+ * @type {boolean}
+ */
+ this.pickableEvenIfInvisible = false;
};
/**
@@ -400,18 +435,33 @@ o3djs.picking.TransformInfo.prototype.getBoundingBox = function() {
};
/**
+ * Returns whether or not this TransformInfo is pickable.
+ *
+ * If this TransformInfo is not pickable then all child shapes and
+ * TransformInfos will be skipped during the picking process.
+ *
+ * @return {boolean} Whether or not this TransformInfo is pickable.
+ */
+o3djs.picking.TransformInfo.prototype.isPickable = function() {
+ return this.transform.visible || this.pickableEvenIfInvisible;
+};
+
+/**
* Updates the shape and child lists for this TransformInfo and recomputes its
* BoundingBox.
*/
o3djs.picking.TransformInfo.prototype.update = function() {
var newChildTransformInfos = {};
var newShapeInfos = {};
+ // We need to add new children and remove old ones so we walk the children
+ // and for each one we find, if it already has a TransformInfo or ShapeInfo we
+ // add it to our new lists, if not we create one and add it to our new lists.
var children = this.transform.children;
for (var c = 0; c < children.length; c++) {
var child = children[c];
var transformInfo = this.childTransformInfos[child.clientId];
if (!transformInfo) {
- transformInfo = o3djs.picking.createTransformInfo(child, this);
+ transformInfo = this.pickManager.createTransformInfo(child, this);
} else {
// clear the boundingBox so we'll regenerate it.
transformInfo.boundingBox = null;
@@ -424,11 +474,11 @@ o3djs.picking.TransformInfo.prototype.update = function() {
var shape = shapes[s];
var shapeInfo = this.shapeInfos[shape.clientId];
if (!shapeInfo) {
- shapeInfo = o3djs.picking.createShapeInfo(shape, this);
+ shapeInfo = this.pickManager.createShapeInfo(shape, this);
} else {
// unless the vertices or elements change there is no need to
// recompute this.
- // shape.update();
+ // shapeInfo.update();
}
newShapeInfos[shape.clientId] = shapeInfo;
}
@@ -438,30 +488,43 @@ o3djs.picking.TransformInfo.prototype.update = function() {
// o3djs.picking.dprint(
// 'num Shapes: ' + shapes.length + '\n');
+ // Now our new lists have the correct children so replace the old lists.
+ // and remove any old children from the PickManager.
+ for (var skey in this.childTransformInfos) {
+ var key = /** @type {number} */ (skey);
+ if (!newChildTransformInfos[key]) {
+ this.pickManager.removeTransformInfo(this.childTransformInfos[key]);
+ }
+ }
+
this.childTransformInfos = newChildTransformInfos;
this.shapeInfos = newShapeInfos;
var boundingBox = null;
for (var key in newShapeInfos) {
var shapeInfo = newShapeInfos[key];
- var box = shapeInfo.getBoundingBox().mul(this.transform.localMatrix);
- if (!boundingBox) {
- boundingBox = box;
- } else if (box) {
- boundingBox = boundingBox.add(box);
+ if (shapeInfo.isPickable()) {
+ var box = shapeInfo.getBoundingBox().mul(this.transform.localMatrix);
+ if (!boundingBox) {
+ boundingBox = box;
+ } else if (box) {
+ boundingBox = boundingBox.add(box);
+ }
}
}
for (var key in newChildTransformInfos) {
var transformInfo = newChildTransformInfos[key];
- // Note: If there is no shape at the leaf on this branch
- // there will be no bounding box.
- var box = transformInfo.getBoundingBox();
- if (box) {
- if (!boundingBox) {
- boundingBox = box.mul(this.transform.localMatrix);
- } else {
- boundingBox = boundingBox.add(box.mul(this.transform.localMatrix));
+ if (transformInfo.isPickable()) {
+ // Note: If there is no shape at the leaf on this branch
+ // there will be no bounding box.
+ var box = transformInfo.getBoundingBox();
+ if (box) {
+ if (!boundingBox) {
+ boundingBox = box.mul(this.transform.localMatrix);
+ } else {
+ boundingBox = boundingBox.add(box.mul(this.transform.localMatrix));
+ }
}
}
}
@@ -479,7 +542,7 @@ o3djs.picking.TransformInfo.prototype.update = function() {
* null if the ray did not intersect any triangles.
*/
o3djs.picking.TransformInfo.prototype.pick = function(worldRay) {
- if (this.boundingBox) {
+ if (this.isPickable() && this.boundingBox) {
var inverseWorldMatrix = o3djs.math.matrix4.identity();
if (this.parent) {
inverseWorldMatrix = o3djs.math.inverse(
@@ -497,7 +560,8 @@ o3djs.picking.TransformInfo.prototype.pick = function(worldRay) {
if (rayIntersectionInfo.intersected) {
var closestPickInfo = null;
var minDistance = -1;
- for (var key in this.childTransformInfos) {
+ for (var skey in this.childTransformInfos) {
+ var key = /** @type {number} */ (skey);
var transformInfo = this.childTransformInfos[key];
var pickInfo = transformInfo.pick(worldRay);
if (pickInfo) {
@@ -512,7 +576,8 @@ o3djs.picking.TransformInfo.prototype.pick = function(worldRay) {
}
}
- for (var key in this.shapeInfos) {
+ for (var skey in this.shapeInfos) {
+ var key = /** @type {number} */ (skey);
var shapeInfo = this.shapeInfos[key];
var pickInfo = shapeInfo.pick(worldRay);
if (pickInfo) {
@@ -534,10 +599,10 @@ o3djs.picking.TransformInfo.prototype.pick = function(worldRay) {
/**
* Dumps info about a TransformInfo
- * @param {string} prefix optional prefix for indenting.
+ * @param {string} opt_prefix optional prefix for indenting.
*/
-o3djs.picking.TransformInfo.prototype.dump = function(prefix) {
- prefix = prefix || '';
+o3djs.picking.TransformInfo.prototype.dump = function(opt_prefix) {
+ var prefix = opt_prefix || '';
o3djs.picking.dprint(prefix + 'TRANSFORM: ' + this.transform.name +
'\n');
@@ -554,17 +619,124 @@ o3djs.picking.TransformInfo.prototype.dump = function(prefix) {
}
o3djs.picking.dprint(prefix + '--Shapes--\n');
- for (var key in this.shapeInfos) {
+ for (var skey in this.shapeInfos) {
+ var key = /** @type {number} */ (skey);
var shapeInfo = this.shapeInfos[key];
shapeInfo.dump(prefix + ' ');
}
o3djs.picking.dprint(prefix + '--Children--\n');
- for (var key in this.childTransformInfos) {
+ for (var skey in this.childTransformInfos) {
+ var key = /** @type {number} */ (skey);
var transformInfo = this.childTransformInfos[key];
transformInfo.dump(prefix + ' ');
}
};
+/**
+ * A PickManager manages picking of primitives from a transform graph.
+ * @constructor
+ * @param {!o3d.Transform} rootTransform The root of the transform graph this
+ * PickManager should manage.
+ */
+o3djs.picking.PickManager = function(rootTransform) {
+ /**
+ * TransformInfos for transforms of this PickManager by client id.
+ * @type {!Object.<number, !o3djs.picking.TransformInfo>}
+ */
+ this.transformInfosByClientId = {};
+
+ /**
+ * The root transform for this PickManager.
+ * @type {!o3djs.picking.TransformInfo}
+ */
+ this.rootTransformInfo = this.createTransformInfo(rootTransform, null);
+};
+
+/**
+ * Creates a new ShapeInfo.
+ * @param {!o3d.Shape} shape Shape to keep info about.
+ * @param {!o3djs.picking.TransformInfo} parent Parent transform of the shape.
+ * @return {!o3djs.picking.ShapeInfo} The new ShapeInfo.
+ */
+o3djs.picking.PickManager.prototype.createShapeInfo = function(shape, parent) {
+ return new o3djs.picking.ShapeInfo(shape, parent, this);
+};
+
+/**
+ * Creates a new TransformInfo.
+ * @param {!o3d.Transform} transform Transform to keep info about.
+ * @param {o3djs.picking.TransformInfo} parent Parent transform of the
+ * transform. Can be null.
+ * @return {!o3djs.picking.TransformInfo} The new TransformInfo.
+ */
+o3djs.picking.PickManager.prototype.createTransformInfo =
+ function(transform, parent) {
+ var info = new o3djs.picking.TransformInfo(transform, parent, this);
+ this.addTransformInfo(info);
+ return info;
+};
+
+/**
+ * Adds a transform info to this PickManager.
+ * @param {!o3djs.picking.TransformInfo} transformInfo The TransformInfo to add.
+ */
+o3djs.picking.PickManager.prototype.addTransformInfo = function(transformInfo) {
+ this.transformInfosByClientId[transformInfo.transform.clientId] =
+ transformInfo;
+};
+
+/**
+ * Removes a transform info from this PickManager.
+ * @param {!o3djs.picking.TransformInfo} transformInfo The TransformInfo to
+ * remove.
+ */
+o3djs.picking.PickManager.prototype.removeTransformInfo =
+ function(transformInfo) {
+ delete this.transformInfosByClientId[transformInfo.transform.clientId];
+};
+
+/**
+ * Gets a transform info from this PickManager by transform.
+ * @param {!o3d.Transform} transform The Transform to get a TransformInfo for.
+ * @return {o3djs.picking.TransformInfo} The TransformInfo for the transform or
+ * null if there isn't one.
+ */
+o3djs.picking.PickManager.prototype.getTransformInfo = function(transform) {
+ return this.transformInfosByClientId[transform.clientId];
+};
+
+/**
+ * Updates the picking info to match the transform graph in its current state.
+ */
+o3djs.picking.PickManager.prototype.update = function() {
+ this.rootTransformInfo.update();
+};
+
+/**
+ * Dumps info about a PickManager
+ */
+o3djs.picking.PickManager.prototype.dump = function() {
+ this.rootTransformInfo.dump();
+};
+/**
+ * Attempts to "pick" objects managed by this PickManager.
+ * @param {!o3djs.picking.Ray} worldRay A ray in world space to pick against.
+ * @return {o3djs.picking.PickInfo} Information about the picking.
+ * null if the ray did not intersect any triangles.
+ */
+o3djs.picking.PickManager.prototype.pick = function(worldRay) {
+ return this.rootTransformInfo.pick(worldRay);
+};
+
+/**
+ * Creates a PickManager.
+ * @param {!o3d.Transform} rootTransform The root of the transform graph this
+ * PickManager should manage.
+ * @return {!o3djs.picking.PickManager} The created PickManager.
+ */
+o3djs.picking.createPickManager = function(rootTransform) {
+ return new o3djs.picking.PickManager(rootTransform);
+};
diff --git a/o3d/samples/picking.html b/o3d/samples/picking.html
index f4a73a0..3466ff5 100644
--- a/o3d/samples/picking.html
+++ b/o3d/samples/picking.html
@@ -81,7 +81,7 @@ var g_math;
var g_client;
var g_pack;
var g_viewInfo;
-var g_treeInfo; // information about the transform graph.
+var g_pickManager; // information about the transform graph.
var g_pickInfoElem;
var g_debugHelper;
var g_debugLineGroup;
@@ -93,11 +93,10 @@ var g_highlightShape;
var g_finished = false; // for selenium testing.
function updateInfo() {
- if (!g_treeInfo) {
- g_treeInfo = o3djs.picking.createTransformInfo(g_client.root,
- null);
+ if (!g_pickManager) {
+ g_pickManager = o3djs.picking.createPickManager(g_client.root);
}
- g_treeInfo.update();
+ g_pickManager.update();
}
function unSelectAll() {
@@ -108,6 +107,8 @@ function unSelectAll() {
o3djs.shape.deleteDuplicateShape(g_highlightShape, g_pack);
g_highlightShape = null;
g_selectedInfo = null;
+ // Turn off the debug line.
+ g_debugLine.setVisible(false);
}
}
@@ -152,9 +153,9 @@ function pick(e) {
// 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();
+ g_pickManager.update();
- var pickInfo = g_treeInfo.pick(worldRay);
+ var pickInfo = g_pickManager.pick(worldRay);
if (pickInfo) {
select(pickInfo);
g_pickInfoElem.innerHTML = pickInfo.shapeInfo.shape.name;
@@ -188,7 +189,6 @@ function pick(e) {
g_debugLine.setVisible(true);
g_debugLine.setEndPoints(worldPosition, normalSpot);
} else {
- g_debugLine.setVisible(false);
g_pickInfoElem.innerHTML = '--nothing--';
}
}
@@ -198,9 +198,9 @@ function onrender(renderEvent) {
g_flashTimer = g_flashTimer % 0.5;
if (g_selectedInfo) {
if (g_flashTimer < 0.25) {
- g_highlightMaterial.getParam('color').value = [1, 1, 1, 1];
+ g_highlightMaterial.getParam('emissive').value = [1, 1, 1, 1];
} else {
- g_highlightMaterial.getParam('color').value = [0, 0, 0, 1];
+ g_highlightMaterial.getParam('emissive').value = [0, 0, 0, 1];
}
}
}
@@ -249,7 +249,7 @@ function loadScene(pack, fileName, parent) {
// Update our info
updateInfo();
- g_treeInfo.dump('');
+ g_pickManager.dump('');
g_finished = true; // for selenium testing.
}
@@ -292,6 +292,7 @@ function initStep2(clientElements) {
g_debugLineGroup = g_debugHelper.createDebugLineGroup(g_client.root);
g_debugLine = g_debugLineGroup.addLine();
g_debugLine.setColor([0,1,0,1]);
+ g_debugLine.setVisible(false);
// Create a material for highlighting.
g_highlightMaterial = o3djs.material.createConstantMaterial(