israel Posted September 17, 2004 Posted September 17, 2004 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, Quote
Aragorn7 Posted September 17, 2004 Posted September 17, 2004 I really don't know how to do this, but I would check out the link to this VB.NET DX9 tutorial. It says something in there about using "matricies" to get x,y data on the screen or something. I don't know how to go about it though because I am not an expert at matricies yet. :P http://216.5.163.53/DirectX4VB/TUT_DX9Start.asp Quote
ThePentiumGuy Posted September 18, 2004 Posted September 18, 2004 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 Quote 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
Aragorn7 Posted September 18, 2004 Posted September 18, 2004 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. :) Quote
Aragorn7 Posted September 19, 2004 Posted September 19, 2004 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. Quote
Phikwe Posted September 19, 2004 Posted September 19, 2004 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! Quote
Phikwe Posted September 19, 2004 Posted September 19, 2004 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 Quote
israel Posted September 19, 2004 Author Posted September 19, 2004 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. Quote
Phikwe Posted September 20, 2004 Posted September 20, 2004 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... Quote
israel Posted September 21, 2004 Author Posted September 21, 2004 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 Quote
israel Posted September 21, 2004 Author Posted September 21, 2004 (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 September 21, 2004 by israel Quote
Reidar Lange Posted October 29, 2004 Posted October 29, 2004 (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 October 30, 2004 by Reidar Lange Quote
JRodman Posted September 29, 2005 Posted September 29, 2005 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. Quote
Reidar Lange Posted September 30, 2005 Posted September 30, 2005 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); Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.