Selecting a vertex

israel

Newcomer
Joined
Aug 5, 2004
Messages
17
Does anybody know if there's a way of selecting a vertex of a 3D object using the mouse?

For instance, I have a 3D view of a foot (I'm in the medical industry) and when the user drags the mouse over the shape I need to draw a point on top of the vertex where the mouse is pointing to, excluding the hidden vertexes.

Does anybody know how to do that?

Thanks,
 
ThePentiumGuy said:
Isn't this called Ray Tracing?
I know that there is a sample on the DirectX 9 SDK for this :).

Also look here:
http://www.google.com/search?hl=en&ie=UTF-8&q=Ray+Tracing+DirectX9+Tutorials
I believe that Ray Tracing is a method for "generating" 3D scenes. It is still used in programs like 3DSMAX to produce fully textured and animated scenes. The only problem with it is that it takes around 30-60 seconds to generate each frame as a picture. :)
 
Finding the inverse of a 4x4 transformation matrix
Inverse matrices aren't used as heavily as normal transformation matrices, but they are the only method for doing certain very useful techniques (such as 'picking' 3D objects based on a 2D mouse coordinate). Inverse Matrices by their very nature are quite slow; so this speed test is crucial.

As with the CreateMatrix() test, the source code is not presented here for clarity, you can find it in the downloadable archive. Thanks to Eric Coleman for letting me use his optimized inverse matrix function.

I figured out where I read this. It turns out it was at the VB.NET vs VB6 speed test results page. ;)

http://216.5.163.53/DirectX4VB/Tutorials/GeneralVB/GM_NETvsVB6.asp

The trick is Inverse Matricies I guess. I have no clue how to go about it from there, but hopefully this helps.
 
Hey men! Your asking the same question I just asked! I will read what these people said and try to get back to you if I find anything... If you figure it out please tell me too!
Thanks men!
 
I found an answer!

Hey men!! I FOUND the answer! Well at least one answer! But it involves alot of matrix stuff men! I found it in the DirectX 8 SDK using VB 6.. If you want to could look at the class I attached.. It has ALL the code needed to determine if a mesh (or all sub meshes of a mesh [they call it "frame" in this example]) falls in a given x , y coordinate on the screen. I my self am going to study it and post the DX 9 equivalent! I is not hard men but you have to first get the project and viewport matrixes your device is using then alpy them to get an resulting Intersect Ray and use that ray to find meshes that intersect with it then find the shortest "IntersectInformation.Dist" to see which mesh that was hit is the closest to the camera...
:)
Look at the "ViewportPick" function. it returns true if the a mesh is hit...
I think I could make a .NET class in VB
Later men!
 

Attachments

Thanks all

Thanks all for your help. I think I'm going to be trying what Phikwe found, but in C# (Phikwe, let me know if you made it work). And I'm also going to keep looking for more info.
 
I got it working!!!!!!!!!!! :) :) :)

Hey Guys! I found it for real now! It was not as hard as I thought it would be...
I made a little function that does it.. Works like a charm! What you do is give it the X and Y coordinates and the mesh and it tells you if the (x,y) is over your mesh... If you want you could call ClosestHit.Dist to see how far your mesh is from the screen.
Here is the function

'Determines if an (x,y) coordinate [could be of your mouse] in screen space is over a mesh
Function DoesMouseHitMesh(ByVal meshAs mesh, ByVal x As Single, ByVal y As Single) As Boolean
Dim viewport As Viewport
Dim world As Matrix
Dim proj As Matrix
Dim view As Matrix

Dim vIn As Vector3, vNear As Vector3, vFar As Vector3, vDir As Vector3
Dim ClosestHit As IntersectInformation

viewport = device.Viewport
world = device.Transform.World 'Now here you have to remember to get the world matrix that will be used on your mesh...
proj = device.Transform.Projection
view = device.Transform.View

vIn.X = x : vIn.Y = y

