-
Notifications
You must be signed in to change notification settings - Fork 5
GL Events #4
Description
The current version of famous lacks an Event model for GL objects, see one issue posted in the famous repo. Famous#466
There is a solution that has been in a pull request for over a month that uses the picking method. Picking is really limited and I don't particularly like the implementation proposed here.
Ive come up with a Ray class that detects hits on 3D objects, so far theres support for plane, sphere but I am working on box and triangle. It can be used generically like this:
var ray = new Ray(cameraNode.getPosition(),[0, 0, -1]); //first arg is origin, send arg is direction of ray
var hit = ray.intersectsSphere(meshNode.getPosition(),radius);
// hit returns a vector with the distance of the hit Vec3 {x: -0, y: -0, z: 400} or null if no hit
Raycasting is superior to picking because now developers have a Vec3 to use to update rotation, position, etc. This method alone doesn't map events from mouse or touch to Rays. To do that, we would need to create a DOMElement and use a GestureHandler to propagate UIEvents to a node that contains a Mesh. Something like this could be useful and is just a proposal ATM. What do you think?
This works out of the box with a GestureHandler and DOMElement that is the full width and height of the scene:
var gestureNode = scene.addChild()
.setOrigin(0.5, 0.5, 0.5)
.setMountPoint(0.5, 0.5, 0.5)
.setAlign(0.5, 0.5, 0.5)
.setSizeMode(1, 1, 1)
.setAbsoluteSize(window.innerWidth,window.innerHeight);
var gestureElem = new DOMElement(gestureNode);
gestureElem.setProperty('background-color', 'transparent');
var gestures = new GestureHandler(gestureNode);
function callback(e) {
ray = new Ray([e.center.x, e.center.y, -1000],[0, 0, 1]);
hit = ray.intersectsBox(meshNode.getPosition(),[100,100,100]);
console.log(hit);
if(hit){
sphere.setBaseColor(new Color('#FFAA00'));
} else {
sphere.setBaseColor(new Color('#454545'));
}
}
gestures.on('drag', callback);
It may be nice if some of this functionality was built into GestureHandler and users had to register nodes that needed to receive events via Components.
var gesture = new GestureHandler(node, events, {gl: true});
// setting the gl option would create a DOMElement for you that is the width and height of the scene, more options could let you size the width and height of the gesture area.
gesture.on('drag', function(e,p){
this.raycast(e.centerDelta.x,e.center.y);
// internally calls a raycast method that shoots a ray into 3D space and if it hits a node
// update first node it hit with Event, optionally propagate to other nodes.
});
var meshNode = scene.addChild();
meshNode.addComponent({
onMount: function(){
// register node with GestureHandler?
},
onReceive: function (ev) {
console.log(‘received event!');
}
});
A preview of this work is in the https://github.com/infamous/engine/tree/infamous-feat-raycast branch. There are two methods intersectBox and intersectSphere. The last example is not implemented, just an idea. Both the top two examples work right now.