riemerg

Hi all --

I'm porting a water shader to XNA, but first I need to get my clip planes right. I noticed we still need to unproject the plane from camera space to world space, but I cannot find a method that actually allows to transform a plane! Like the MDX Plane.Transform method used to do.

I tried to transform 3 world points with the inverse of my world*view*proj matrix, and create a plane including these points, but no luck.




Re: XNA Framework (Clip) Plane transform?

Derek Nedelman

You should calculate the world space plane from your vertices (using your model's local->world transformation matrix, which is what you seem to already be doing) and then transform the coefficients of that plane by the inverse transpose world*view*proj matrix. (The world matrix in this case is an additional, optional, world transformation, not your model's world matrix)

You will end up with code that looks something like this:

//It's assumed there's a plane instance called worldClipPlane and a Matrix called worldViewProjection that takes world space coordinates to projective space coordinates. If you don't do anything with your world coordinates (like flip them for doing reflections), then worldViewProjection is the same as view*projection

Matrix planeProjectionMatrix = Matrix.Transpose(Matrix.Invert(worldViewProjection));
Vector4 worldClipPlaneCoefficients = new Vector4(worldClipPlane.Normal.X, worldClipPlane.Normal.Y, worldClipPlane.Normal.Z, worldClipPlane.D);
Vector4 projectedPlaneCoefficients = Vector4.Transform(worldClipPlaneCoefficients, planeProjectionMatrix);
projectedPlaneCoefficients.Normalize();

graphicsDevice.ClipPlanes[0].Plane = new Plane(projectedPlaneCoefficients);
graphicsDevice.ClipPlanes[0].IsEnabled = true;

This code is adapted from my 3DS Viewer project, which I use to render reflections. You can find the usage in the DrawMirrors() method in Scene.cs.





Re: XNA Framework (Clip) Plane transform?

riemerg

Hi there Derek,

thanks for the reply, I got it working using your vector4 approach ;) Somehow, the creation of a plane using the 3 points vector doesn't want to give the correct results.

I have one more question: are you sure about the projectedPlaneCoefficients.Normalize(); line Ofcourse, the direction of the normal can be normalized, but generally if you apply the Normalize method to a Vector4, the w component is also affected. This w component is the distance from your origin perpendicular to the plane, so I think this should give problems. I think you only want the direction of the normal to be normalized.






Re: XNA Framework (Clip) Plane transform?

Derek Nedelman

There was a bug introduced into the Beta 2 Plane(Vector3,Vector3,Vector3) constructor. It doesn't correctly initialize the plane, so you'll need to calculate it yourself. Here's some code for how I do (you may need to change the order of the vertices for your own program):

public static void CreatePlane(ref Vector3 p0, ref Vector3 p1, ref Vector3 p2, out Plane result)
{
Vector3 normal;
CreateNormal(ref p0, ref p1, ref p2, out normal);

result = new Plane(normal, -Vector3.Dot(normal, p0));
}

public static void CreateNormal(ref Vector3 p0, ref Vector3 p1, ref Vector3 p2, out Vector3 result)
{
Vector3 v0;
Vector3.Subtract(ref p1, ref p0, out v0);

Vector3 v1;
Vector3.Subtract(ref p2, ref p1, out v1);

Vector3.Cross(ref v0, ref v1, out result);
result.Normalize();
}

As for projectedPlaneCoefficients.Normalize(), yes, it's correct as it is. Actually, it should even work without the normalization since if you scale all the coefficients of a plane equation you still have the same plane (I wasn't sure at the time whether DirectX required it to be normalized). If you normalize just the A/B/C components you will change the plane equation.






Re: XNA Framework (Clip) Plane transform?

riemerg

Thanks derek for the nice methods.

However, I fear I must disagree with your last lines. The plane(0, 0, 1, -5) is NOT the same as the plane(0, 0, 100, -5). What we want here is the Z=5 plane, but in the second case you get a plane that is more like Z=0.05, because the Vector4 is normalized. I solve this by using:

 

<pseudocode, XNA not installed on this pc>

Vector3 normaldirection = new vec3(220, 31, 100); //unnormalized vector

normaldirection.Normalize();

Vector4 planecoeffs = new Vector4(normaldirection, -5);

planecoeffs = vec4.transform(planecoeffs, invWVP);

Plane ourclipplane = new Plane(planecoeffs);

</pseudocode>

 

This way, the D coefficient is not affected by the length of our normal. I'm really thankful for helping me out, thanks to you I have finished porting my app.






Re: XNA Framework (Clip) Plane transform?

Derek Nedelman

No, it's fine, I can see where the confusion is. But I didn't say that a plane like (0, 0, 1, -5) was the same as (0, 0, 100, -5).

I was referring to the fact that you when you take your standard plane equation (Ax+By+Cz+D = 0) and scale it by a constant (sAx+sBy+sCz+sD=0), which is what's being done with the Normalize() on the Vector4, you still have the same plane. In this case, don't think about A,B,C as a normal, just think of the entire plane equation. So in the case you gave, (0, 0, 1, -5) is the same plane as (0, 0, 100, -500)

And, in fact, I removed the Normalize() from the code I posted- as I mentioned I could probably do - and the user clip plane in my program still worked as expected.

If you have another method for generating the plane coefficients you are still ending up with the same plane. The only thing that's different is the scale factor.






Re: XNA Framework (Clip) Plane transform?

riemerg

You're completely correct there. Thanks for explaining this in detail ;) I was indeed mixing up an unnormalized normal with an absolute distance.

I have edited away a line from my previous post, as it was completely wrong and only could cause confusion.