Re: [osg-users] picking and custom active area

2009-06-13 Thread Stephan Huber
Hi Stefan,

stefan nortd schrieb:
 So I found some code for intersecting a line with a plane. 
 What I am missing is how do I translate the mouse pointer 
 coordinates into a line expressed in local coordinates?
 
 Here the intersection code if anybody is interested:


There's a class called osg::Plane which you can use to do some
plane-ray-intersections:

double dist = _dragPlane.distance(mouseloc);
double numerator = -dist;
double denominator = _dragPlane.getNormal() * normalizedMouseRay;

if (0.0 == denominator) { // is on Plane
return true;
}
else
{
pointOnDragPlane = mouseloc + (normalizedMouseRay * 
numerator/denominator);
}

the plane, mouseloc and normalizedMouseRay are in local coordinates.

To convert the mouseloc into local coordinates you'll have to
backproject the coordinates.

I do this via:

// get the coords in screen-space:
float tx =  cefix::MouseLocationProvider::instance()-getNativeX();
float ty =  cefix::MouseLocationProvider::instance()-getNativeY();
osg::Vec3 mouseloc =  osg::Vec3(tx, ty, 0) * _invMatrix;
osg::Vec3 normalizedMouseRay = (osg::Vec3(tx, ty, 1) * _invMatrix) -
mouseloc;


The last question which remains: where comes _invMatrix from:

I get the nodepath of the picked object (it's basically a list of
transforms which affects this specific node) and compute a
localToWorld-matrix. I need the current cam to get view + projection matrix.

osg::Matrix MVPW = osg::computeLocalToWorld(nodepath) *
cam-getViewMatrix() * cam-getProjectionMatrix();

// include the viewport:
if (cam-getViewport())

MVPW.postMult(cam-getViewport()-computeWindowMatrix());

_inverseMat.invert(MVPW);

This code is basically the same as in osg, where picking is done.

cheers,

Stephan
___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] picking and custom active area

2009-06-13 Thread stefan nortd
Thanks Stephan, you answer was very helpful. After some headbanging I have it 
working seemingly flawless. Here is the code for reference:


Code:


osg::Vec3d  rayIntersectWithXYPlane(float x, float y, osg::Node* widget) {
// flip mouse y axis
y = ofGetHeight() - y;  //important

osg::Vec3d isect = osg::Vec3d(0,0,0);

// compute model to window transform
// Model*View*Projection*WindowMatrix
osg::Matrixd matrix;
matrix.postMult(widget-getWorldMatrices()[0]);
matrix.postMult(camera-getViewMatrix());
matrix.postMult(camera-getProjectionMatrix());  
matrix.postMult(camera-getViewport()-computeWindowMatrix());

osg::Matrixd inverse;
inverse.invert(matrix);

// Transform ray from window to model coordinates
osg::Vec3d startRay = osg::Vec3d(x,y,0) * inverse;
osg::Vec3d endRay = osg::Vec3d(x,y,1) * inverse;

// Intersect ray with XY-plane
// (0,0,1,0) is plane in hess normal form
getPlaneLineIntersection(osg::Vec4d(0,0,1,0), startRay, endRay, isect);

return isect;
}
bool getPlaneLineIntersection(const osg::Vec4d plane, 
  const osg::Vec3d lineStart, const osg::Vec3d 
lineEnd, 
  osg::Vec3d isect)
{
// intersects an infinite line with an infinite plane
// in hesse normal form  Ax + By + Cz + D = 0
// A,B,C is the normal vector of the plane, D the distance to the origin
const double deltaX = lineEnd.x() - lineStart.x();
const double deltaY = lineEnd.y() - lineStart.y();
const double deltaZ = lineEnd.z() - lineStart.z();

const double denominator = (plane[0]*deltaX + plane[1]*deltaY + 
plane[2]*deltaZ);
if (! denominator) return false;

const double C = (plane[0]*lineStart.x() + plane[1]*lineStart.y() + 
plane[2]*lineStart.z() + plane[3]) / denominator;

isect.x() = lineStart.x() - deltaX * C;
isect.y() = lineStart.y() - deltaY * C;
isect.z() = lineStart.z() - deltaZ * C;

return true;
}





