razdazzle Posted April 15, 2005 Posted April 15, 2005 hi guys, I'm trying to check for intersections with meshes in my scene(to find out which tile the user clicked on). I am developing a fake isometric(ortho view) tile based game in c# and MDX. I found an example of how to do this in vb.net(intersecting teapot mesh). I played around with it in vb, added extra meshes and changed the view and projection matrices etc. just to mimic how I would be using it in my game. I can't however seem to get the ray picking to work now that I have converted the code. any ideas on where I could be going wrong? here is the vb ver Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load '=======Parameters presentParams = New PresentParameters presentParams.Windowed = True presentParams.SwapEffect = SwapEffect.Discard '=======Device dev = New Direct3D.Device(0, DeviceType.Hardware, pic3d, CreateFlags.HardwareVertexProcessing, presentParams) '=======Mesh mesh = mesh.Teapot(dev) mesh2 = mesh.Teapot(dev) '=======Camera dev.Transform.View = Matrix.LookAtLH(New Vector3(0.0F, 2.0F, 2.0F), New Vector3(0, 0, 0), New Vector3(0, 1, 0)) 'dev.Transform.View = Matrix.LookAtLH(New Vector3(0.0F, 30.0F, 30.0F), New Vector3(1, 1, 0), New Vector3(0, 1, 0)) 'dev.Transform.View = Matrix.LookAtLH(Me.Width / 35, Me.Height / 35, -1000.0F, 10000.0F) dev.Transform.Projection = Matrix.OrthoLH(CSng(Math.PI / 4), 1.3333, 1, 100) '=======Loop Me.Show() MainLoop() End Sub Private Sub MainLoop() Do Render() Application.DoEvents() Loop End Sub Private Sub Render() dev.Clear(ClearFlags.Target, System.Drawing.Color.CornflowerBlue, 1.0F, 0) dev.BeginScene() '========== vec1 = New Vector3(1.7, 0, 0) vec2 = New Vector3(-1.7, 0, 0) dev.Transform.World = Matrix.Translation(vec1) mesh.DrawSubset(0) dev.Transform.World = Matrix.Translation(vec2) mesh2.DrawSubset(0) '========== dev.EndScene() dev.Present() End Sub Private Sub Form1_Mousedown(ByVal sender As System.Object, ByVal e As _ System.Windows.Forms.MouseEventArgs) Handles pic3d.MouseDown If e.Button = MouseButtons.Left Then Intersect(e.X, e.Y, vec1, mesh) Intersect(e.X, e.Y, vec2, mesh2) End If End Sub Public Sub Intersect(ByVal x As Single, ByVal y As Single, ByVal t As Vector3, ByVal m As Direct3D.Mesh) Dim Near As Vector3 Dim Far As Vector3 Dim Closest As IntersectInformation Dim locMesh As Mesh Dim tran As Vector3 Near = New Vector3(x, y, 0) Far = New Vector3(x, y, 1) tran = New Vector3(0, 0, 0) locMesh = m Near.Unproject(dev.Viewport, dev.Transform.Projection, dev.Transform.View, Matrix.Translation(t)) Far.Unproject(dev.Viewport, dev.Transform.Projection, dev.Transform.View, Matrix.Translation(t)) Far.Subtract(Near) '======================================================= ' Here is where you check for an intersection If locMesh.Intersect(Near, Far, Closest) Then dev.RenderState.FillMode = FillMode.WireFrame Else 'dev.RenderState.FillMode = FillMode.Solid End If End Sub here is some important snippets from the c# ver private void SetupCamera() { device.Transform.Projection = Matrix.OrthoLH(this.Width / 35, this.Height / 35,-1000.0f, 10000.0f); //device.Transform.View = Matrix.LookAtLH(new Vector3(0f,0f, 18.0f), new Vector3(28f,28f,0), new Vector3(1,1,0)); device.Transform.View = Matrix.LookAtLH(new Vector3(0f,0f, 18.0f), new Vector3(28f,28f,0), new Vector3(1,1,0)); //device.RenderState.Ambient = Color.DarkBlue; device.Lights[0].Type = LightType.Directional; device.Lights[0].Diffuse = Color.White; device.Lights[0].Direction = new Vector3(0, -1, -2); device.Lights[0].Enabled = true; } protected override void OnMouseDown(MouseEventArgs e) { if(e.Button == MouseButtons.Left) { intersection(grassMesh); } } private void intersection(StaticMesh staticMesh) { IntersectInformation closest = new IntersectInformation(); Vector3 near = new Vector3(xMousePos,yMousePos,0); Vector3 far = new Vector3(xMousePos,yMousePos,1); Vector3 vec = (Vector3) tilesCoOrd[0]; near.Unproject(device.Viewport,device.Transform.Projection,device.Transform.View,Matrix.Translation(vec)); far.Unproject(device.Viewport,device.Transform.Projection,device.Transform.View,Matrix.Translation(vec)); far.Subtract(near); Mesh mesh = staticMesh.getMesh(); if( mesh.Intersect(near,far,out closest)) { //handle intersection } } Quote
Equis1 Posted April 15, 2005 Posted April 15, 2005 I recently implemented Ray Picking myself, I'm not an expert but here is what I did. I tranformed back through the Project and View matrix's and created a ray. Then I used this ray with a bounding sphere in the world to detect my own collisions, instead of using the mesh.intersect() method. Using that method requires you to tranform the ray back through the mesh's world tranform. Which I never got to work properly. I'm not familiar with how the DirectX unproject functions work but I suspect you are getting a translation component in your far vector. Which mesh.intersect() expects a Ray Orgin and Ray Direction (no translation in direction). Anyway, here is how I transformed the mouse click into world co-ordinates private void HardwareToWorld(int x, int y, out Vector3 RayOrig, out Vector3 RayDir) { Matrix invView = Matrix.Invert(device.Transform.View); Vector3 v = new Vector3(); //Reverse the Projection transformation v.X = (float)(((2.0 * x) / container.Width) - 1) / device.Transform.Projection.M11; v.Y = (float)-(((2.0 * y) / container.Height) - 1) / device.Transform.Projection.M22; v.Z = -1; //We are looking down the Z //Multiplying by the inverse Matrix in this way prevents the translation component //of the Matrix from taking affect. RayDir.X = v.X * invView.M11 + v.Y * invView.M21 + v.Z * invView.M31; RayDir.Y = v.X * invView.M12 + v.Y * invView.M22 + v.Z * invView.M32; RayDir.Z = v.X * invView.M13 + v.Y * invView.M23 + v.Z * invView.M33; RayDir.Normalize(); RayOrig.X = invView.M41; RayOrig.Y = invView.M42; RayOrig.Z = invView.M43; RayOrig += RayDir * camera.Near; //Move it to the near plane } Hope it helps! Quote
razdazzle Posted April 16, 2005 Author Posted April 16, 2005 thanks a lot for the reply. I have tried implementing your method, I haven't been able to get it working yet,but I think that may be because I'm scrolling my tile map by changing the tile meshes position in world co-ords. I'll have a go at it again when I set up scrolling based on the view matrix. 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.