I had another thread about Mesh movement which kind of turned into this issue, so i'm posting a new thread to state the new problem so people can help me figure it out.
The basic problem i'm having is that whenever we do a device.Transform.World that is not tied to the currently selected object, it messes up the picking ray somehow so that it no longer hits anything. The code where the picking is done is shown below (an excerpt):
//Picking tests etc..for now just do the one unit..eventually handle multiple and only check
//ones that are on-screen by using quad tree culling
Vector3 pickRayOrigin, pickRayDirection;
Matrix matProj = device.GetTransform(Microsoft.DirectX.Direct3D.TransformType.Projection);
int x = e.X;
int y = e.Y;
Vector3 v;
v.X = ( ( ( 2.0f * x ) / device.PresentationParameters.BackBufferWidth ) - 1 ) / matProj.M11;
v.Y = -( ( ( 2.0f * y ) / device.PresentationParameters.BackBufferHeight ) - 1 ) / matProj.M22;
v.Z = 1.0f;
// Get the inverse of the composite view and world matrix
Matrix matView, matWorld, m;
matView = this.device.GetTransform(Microsoft.DirectX.Direct3D.TransformType.View);
matWorld = this.device.GetTransform(Microsoft.DirectX.Direct3D.TransformType.World);
m = matWorld * matView;
m = Matrix.Invert(m);
// Transform the screen space pick ray into 3D space
pickRayDirection.X = v.X * m.M11 + v.Y * m.M21 + v.Z * m.M31;
pickRayDirection.Y = v.X * m.M12 + v.Y * m.M22 + v.Z * m.M32;
pickRayDirection.Z = v.X * m.M13 + v.Y * m.M23 + v.Z * m.M33;
pickRayOrigin.X = m.M41;
pickRayOrigin.Y = m.M42;
pickRayOrigin.Z = m.M43;
//start temporary code without quad-tree support
Unit tempUnitData;
bool matches = false;
//for now just check all units for picking code using an arraylist
for (int j = 0; j < this.createdUnitsList.Count; j++)
{
tempUnitData = (Unit) this.createdUnitsList[j];
//uncomment below for OLD picking method before bounding boxes
//if (tempUnitData.MeshData.Intersect(pickRayOrigin, pickRayDirection))
//{
//new picking code
Matrix Wtrans = tempUnitData.returnRotateXTranslation() *
tempUnitData.returnRotateYTranslation() * tempUnitData.returnRotateZTranslation()
* tempUnitData.returnObjectTranslation();
Matrix InWTrans = Matrix.Invert(Wtrans);
Vector3 IpickRayDirection = Vector3.TransformNormal(pickRayDirection, InWTrans);
Vector3 IpickRayOrigin = Vector3.TransformCoordinate(pickRayOrigin, InWTrans);
if (tempUnitData.myCollisionObject.ORayProbe(IpickRayOrigin, IpickRayDirection))
The ORayProbe method being called in the code above is found below:
public bool ORayProbe(Vector3 rayPosition, Vector3 rayDirection)
{
return Geometry.BoxBoundProbe(this.OLowerLeft, this.OUpperRight, rayPosition, rayDirection);
}
The OUpperRight and OLowerLeft parameters in the code above represent the location of a static boundingbox drawn around the mesh located at the origin (in WorldSpace).
Here is the code where the model is actually drawn in our Unit class.
protected void DrawModel()
{
//this method is dependent on the constructor being formed properly with meshMaterials and meshTextures properties
for (int i = 0; i < this.meshMaterials.Length; i++)
{
this.device.Material = this.meshMaterials;
this.device.SetTexture(0, this.meshTextures);
//we are doing an X, Y, Z, and translation here by multiplying 4 matrices together - ORDER matters!
Matrix Wtrans = this.returnRotateXTranslation() *
this.returnRotateYTranslation() * this.returnRotateZTranslation()
* this.returnObjectTranslation();
this.device.Transform.World = Wtrans;
//just debug code to render all meshes as wireframes for now - they look better than untextured!
//device.RenderState.FillMode = FillMode.WireFrame;
device.RenderState.FillMode = FillMode.Solid;
this.mesh.DrawSubset(i);
}
}
This is where we think the issue is. The code works fine with one unit loaded. You can select it, move it around etc with no issues. When you load more than one unit, you can select one, move it somewhere then shift-select another so that you have both selected. You can even move both to somewhere on the screen. As soon as you unselect them though, and then try to re-select either unit, you never detect a hit. It seems like moving the second unit renders the picking code invalid somehow b/c it doesnt account for the device.Transform.World change that took place.
How can we rewrite the picking code to take in account the movement, or is there something we need to do when we draw to fix the world transform back to its original state?
Thanks,
Nathan
[Edited by - ironwill96 on March 15, 2005 6:27:03 PM]
"There are those who said this day would never come, what do they have to say now?" - Halo 2 Trailer