'Compute point on Near Clip plane at cursor
vIn.Z = 0
vNear = Microsoft.DirectX.Vector3.Unproject(vIn, viewport, proj, view, world)

'compute point on far clip plane at cursor
vIn.Z = 1
vFar = Microsoft.DirectX.Vector3.Unproject(vIn, viewport, proj, view, world)

'Comput direction vector
vDir = Microsoft.DirectX.Vector3.Subtract(vFar, vNear)

If mesh.Intersect(vNear, vDir, ClosestHit) = True Then
Return True
End If
End Function

It works GRATE men! :)
Later! Tell me if you need help in using it or dont understnad somthing...
 
Phikwe said:
Hey Guys! I found it for real now! It was not as hard as I thought it would be...
I made a little function that does it.. Works like a charm! What you do is give it the X and Y coordinates and the mesh and it tells you if the (x,y) is over your mesh... If you want you could call ClosestHit.Dist to see how far your mesh is from the screen.
Here is the function

'Determines if an (x,y) coordinate [could be of your mouse] in screen space is over a mesh
Function DoesMouseHitMesh(ByVal meshAs mesh, ByVal x As Single, ByVal y As Single) As Boolean
Dim viewport As Viewport
Dim world As Matrix
Dim proj As Matrix
Dim view As Matrix

Dim vIn As Vector3, vNear As Vector3, vFar As Vector3, vDir As Vector3
Dim ClosestHit As IntersectInformation

viewport = device.Viewport
world = device.Transform.World 'Now here you have to remember to get the world matrix that will be used on your mesh...
proj = device.Transform.Projection
view = device.Transform.View

vIn.X = x : vIn.Y = y

'Compute point on Near Clip plane at cursor
vIn.Z = 0
vNear = Microsoft.DirectX.Vector3.Unproject(vIn, viewport, proj, view, world)

'compute point on far clip plane at cursor
vIn.Z = 1
vFar = Microsoft.DirectX.Vector3.Unproject(vIn, viewport, proj, view, world)

'Comput direction vector
vDir = Microsoft.DirectX.Vector3.Subtract(vFar, vNear)

If mesh.Intersect(vNear, vDir, ClosestHit) = True Then
Return True
End If
End Function

It works GRATE men! :)
Later! Tell me if you need help in using it or dont understnad somthing...

Hey Phikwe, Good job man! I have a question for you. Are the (x,y) values you're passing to your function in pixels and starting from the top left corner of your screen?

Thanks again
 
Nevermind, I got it. Thanx everybody

Thanks all for your help, I followed Phikwe's implementation (thanks alot man) to come up with a routine to find which triangle I hit with the mouse (I'm drawing primitives). In this function I'm testing for just one triangle that's why my vectors zero, one and two are hard-coded.

I'm pasting my function here just in case anybody is interested:

private bool intersectedTriangle()
{
Point pt = Cursor.Position;
pt = this.PointToClient(pt);
Viewport vp;
Matrix world;
Matrix proj;
Matrix view;
IntersectInformation closeHit

Vector3 vIn, vNear, vFar, vDir;

vp = device.Viewport;
world = device.Transform.World;
proj = device.Transform.Projection;
view = device.Transform.View;

vIn.X = pt.X;
vIn.Y = pt.Y;

// Compute point on near clip plane at cursor
vIn.Z = 0;
vNear = Vector3.Unproject(vIn, vp, proj, view, world);

// Compute point on far clip plane at cursor
vIn.Z = 1;
vFar = Vector3.Unproject(vIn, vp, proj, view, world);

// Compute direction vector
vDir = Vector3.Subtract(vFar, vNear);

Vector3 zero, one, two;
// The vertexes of my triangle
zero = new Vector3(0.0f, 1.0f, 1.0f);
one = new Vector3(-1.0f, -1.0f, 1.0f);
two = new Vector3(1.0f, -1.0f, 1.0f);
if (Geometry.IntersectTri(zero, one, two, vNear, vDir, ref closeHit))
{
return true;
}
return false;
}
 
