From ceea26c140b8a47fa52fa94cd494ce60c41a4efb Mon Sep 17 00:00:00 2001 From: Tom Gaskins Date: Fri, 30 Oct 2015 12:29:11 -0700 Subject: [PATCH] Added pick position calculation to mesh shapes. Added picking to USGSSlabs app. --- apps/USGSSlabs/USGSSlabs.js | 33 ++++++++++++++++++++--- src/shapes/AbstractMesh.js | 51 +++++++++++++++++++++++++++++++++--- src/shapes/TriangleMesh.js | 2 +- src/util/WWMath.js | 52 +++++++++++++++++++++++++++++++++++++ 4 files changed, 131 insertions(+), 7 deletions(-) diff --git a/apps/USGSSlabs/USGSSlabs.js b/apps/USGSSlabs/USGSSlabs.js index d492e410..9e413790 100644 --- a/apps/USGSSlabs/USGSSlabs.js +++ b/apps/USGSSlabs/USGSSlabs.js @@ -43,6 +43,8 @@ define(['../../src/WorldWind', // Enable sub-surface rendering for the World Window. this.wwd.subsurfaceMode = true; + // Enable deep picking in order to detect the sub-surface shapes. + this.wwd.deepPicking = true; // Start the view pointing to a longitude within the current time zone. this.wwd.navigator.lookAtLocation.latitude = 30; @@ -56,9 +58,34 @@ define(['../../src/WorldWind', this.layersPanel.synchronizeLayerList(); this.loadSlabData("CAS", "cascadia_slab1.0_clip.xyz", 401, WorldWind.Color.YELLOW); - this.loadSlabData("SOL", "sol_slab1.0_clip.xyz", 1001, WorldWind.Color.YELLOW); - this.loadSlabData("MEX", "mex_slab1.0_clip.xyz", 1251, WorldWind.Color.CYAN); - this.loadSlabData("ALU", "alu_slab1.0_clip.xyz", 2451, WorldWind.Color.MAGENTA); + //this.loadSlabData("SOL", "sol_slab1.0_clip.xyz", 1001, WorldWind.Color.YELLOW); + //this.loadSlabData("MEX", "mex_slab1.0_clip.xyz", 1251, WorldWind.Color.CYAN); + //this.loadSlabData("ALU", "alu_slab1.0_clip.xyz", 2451, WorldWind.Color.MAGENTA); + + var wwd = this.wwd; + var handlePick = function (o) { + var pickPoint = wwd.canvasCoordinates(o.clientX, o.clientY); + + var pickList = wwd.pick(pickPoint); + if (pickList.objects.length > 0) { + for (var p = 0; p < pickList.objects.length; p++) { + var pickedObject = pickList.objects[p]; + if (pickedObject.userObject instanceof WorldWind.TriangleMesh) { + if (pickedObject.position) { + console.log("PO: " + pickedObject.position.toString() + " " + pickedObject.isOnTop); + console.log("TN: " + pickList.terrainObject().position.toString() + + " " + pickList.terrainObject().isOnTop); + } + } + } + } + }; + + // Listen for mouse moves and highlight the placemarks that the cursor rolls over. + wwd.addEventListener("mousemove", handlePick); + + // Listen for taps on mobile devices and highlight the placemarks that the user taps. + var tapRecognizer = new WorldWind.TapRecognizer(wwd, handlePick); }; USGSSlabs.prototype.loadSlabData = function (name, dataFile, width, color) { diff --git a/src/shapes/AbstractMesh.js b/src/shapes/AbstractMesh.js index b76da219..abb78a1a 100644 --- a/src/shapes/AbstractMesh.js +++ b/src/shapes/AbstractMesh.js @@ -12,6 +12,7 @@ define([ '../geom/BoundingBox', '../util/Color', '../util/ImageSource', + '../geom/Line', '../geom/Location', '../util/Logger', '../geom/Matrix', @@ -20,6 +21,7 @@ define([ '../shapes/ShapeAttributes', '../geom/Vec2', '../geom/Vec3', + '../util/WWMath' ], function (AbstractShape, ArgumentError, @@ -27,6 +29,7 @@ define([ BoundingBox, Color, ImageSource, + Line, Location, Logger, Matrix, @@ -34,7 +37,8 @@ define([ Position, ShapeAttributes, Vec2, - Vec3) { + Vec3, + WWMath) { "use strict"; /** @@ -122,7 +126,7 @@ define([ // Set the transformation matrix to correspond to the reference position. var refPt = currentData.referencePoint; dc.surfacePointForMode(this.referencePosition.latitude, this.referencePosition.longitude, - this.referencePosition.altitude, this._altitudeMode, refPt); + this.referencePosition.altitude * this._altitudeScale, this._altitudeMode, refPt); currentData.transformationMatrix.setToTranslation(refPt[0], refPt[1], refPt[2]); // Convert the geographic coordinates to the Cartesian coordinates that will be rendered. @@ -468,12 +472,53 @@ define([ } if (dc.pickingMode) { - var po = new PickedObject(pickColor, this.pickDelegate ? this.pickDelegate : this, null, + var pickPosition = this.computePickPosition(dc); + var po = new PickedObject(pickColor, this.pickDelegate ? this.pickDelegate : this, pickPosition, dc.currentLayer, false); dc.resolvePick(po); } }; + AbstractMesh.prototype.computePickPosition = function (dc) { + var currentData = this.currentData, + line = dc.navigatorState.rayFromScreenPoint(dc.pickPoint), + localLineOrigin = new Vec3(line.origin[0], line.origin[1], line.origin[2]).subtract( + currentData.referencePoint), + localLine = new Line(localLineOrigin, line.direction), + intersectionPoints = []; + + if (WWMath.computeIndexedTrianglesIntersection(localLine, currentData.meshPoints, this.meshIndices, + intersectionPoints)) { + var iPoint = intersectionPoints[0]; + + if (intersectionPoints.length > 1) { + // Find the intersection nearest the eye point. + var distance2 = iPoint.distanceToSquared(dc.navigatorState.eyePoint); + + for (var i = 1; i < intersectionPoints.length; i++) { + var d2 = intersectionPoints[i].distanceToSquared(dc.navigatorState.eyePoint); + if (d2 < distance2) { + distance2 = d2; + iPoint = intersectionPoints[i]; + } + } + } + + var pos = new Position(0, 0, 0); + dc.globe.computePositionFromPoint( + iPoint[0] + currentData.referencePoint[0], + iPoint[1] + currentData.referencePoint[1], + iPoint[2] + currentData.referencePoint[2], + pos); + + pos.altitude /= this._altitudeScale; + + return pos; + } + + return null; + }; + // Overridden from AbstractShape base class. AbstractMesh.prototype.beginDrawing = function (dc) { var gl = dc.currentGlContext; diff --git a/src/shapes/TriangleMesh.js b/src/shapes/TriangleMesh.js index 52244a26..c8816a81 100644 --- a/src/shapes/TriangleMesh.js +++ b/src/shapes/TriangleMesh.js @@ -135,7 +135,7 @@ define([ } this._positions = positions; - this.referencePosition = this.determineReferencePosition(this._positions); + this.referencePosition = this._positions[0]; this.reset(); } }, diff --git a/src/util/WWMath.js b/src/util/WWMath.js index 456666af..399850ef 100644 --- a/src/util/WWMath.js +++ b/src/util/WWMath.js @@ -208,6 +208,58 @@ define([ } }, + computeIndexedTrianglesIntersection: function (line, points, indices, results) { + if (!line) { + throw new ArgumentError(Logger.logMessage(Logger.LEVEL_SEVERE, "WWMath", + "computeIndexedTrianglesIntersection", "missingLine")); + } + + if (!points) { + throw new ArgumentError(Logger.logMessage(Logger.LEVEL_SEVERE, "WWMath", + "computeIndexedTrianglesIntersection", "missingPoints")); + } + + if (!indices) { + throw new ArgumentError(Logger.logMessage(Logger.LEVEL_SEVERE, "WWMath", + "computeIndexedTrianglesIntersection", "missingIndices")); + } + + if (!results) { + throw new ArgumentError(Logger.logMessage(Logger.LEVEL_SEVERE, "WWMath", + "computeIndexedTrianglesIntersection", "missingResults")); + } + + var v0 = new Vec3(0, 0, 0), + v1 = new Vec3(0, 0, 0), + v2 = new Vec3(0, 0, 0), + iPoint = new Vec3(0, 0, 0); + + for (var i = 0, len = indices.length; i < len; i += 3) { + var i0 = 3 * indices[i], + i1 = 3 * indices[i + 1], + i2 = 3 * indices[i + 2]; + + v0[0] = points[i0]; + v0[1] = points[i0 + 1]; + v0[2] = points[i0 + 2]; + + v1[0] = points[i1]; + v1[1] = points[i1 + 1]; + v1[2] = points[i1 + 2]; + + v2[0] = points[i2]; + v2[1] = points[i2 + 1]; + v2[2] = points[i2 + 2]; + + if (WWMath.computeTriangleIntersection(line, v0, v1, v2, iPoint)) { + results.push(iPoint); + iPoint = new Vec3(0, 0, 0); + } + } + + return results.length > 0; + }, + /** * Computes the Cartesian intersection points of a specified line with a triangle strip. The triangle strip * is specified by a list of vertex points and a list of indices indicating the triangle strip tessellation