Trying to use “right” approach for doing picking in a scene of many objects some of which can be ignored (deep hierarchies).
Constraints:
- All my objects procedurally generated with a top level encompassing entity and ignorable children.
- Object is a mesh asset - simple box collision object of this is adequate for picking
- on collision find the useful top entity node.
So reading through it looks like I want to either:
- make a collision component under my key entity and raycast into the scene to find what it hits
- e.g. Entity picking using Physics
-
https://developer.playcanvas.com/en/tutorials/entity-picking-using-physics/
OR - make my own bounding box and test just the specific objects with ray
- e.g. tut - simple shape ray casting
- https://developer.playcanvas.com/en/tutorials/simple-shape-raycasting/
Doing my own raycasting
Raycast.prototype.initialize = function() {
this.ray = new pc.Ray();
// Register the mouse down and touch start event so we know when the user has clicked
this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onMouseDown, this);
// will push resulting collision position in here.
this.hitPosition = new pc.Vec3();
// Make the bbox shape of an entity
this.aabbShape = new pc.BoundingBox(this.boxEntity.getPosition().clone(), this.boxEntity.getLocalScale().clone().scale(0.5));
};
Raycast.prototype.onMouseDown = function(event) {
if (event.button == pc.MOUSEBUTTON_LEFT) {
this.doRayCast(event);
}};
Raycast.prototype.doRayCast = function (screenPosition) {
// Initialise the ray and work out the direction of the ray from the a screen position
this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.farClip, this.ray.direction);
this.ray.origin.copy(this.cameraEntity.getPosition());
this.ray.direction.sub(this.ray.origin).normalize();
var results = [];
var result;
for (var i=0;i<this.bboxes.length; i++) {
var hitPosition = new pc.Vec3();
result = this.bboxes[i][0].intersectsRay(this.ray, hitPosition);
// result here is just true or false.
// hitPosition contains the 3space point hit
if (result)
results.push(this.bboxes[i][1]); // and maybe hitposition too
}
if (results.length > 0) {
// the hitEntity = results[0]; // might not need a list for this - not sure...
}
};
Using the collision system:
Raycast.prototype.initialize = function() {
// Find the first entity in the hierarchy with the name 'Camera'
this.cameraEntity = this.app.root.findByName('Camera');
// Add a mousedown event handler
this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.mouseDown, this);
// Here we have to have a collision component added to the nodes we care about.
// haven't coded it ...
};
Raycast.prototype.mouseDown = function (e) {
this.doRaycast(e);
};
Raycast.prototype.doRaycast = function (screenPosition) {
// The vec3 to raycast from
var from = this.cameraEntity.getPosition ();
// The vec3 to raycast to
var to = this.cameraEntity.camera.screenToWorld(screenPosition.x, screenPosition.y, this.cameraEntity.camera.farClip);
// Raycast between the two points
var result = this.app.systems.rigidbody.raycastFirst(from, to);
// here result is a combination of an entity, vector and point
};
Its not clear which is the preferred approach and how much overhead is in the systems.rigidbody approach ?
Is one of them preferred for hover type of detection as user moves mouse over scene ?
##Aside:##
(Also there is another system here: Collision Detection library updated for new scripting system. Not sure of its merits.
How do you find all these addons ? is there a registry ? )