Last edited:
Pick a mesh.

I have resently done som work on this subject and here is a synopsis of what i have come up with so far.

But first a cuppleo warnings:
1. The code here is not tested as is. I have cut it out from various places in my source code, so you may have to play with it to actual make it work.

2. The code relays strongly on what others have writen, so if you recognize this as your own work, you may be right.

3. After rereading your question I see that there is a missing part here. How to do something with the selected face (hide it or something) can be seen in the sdk's pick sample. It is written in C++ but you should be able to work out the missing pieces.

Picking meshes can be acomplished in the folowing steps:

Let's say the mouse is located in point 100,200 on screen:

1. Transform this coordinate in the range -1 , +1 for x and -1 , +1 for y, y - axis are inverted. In adition the projection matrix must be takent into acount:
---------------------------------------------------------------------------------------------
Matrix matProj = device.GetTransform(TransformType.Projection);
Vector3 screenVector = new Vector3(( ( ( 2.0f * screenX ) / this.ClientRectangle.Width ) - 1) / matProj.M11,-( ( ( 2.0f * screenY ) / this.ClientRectangle.Height ) - 1) / matProj.M22,1.0f);
--------------------------------------------------------------------------------------------

This first step has to be done once each time you start intersection testing in the scene.

The remaining steps must be done for each mesh.


2. Calculate a ray defined by the camaraposition and a direction vector such that it gos trough the actual point on the screen.

The World transform is the same transform that is used to "place" the mesh in the 3D-world, so this, and the remaining steps must be done for each mesh.
---------------------------------------------------------------------------------------------
Matrix m = device.Transform.World * device.Transform.View;
m.Invert();

// Transform the screen space pick ray into 3D space
Vector3 vPickRayDir = new Vector3(0,0,0);
Vector3 vPickRayOrig = new Vector3(0,0,0);
startPoint = Vector3.Empty;
direction = Vector3.Empty;
direction.X = screenVector.X*m.M11 + screenVector.Y*m.M21 + screenVector.Z*m.M31;
direction.Y = screenVector.X*m.M12 + screenVector.Y*m.M22 + screenVector.Z*m.M32;
direction.Z = screenVector.X*m.M13 + screenVector.Y*m.M23 + screenVector.Z*m.M33;
startPoint.X = m.M41;
startPoint.Y = m.M42;
startPoint.Z = m.M43;
---------------------------------------------------------------------------------------------

3. Test intersection for mesh of interest:
---------------------------------------------------------------------------------------------
IntersectInformation closestHit = new IntersectInformation();
if(mesh.Intersect(startPoint,direction,ref closestHit))
{
// Intersection found. For example closestHit.Dest will tell you how close
// the mesh is from camera.
}
---------------------------------------------------------------------------------------------

If you want to do intersection test on triangles this can be acheaved by Geometry.IntersectTri()

The intersectionInformation object have information about whitch face has been selected. This will be 3 Vector3 objects. They will be in model space. Along with the 3 points, the IntersectInformation object also contains a u,v pair that can be used to calculate the exact intersection point:

If we say that the tree points are v0, v1 and V3, then the intersection point will be: Vector3 vIntersection = (1-u-v)*v0+u*v1+v*v2;

The vIntersection will be in model space. To convert it to real world space you can do the following:
Vector3 vIntersectionRealWorld = vIntersection;
vIntersectionPointRealWorld.TransformCoordinate(device.GetTransform(TransformType.World));

Thats it for now. Hope this helps.
 
Last edited:
How would you do this in code?

Vector3 vIntersection = (1-u-v)*v0+u*v1+v*v2;

Reidar Lange said:
I have resently done som work on this subject and here is a synopsis of what i have come up with so far.