Instead of osg::computeLocalToWorld(...) I use getWorldMatrices(...) which I 
believe does pretty much the same. I also use this 
getPlaneLineIntersection(...) for doing the actual intersection.

I have one more quick question. What is generally meant in osg with world 
coordinates? For example in computeLocalToWorldMatrix(). Is it simply the 
coordinates in the parent or all the way up to the root node? I would assume 
it's all the way up to the root but I read some code that makes me think 
otherwise.

Thanks again,

/stefanix

--
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=13960#13960





___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] picking and custom active area

2009-06-12 Thread stefan nortd
So far so good. The culling works as expected. I can now define a custom active 
invisible area and the picking works with it. Unfortunately it did not quite 
tackle my problem with dragging.

The question have now: How do I manually intersect a ray with the x/y-plane of 
geode?

The problem I have is that when I drag an object, the mouse pointer (in my case 
it is actually one of multiple touches) momentarily leaves it within one frame 
and the move handler that adjusts the new location is never called.

My first approach was to increase the active area so that this does not happen 
but this leads to all kinds of problems and is not fully robust, conceptually 
speaking. Instead I would like to do the following:

Objects get clicked on, I do normal picking. On mouse drag and up I do manual 
ray intersection with the entire x/y plane of the object that got the mouse 
down previously. This way the object never miss out on the drag/up.

So how do I manually intersect a ray with the x/y-plane of geode?

/stefanix

--
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=13953#13953





___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] picking and custom active area

2009-06-12 Thread stefan nortd
So I found some code for intersecting a line with a plane. 
What I am missing is how do I translate the mouse pointer 
coordinates into a line expressed in local coordinates?

Here the intersection code if anybody is interested:

Code:

bool getPlaneLineIntersection(const osg::Vec4d plane, 
  const osg::Vec3d lineStart, const 
osg::Vec3d lineEnd, 
  osg::Vec3d isect)
{
// intersects an infinite line with an infinite plane
// in hesse normal form  Ax + By + Cz + D = 0
// A,B,C is the normal vector of the plane, D the distance to the 
origin
const double deltaX = lineEnd.x() - lineStart.x();
const double deltaY = lineEnd.y() - lineStart.y();
const double deltaZ = lineEnd.z() - lineStart.z();

const double denominator = (plane[0]*deltaX + plane[1]*deltaY + 
plane[2]*deltaZ);
if (! denominator) return false;

const double C = (plane[0]*lineStart.x() + plane[1]*lineStart.y() + 
plane[2]*lineStart.z() + plane[3]) / denominator;

isect.x() = lineStart.x() - deltaX * C;
isect.y() = lineStart.y() - deltaY * C;
isect.z() = lineStart.z() - deltaZ * C;

return true;
}




--
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=13954#13954





___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] picking and custom active area

2009-06-11 Thread stefan nortd
I think I just found some code that would do what I want. Let me know if there 
is a better way of doing this both in regard of the custom active area and the 
drag issue.

So I found this in osgManipulator but I belive I could use this code 
independantly of it. The idea is to add a cull callback that does nothing and 
returns true.


Code:

class ForceCullCallback : public osg::Drawable::CullCallback
{
 public:
virtual bool cull(osg::NodeVisitor*, osg::Drawable*, osg::State*) const
{
return true;
}
};

void osgManipulator::setDrawableToAlwaysCull(osg::Drawable drawable)
{
ForceCullCallback* cullCB = new ForceCullCallback;
drawable.setCullCallback (cullCB);
}




--
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=13917#13917





___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org


Re: [osg-users] picking and custom active area

2009-06-11 Thread Jean-Sébastien Guay

Hi Stefan,

So I found this in osgManipulator but I belive I could use this code independantly of it. 


Yes, definitely. This will work even outside osgManipulator (I was going 
to reply pointing you to this very code, glad you found it by yourself)


The reason why this works is that the drawable on which this callback is 
attached will always be culled and so never be displayed (the return 
true does that) but it will still be traversed during intersection 
tests and so you'll be able to pick it.


Hope this helps,

J-S
--
__
Jean-Sebastien Guayjean-sebastien.g...@cm-labs.com
   http://www.cm-labs.com/
http://whitestar02.webhop.org/
___
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org