Skip to content

Commit

Permalink
review(StreetControls): Use existing pick methods
Browse files Browse the repository at this point in the history
  • Loading branch information
gliegard committed Feb 19, 2019
1 parent 269b41c commit 3845dab
Showing 1 changed file with 21 additions and 49 deletions.
70 changes: 21 additions & 49 deletions src/Controls/StreetControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class StreetControls extends FirstPersonControls {
* @param { number } [options.animationDurationWall=1000] - Time in millis for the animation when clicking on a wall.
* @param { THREE.Mesh } [options.surfaceGround] - Surface helper to see when mouse is on the ground, default is a transparent circle.
* @param { THREE.Mesh } [options.surfaceWall] - Surface helper to see when mouse is on a wall, default is a transparent rectangle.
* @param { string } [options.buildingsLayer='Buildings'] - Name of the building layer (used to pick on wall).
*/
constructor(view, options = {}) {
super(view, options);
Expand Down Expand Up @@ -97,6 +98,7 @@ class StreetControls extends FirstPersonControls {

this.wallMaxDistance = options.animationDurationWall || 1000;
this.animationDurationWall = options.animationDurationWall || 1000;
this.buildingsLayer = options.buildingsLayer || 'Buildings';
}

setCurrentPosition(newCurrentPosition) {
Expand All @@ -111,56 +113,26 @@ class StreetControls extends FirstPersonControls {
this.previousPosition = newPreviousPosition;
}

firstPickedObject(event) {
// basic threeJs pick with raycaster
const normalized = this.view.viewToNormalizedCoords(event);
this.raycaster.setFromCamera(normalized.clone(), this.camera);
const intersects = this.raycaster.intersectObjects(this.view.scene.children, true);

// skipping specific objects:
// - skip the two surfaces (rectangle and circle)
// - skip all the object without face, because we use the face to manage surface angle, so it's needed.
let i = 0;
while (i < intersects.length &&
(!intersects[i].face || intersects[i].object == this.surfaceWall || intersects[i].object == this.surfaceGround)) {
i++;
}

// return first interesting picked object, or undefined
if (i < intersects.length) {
return intersects[i];
}
}

pick(event, pickGround = () => {}, pickObject = () => {}, target = new THREE.Vector3()) {
// specific method to pick on the elevation layer at the good elevation, even if elevation layer is done in the shader
const mouse = this.view.eventToViewCoords(event);
if (this.view.getPickingPositionFromDepth(mouse, target)) {
// other way to pick object, with the basic threeJs raycast, and then objects are filtered.
const firstPicked = this.firstPickedObject(event);

// nothing is picked
if (!firstPicked) {
this.hideSurfaces();
return;
}

// get distance from the elevation layer
const distanceToGround = this.camera.position.distanceTo(target);
// compare first picked object distance to the distance of the elevation layer
if (!firstPicked.object.isTileMesh && firstPicked.distance < distanceToGround) {
// here we pick something, for example a building
target.copy(firstPicked.point);
// update recangle surface helper
this.updateSurface(target, firstPicked.face.normal, this.surfaceWall, this.surfaceGround);
// callback
pickObject(target);
} else {
// here we pick the ground, update circle surface helper
this.updateSurface(target, firstPicked.face.normal, this.surfaceGround, this.surfaceWall);
// callback
pickGround(target);
}
// get real distance to ground, with a specific method to pick on the elevation layer
this.view.getPickingPositionFromDepth(this.view.eventToViewCoords(event), target);
const distanceToGround = this.camera.position.distanceTo(target);

const intersectsBuildings = this.view.pickObjectsAt(event, 0, this.buildingsLayer);
const intersectsGround = this.view.pickObjectsAt(event, 0, this.view.tileLayer);

// to detect pick on building, compare first picked building distance to ground distance
if (intersectsBuildings.length && intersectsBuildings[0].distance < distanceToGround) { // pick buildings
this.updateSurface(intersectsBuildings[0].point, intersectsBuildings[0].face.normal, this.surfaceWall, this.surfaceGround);
// callback
pickObject(intersectsBuildings[0].point);
} else if (intersectsGround.length) { // pick ground
const normal = target.clone().multiplyScalar(1.1);
this.updateSurface(target, normal, this.surfaceGround, this.surfaceWall);
// callback
pickGround(target);
} else { // pick nothing
this.hideSurfaces();
}
}

Expand Down

0 comments on commit 3845dab

Please # to comment.