Mesh.Intersect issue

Started by
9 comments, last by sumit381 17 years, 2 months ago
Hello, I am writing a DX app using C#, VS05, and DX 9.0c SDK. My app takes an xml files filed with x,y,z coords and makes an array of Vector3 called dataList. This data is then used to create a bunch of spheres as data points on a grid. The problem I am having is being able to select the data point when I click on them. The data points are rendered as sphere meshes stored in a mesh called dataSphereMesh. When I render the data points, I loop through my dataList array and create a subset of the dataSphereMesh for each item in the array. This is the picking code that I am currently using:

private void DrawDataPoints()
{
   d3dDevice.SetTexture(0, null);
   for (int i = 0; i <= dataList.Length - 1; i++)
   {
      d3dDevice.Transform.World = Matrix.Translation((float)dataList.X, (float)dataList.Y, (float)dataList.Z);

      dataSphereMesh.DrawSubset(0);
   }
}

protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
{
   mousing = true;
   string test = "";
   for (int i = 0; i <= dataList.Length - 1; i++)
   {
      dataPosition = new Vector3(dataList.X, dataList.Y, dataList.Z);
      if (testHit(e.X, e.Y, dataPosition))
         test = "it's a hit!";
      else
         test = "false";
   }
   this.Text = test;
}


private bool testHit(Single x, Single y, Vector3 position)
{
   Vector3 near = new Vector3(x, y, 0);
   Vector3 far = new Vector3(x, y, 1);
   near.Unproject(d3dDevice.Viewport, d3dDevice.Transform.Projection, d3dDevice.Transform.View, Matrix.Translation(position));

   far.Unproject(d3dDevice.Viewport, d3dDevice.Transform.Projection, d3dDevice.Transform.View, Matrix.Translation(position));

   far.Subtract(near);
   IntersectInformation closest = new IntersectInformation();
   if (dataSphereMesh.Intersect(near, far, out closest))
     return true;
   else
     return false;
}

When I run the code, I am only able to click on the very last item in the array. Please help in this matter if possible, thanks. [Edited by - Washu on February 13, 2007 12:06:20 PM]
Advertisement
hey.. i got the same/similar problem. i just wrote about it here couple of hours ago:
http://www.gamedev.net/community/forums/topic.asp?topic_id=435413

hopefully there is some solution for this.
It seems the problem isn't with the picking, but with your looping. A hit on any other item than the last one does get recorded, but is subsequently overwritten as you continue to loop over the other elements in the data array. You should break or return from the loop when you have a hit, that ought to work.

@sumit381: your interest in this thread probably ends here, sorry for the Hijack [smile]

[Edited by - remigius on February 14, 2007 3:12:21 AM]
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
well that makes sense but its not the problem in my case. im only cycling thru the first four objects and if there is a success, it breaks from the loop with a flag 'isPicked=true' and another variable set to the picked object (which is then used to output the information). those two get null'd everytime i click the mouse button. i get output only when i click on the 16th object, which is not even close to the first four im cycling thru and the fact that its the very last one just makes me wonder.. if it wasnt the last object, i guess it would be some kind of a bug but in this case i just thing there is something i missed.

i also tried to output some information about each of the meshes that get loaded upon the object creation and each of them has the same HashId. so now im even more confused. we're just goin to visit one of the proffessors from our uni and i hope he brings some light into our lives.
@EwanK:

Was ZMan's reply in your MSDN thread of any use? Without more code, I'd make the same guess he offers. You need to unproject the ray for each object with the appropriate world matrix, otherwise it won't work. This is necessary since the Mesh.Intersect method works in local object space, as explained in more detail over here.

If you're using other world-space rays (for collision detection for example), you'll need to transform them by the inverse of the world matrix for each object, so the rays are in local object space to satisfy the requirements for using Mesh.Intersect.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
yeah, i just checked it out and already replied.
but as i wrote in my reply, im not sure how to do that unprojection he meant and included the code of my method that calculates those two vectors (which i havent made up myself, just modified a VB.NET sample i found somewhere before).

edit: just tell me what more code you need 8-)
so ive changed the picking cycle to this:

for( int i = 0; i < ActivePlayer.characters.Count; i++ )
{
Character panak = ActivePlayer.characters as Character;
//IntersectInformation[] closestHit;
closestHit = new IntersectInformation();
isPicked = false;
intPanacik = null;
device.Transform.World = Matrix.Identity;
device.Transform.World = Matrix.Translation( panak.x, panak.y, 0 );
rayOrigin = new Vector3();
rayDir = new Vector3();
calcRay( mouseX, mouseY, ref rayOrigin, ref rayDir );
if( panak.charMesh.Intersect( rayOrigin, rayDir,out closestHit ) )
{
if( closestHit.FaceIndex <= panak.charMesh.NumberFaces )
{
isPicked = true;
pickedPanakIndex = i;
isWaitingToPick = false;
intPanacik = panak;
break;
}
}
}


so im actually recalculating the picking vectors just before the intersection check happens. the thing is that now i dont succeed with the last orange piece, but with each of the green ones, with output saying i clicked on the very first one. but we're coming closer! :)

edit: and i know for sure that the x and y of those four pieces are different as they were already used to draw them to their appropriate spots.
The 'unprojection' basically is what happens in your calcRay method, the mouse coordinaate gets translated from camera space to your local object space. You need to unproject your ray seperately for each object, since each object has a different world matrix. So in pseudo code:

foreach( panak in yourPanakArray ){  panakWorldMatrix = Matrix.Translation( panak.x, panak.y, 0 );    Vector3 vIn = new Vector3( mouseX, mouseY, 0 );  Vector3 vFar = new Vector3( mouseX, mouseY, 1 );    // use object's world matrix for EACH unprojection  near = Vector3.Unproject( vIn, device.Viewport, device.Transform.Projection,    device.Transform.View, panakWorldMatrix  );      vFar = Vector3.Unproject( vFar, device.Viewport, device.Transform.Projection,     device.Transform.View, panakWorldMatrix  );    far = Vector3.Subtract( vFar, near );  IntersectInformation closestHit;    if( panak.charMesh.Intersect( near, far, out closestHit ) )  {    // intersection!  }}


As for why this is needed, it's a bit hard to explain without going into vector spaces. Basically the vertices in the mesh are defined in local object space. By transforming these with a world matrix, you typically display them at some location in the world space, but the vertices themselves are not changed and remain in local object space (as if a Matrix.Translation(0, 0, 0) was used for the world matrix).

Hence operations like Mesh.Intersect require the rays to be in local object space too, since the mesh doesn't know about any world space transformations. By unprojecting the rays for each object with its appropriate world matrix, you obtains the rays in local object space. Maybe a picture will clear things up:



Hope this helps (and upstages ZMan [wink])
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
thanks for clearing it up :) but that does the same thing it does with my previous modifications - it succeeds with all four green pieces BUT says i clicked on the first one of them even tho i clicked on one of the other three. i think im still missing something :I
aight, i got it working finally :) i just needed to multiply the objects world matrix with the scaling matrix. THANKS A LOT!

This topic is closed to new replies.

Advertisement