Created
December 4, 2017 05:53
-
-
Save leefsmp/d38f1ce2b81ecf641c72d2b0011bc76c to your computer and use it in GitHub Desktop.
Forge Viewer MeshSelectionExtension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////// | |
// MeshSelectionExtension, written by Philippe Leefsma - Dec 2017 | |
// | |
// Illustrates how to perform double ray casting to detect selection | |
// of custom meshes added to the scene and handle occlusion with | |
// Viewer meshes from loaded model. | |
// | |
///////////////////////////////////////////////////////////////////// | |
class MeshSelectionExtension extends Autodesk.Viewing.Extension { | |
///////////////////////////////////////////////////////// | |
// Class constructor | |
// | |
///////////////////////////////////////////////////////// | |
constructor (viewer, options) { | |
super (viewer, options) | |
this.viewer = viewer | |
} | |
///////////////////////////////////////////////////////// | |
// Load callback | |
// | |
///////////////////////////////////////////////////////// | |
load () { | |
console.log('Viewing.Extension.MeshSelection loaded') | |
this.viewer.addEventListener( | |
Autodesk.Viewing.OBJECT_TREE_CREATED_EVENT, () => { | |
this.dbIds = this.getAllDbIds() | |
}) | |
this.viewer.toolController.registerTool(this) | |
this.viewer.toolController.activateTool( | |
'Viewing.Extension.MeshSelection') | |
this.intersectMeshes = [ | |
this.addMesh(), | |
this.addMesh(), | |
this.addMesh(), | |
this.addMesh(), | |
this.addMesh() | |
] | |
return true | |
} | |
///////////////////////////////////////////////////////// | |
// Tool Interface | |
// | |
///////////////////////////////////////////////////////// | |
getNames () { | |
return ['Viewing.Extension.MeshSelection'] | |
} | |
activate () { | |
} | |
deactivate () { | |
} | |
///////////////////////////////////////////////////////// | |
// Unload callback | |
// | |
///////////////////////////////////////////////////////// | |
unload () { | |
console.log('Viewing.Extension.MeshSelection unloaded') | |
this.viewer.toolController.deactivateTool( | |
'Viewing.Extension.MeshSelection') | |
this.viewer.toolController.unregisterTool(this) | |
return true | |
} | |
///////////////////////////////////////////////////////// | |
// Adds a box mesh with random size and position | |
// to the scene | |
// | |
///////////////////////////////////////////////////////// | |
addMesh () { | |
const geometry = new THREE.BoxGeometry( | |
Math.random() * 10 + 5.0, | |
Math.random() * 10 + 5.0, | |
Math.random() * 10 + 5.0) | |
const color = Math.floor(Math.random() * 16777215) | |
const material = this.createColorMaterial(color) | |
const mesh = new THREE.Mesh(geometry, material) | |
mesh.position.x = -50 + Math.random() * 100 | |
mesh.position.y = -50 + Math.random() * 100 | |
mesh.position.z = -50 + Math.random() * 100 | |
this.viewer.impl.scene.add(mesh) | |
this.viewer.impl.sceneUpdated(true) | |
return mesh | |
} | |
///////////////////////////////////////////////////////// | |
// Creates color material from int | |
// | |
///////////////////////////////////////////////////////// | |
createColorMaterial (color) { | |
const material = new THREE.MeshPhongMaterial({ | |
specular: new THREE.Color(color), | |
side: THREE.DoubleSide, | |
reflectivity: 0.0, | |
color | |
}) | |
const materials = this.viewer.impl.getMaterials() | |
materials.addMaterial( | |
color.toString(16), | |
material, | |
true) | |
return material | |
} | |
///////////////////////////////////////////////////////// | |
// Creates Raycaster object from the pointer | |
// | |
///////////////////////////////////////////////////////// | |
pointerToRaycaster (domElement, camera, pointer) { | |
const pointerVector = new THREE.Vector3() | |
const pointerDir = new THREE.Vector3() | |
const ray = new THREE.Raycaster() | |
const rect = domElement.getBoundingClientRect() | |
const x = ((pointer.clientX - rect.left) / rect.width) * 2 - 1 | |
const y = -((pointer.clientY - rect.top) / rect.height) * 2 + 1 | |
if (camera.isPerspective) { | |
pointerVector.set(x, y, 0.5) | |
pointerVector.unproject(camera) | |
ray.set(camera.position, | |
pointerVector.sub( | |
camera.position).normalize()) | |
} else { | |
pointerVector.set(x, y, -1) | |
pointerVector.unproject(camera) | |
pointerDir.set(0, 0, -1) | |
ray.set(pointerVector, | |
pointerDir.transformDirection( | |
camera.matrixWorld)) | |
} | |
return ray | |
} | |
///////////////////////////////////////////////////////// | |
// Click handler | |
// | |
///////////////////////////////////////////////////////// | |
handleSingleClick (event) { | |
const pointer = event.pointers | |
? event.pointers[0] | |
: event | |
const rayCaster = this.pointerToRaycaster( | |
this.viewer.impl.canvas, | |
this.viewer.impl.camera, | |
pointer) | |
const intersectResults = rayCaster.intersectObjects( | |
this.intersectMeshes, true) | |
const hitTest = this.viewer.model.rayIntersect( | |
rayCaster, true, this.dbIds) | |
const selections = intersectResults.filter((res) => | |
(!hitTest || (hitTest.distance > res.distance)) | |
) | |
if (selections.length) { | |
console.log('Custom meshes selected:') | |
console.log(selections) | |
return true | |
} | |
return false | |
} | |
///////////////////////////////////////////////////////// | |
// Get list of all dbIds in the model | |
// | |
///////////////////////////////////////////////////////// | |
getAllDbIds() { | |
const {instanceTree} = this.viewer.model.getData() | |
const {dbIdToIndex} = instanceTree.nodeAccess | |
return Object.keys(dbIdToIndex).map((dbId) => { | |
return parseInt(dbId) | |
}) | |
} | |
} | |
Autodesk.Viewing.theExtensionManager.registerExtension( | |
'Viewing.Extension.MeshSelection', | |
MeshSelectionExtension) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, I am trying to use your extension when I change
handleSingleClick
tohandleButtonDown
orhandleButtonUp
. Nothing happens when I click the mouse. Do you know the reason?The viewer version I use is 7.x
Thank you!