Jump to content
Xtreme .Net Talk

Recommended Posts

Posted

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,

Posted

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

My VB.NET Game Programming Tutorial Site (GDI+, Direct3D, Tetris [coming soon], a full RPG.... you name it!)

vbprogramming.8k.com

My Project (Need VB.NET Programmers)

http://workspaces.gotdotnet.com/ResolutionRPG

Posted
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. :)

Posted
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.

Posted

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!

Posted

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!

d3dPick.cls.txt

Posted

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.

Posted

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...

Posted
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

Posted (edited)

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;

}

Edited by israel
  • 1 month later...
Posted (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.

Edited by Reidar Lange
  • 10 months later...
Posted

How would you do this in code?

 

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

 

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.

Posted

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);

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...