var ray_start = [x,y,1]; //had to swap the Z so its cast forward
var ray_dest = [x,y,0];
var matrix = osg.Matrix.makeIdentity();
var w = osg.Matrix.copy(viewer.view.viewport.computeWindowMatrix(), []);
var p = viewer.view.getProjectionMatrix();
var m = viewer.view.getViewMatrix();
osg.Matrix.preMult(matrix, w);
osg.Matrix.preMult(matrix, p);
osg.Matrix.preMult(matrix, m);
var inv = [];
var valid = osg.Matrix.inverse(matrix, inv);
var ns = osg.Matrix.transformVec3(inv, ray_start, new Array(3));
var ne = osg.Matrix.transformVec3(inv, ray_dest, new Array(3));
//======Ray-Sphere intersection========
var t0, t1; // parametric solutions for t if the ray intersects
var radius2 = (6371* 6371);
var ray_dir = osg.Vec3.normalize(osg.Vec3.sub(ns,ne, []) ,[]);
var L = osg.Vec3.sub([0,0,0],ns,[]);
var tca = osg.Vec3.dot(L,ray_dir);
if (tca < 0) return false; //wrong direction
var d2 = osg.Vec3.dot(L,L) - (tca * tca); //o2=h2-a2
if (d2 > radius2) return false; //overshoots
var thc = Math.sqrt(radius2 - d2); //find the exit point
t0 = tca - thc;
t1 = tca + thc;
//Draw a box at the world point
var hitPoint = osg.Vec3.add(ns, osg.Vec3.mult(ray_dir,t0,[]),[]);
var geometry = osg.createTexturedBox(0, 0, 0, 1000,1000,1000);
geometry.setNodeMask(0x2);
var xform = new osg.MatrixTransform()
xform.setMatrix(osg.Matrix.makeTranslate(hitPoint[0],hitPoint[1],hitPoint[2],[]));
xform.addChild(geometry);
root.addChild(xform);
For any interested please read.--
osgUtil.IntersectVisitor.prototype.intersectSegmentWithSphere: function(start, end, bsphere) {
var t0, t1; // parametric solutions for t if the ray intersects
var radius2 = bsphere.radius2();
var ray_dir = osg.Vec3.normalize(osg.Vec3.sub(end,start, []) ,[]);
var L = osg.Vec3.sub(bsphere.center(),start,[]);
var tca = osg.Vec3.dot(L,ray_dir);
if (tca < 0) return false; //wrong direction
var d2 = osg.Vec3.dot(L,L) - (tca * tca); //o2=h2-a2
if (d2 > radius2) return false; //overshoots
var thc = Math.sqrt(radius2 - d2); //find the exit point
t0 = tca - thc;
t1 = tca + thc;
return {t0:t0,t1:t1};
}
osgUtil.screenToRay = function(x, y, view) {
var ray_start = [];
var ray_dest = [];
ray_start[0] = (x / view.viewport.width()) * 2 - 1;
ray_start[1] = -(y / view.viewport.height()) * 2 + 1;
ray_start[2] = 0;
ray_dest[0] = (x / view.viewport.width()) * 2 - 1;
ray_dest[1] = -(y / view.viewport.height()) * 2 + 1;
ray_dest[2] = 1;
var matrix = osg.Matrix.makeIdentity();
var p = view.getProjectionMatrix();
var m = view.getViewMatrix();
osg.Matrix.preMult(matrix, p);
osg.Matrix.preMult(matrix, m);
var inv = [];
var valid = osg.Matrix.inverse(matrix, inv);
var start = osg.Matrix.transformVec3(inv, ray_start, new Array(3));
var end = osg.Matrix.transformVec3(inv, ray_dest, new Array(3));
return {
start:start,
end:end,
dir:osg.Vec3.normalize(osg.Vec3.sub(end,start, []) ,[])
}
}
var world_ray = osgUtil.screenToRay(x, y, viewer.view);
var ray_dir = world_ray.dir;
var bs = new osg.BoundingSphere();
bs.set([0,0,0],6371000);
var iv = new osgUtil.IntersectVisitor();
var is = iv.intersectSegmentWithSphere(world_ray.start,world_ray.end,bs);
if(is){
var hitPoint = osg.Vec3.add(world_ray.start, osg.Vec3.mult(ray_dir,is.t0,[]),[]);
var geometry = osg.createTexturedSphere(400000, 64, 64);
geometry.setNodeMask(0x2);
var xform = new osg.MatrixTransform()
xform.setMatrix(osg.Matrix.makeTranslate(hitPoint[0],hitPoint[1],hitPoint[2],[]));
xform.addChild(geometry);
root.addChild(xform);
}
So thats straight forward sphere intersection code extracted for ease of testing. I have updated osgUtils so it fits into intersectVisitor pipeline and also did some mods to the tri intersection. If you are interested in that I have pasted as a gist.
https://gist.github.com/4655539
Updated:
- intersectSegmentWithSphere (returns intersection t, can be used with direct detection)
- compact moller triangle intersection test http://www.cs.lth.se/home/Tomas_Aken...ubs/tritri.pdf
- applyNode (IntersectVisitor) Added pre triangle test a bounding sphere test, Also the fix for the NDC mouse coords.
Hope this is of use.
Cheers,