But first a cuppleo warnings:
1. The code here is not tested as is. I have cut it out from various places in my source code, so you may have to play with it to actual make it work.

2. The code relays strongly on what others have writen, so if you recognize this as your own work, you may be right.

3. After rereading your question I see that there is a missing part here. How to do something with the selected face (hide it or something) can be seen in the sdk's pick sample. It is written in C++ but you should be able to work out the missing pieces.

Picking meshes can be acomplished in the folowing steps:

Let's say the mouse is located in point 100,200 on screen:

1. Transform this coordinate in the range -1 , +1 for x and -1 , +1 for y, y - axis are inverted. In adition the projection matrix must be takent into acount:
---------------------------------------------------------------------------------------------
Matrix matProj = device.GetTransform(TransformType.Projection);
Vector3 screenVector = new Vector3(( ( ( 2.0f * screenX ) / this.ClientRectangle.Width ) - 1) / matProj.M11,-( ( ( 2.0f * screenY ) / this.ClientRectangle.Height ) - 1) / matProj.M22,1.0f);
--------------------------------------------------------------------------------------------

This first step has to be done once each time you start intersection testing in the scene.

The remaining steps must be done for each mesh.


2. Calculate a ray defined by the camaraposition and a direction vector such that it gos trough the actual point on the screen.

The World transform is the same transform that is used to "place" the mesh in the 3D-world, so this, and the remaining steps must be done for each mesh.
---------------------------------------------------------------------------------------------
Matrix m = device.Transform.World * device.Transform.View;
m.Invert();

// Transform the screen space pick ray into 3D space
Vector3 vPickRayDir = new Vector3(0,0,0);
Vector3 vPickRayOrig = new Vector3(0,0,0);
startPoint = Vector3.Empty;
direction = Vector3.Empty;
direction.X = screenVector.X*m.M11 + screenVector.Y*m.M21 + screenVector.Z*m.M31;
direction.Y = screenVector.X*m.M12 + screenVector.Y*m.M22 + screenVector.Z*m.M32;
direction.Z = screenVector.X*m.M13 + screenVector.Y*m.M23 + screenVector.Z*m.M33;
startPoint.X = m.M41;
startPoint.Y = m.M42;
startPoint.Z = m.M43;
---------------------------------------------------------------------------------------------

3. Test intersection for mesh of interest:
---------------------------------------------------------------------------------------------
IntersectInformation closestHit = new IntersectInformation();
if(mesh.Intersect(startPoint,direction,ref closestHit))
{
// Intersection found. For example closestHit.Dest will tell you how close
// the mesh is from camera.
}
---------------------------------------------------------------------------------------------

If you want to do intersection test on triangles this can be acheaved by Geometry.IntersectTri()

The intersectionInformation object have information about whitch face has been selected. This will be 3 Vector3 objects. They will be in model space. Along with the 3 points, the IntersectInformation object also contains a u,v pair that can be used to calculate the exact intersection point:

If we say that the tree points are v0, v1 and V3, then the intersection point will be: Vector3 vIntersection = (1-u-v)*v0+u*v1+v*v2;

The vIntersection will be in model space. To convert it to real world space you can do the following:
Vector3 vIntersectionRealWorld = vIntersection;
vIntersectionPointRealWorld.TransformCoordinate(device.GetTransform(TransformType.World));

Thats it for now. Hope this helps.
 
Calculating intersection points

// Assuming that you have the intersectInformation object ready:
float u = intersectInformation.intersectInformation.U;
float v = intersectInformation.intersectInformation.V;

// The intersection point in model space
Vector3 IntersectionPoint = (1-u-v)*intersectInformation.triangle[0]+ u*intersectInformation.triangle[1]+
v*intersectInformation.triangle[2];

// The intersection point in real world
Vector3 IntersectionPointRealWorld = IntersectionPoint;
IntersectionPointRealWorld.TransformCoordinate(device.Transform.World);
 
Back
Top