2

I am trying to write an algorithm to convert my mouse click to 3D coordinates (to insert an object at this point).

I have "ground" level where Y = 0 and I want to calculate X and Z based on my mouse click. My function currently looks like that:

Point p = this.control.PointToClient(new Point(System.Windows.Forms.Cursor.Position.X, System.Windows.Forms.Cursor.Position.Y));

Vector3 pos = GeometryHelper.Unproject(new Vector3(p.X, 0f, p.Y), viewport.X, viewport.Y, viewport.Width, viewport.Height, projectionPlane.Near, projectionPlane.Far, Matrix4.Invert(mProjectionMatrix * camera.GetViewMatrix()));
active.applyGeometry(pos);

function applyGeometry simply sets the position of an object. I believe passed arguments are self-explanatory.

My Unproject function looks this way:

public static Vector3 Unproject(Vector3 vector, float x, float y, float width, float height, float minZ, float maxZ, Matrix4 inverseWorldViewProjection)
        {
            Vector4 result;

            result.X = ((((vector.X - x) / width) * 2.0f) - 1.0f);
            result.Y = ((((vector.Y - y) / height) * 2.0f) - 1.0f);
            result.Z = (((vector.Z / (maxZ - minZ)) * 2.0f) - 1.0f);

            result.X =
                result.X * inverseWorldViewProjection.M11 +
                result.Y * inverseWorldViewProjection.M21 +
                result.Z * inverseWorldViewProjection.M31 +
                inverseWorldViewProjection.M41;

            result.Y =
                result.X * inverseWorldViewProjection.M12 +
                result.Y * inverseWorldViewProjection.M22 +
                result.Z * inverseWorldViewProjection.M32 +
                inverseWorldViewProjection.M42;

            result.Z =
                result.X * inverseWorldViewProjection.M13 +
                result.Y * inverseWorldViewProjection.M23 +
                result.Z * inverseWorldViewProjection.M33 +
                inverseWorldViewProjection.M43;

            result.W =
                result.X * inverseWorldViewProjection.M14 +
                result.Y * inverseWorldViewProjection.M24 +
                result.Z * inverseWorldViewProjection.M34 +
                inverseWorldViewProjection.M44;

            result /= result.W;

            return new Vector3(result.X, result.Y, result.Z);
        }

The problem is that Unproject function returns result close to 0,0,0 and that makes my object appear around 0,0,0. Any idea how to modify it to work properly?

Update

I believe I have given enough details on this case, but in case you'd need something else to help me out just do not hesitate to tell me ; )

pzaj
  • 1,062
  • 1
  • 17
  • 37
  • http://www.opentk.com/node/1276 (#8 comment) works well (z is up vector) – j-p May 28 '15 at 10:19
  • The unprojected point you'll get will be on the view plane, not on your ground plane, see http://i.stack.imgur.com/W0mDw.png – j-p May 28 '15 at 10:23
  • To get the resulting point on your ground plane, you have to follow the ray traced by your view vector starting at the unprojected point...for this you have to use parametric line equation with y = 0... – j-p May 28 '15 at 10:27
  • I believe I should swap vec.Y and vec.Z in my unproject function, if my up vector is Y? The function you pointed me to return Vector4, my function returns Vector3, is W just not important here? – pzaj May 28 '15 at 10:40
  • w should be 1 to allow Matrix4 transformations to be completed, but after the transformation, only x,y and z are important for you. And yes, if your up vector is Y, => `vec.Z = -(2.0f * mouse.Y / (float)viewport.Height - 1);` and `vec.Y=0;` – j-p May 28 '15 at 10:49
  • wherever I click it returns me a Vector4 similar to that: {(219,6796; 219,759; 219,8385; 2,395841)} (top left corner), {(219,9944; 219,9224; 219,8504; 7,437502)} (top right corner) – pzaj May 28 '15 at 10:50
  • The resulting point should be in world coordinate, the same coordinate system than your objects. – j-p May 28 '15 at 10:53
  • well, these values hardly change apart from W (just like in my previous comments I posted). I'm a bit confused here, what does Vector4 returned by that function do and how can I translate it to Vector3 which is a position vector (having X or Y or Z equals to ground, no matter which one, I'll make any modifications needed). – pzaj May 28 '15 at 11:34
  • w is only significant during matrix with 4 columns tranformation, vec4 to vec3 is completed by simply removing w. You will not be on the ground plane with the unproject function as I've already explained, but on the camera plane... – j-p May 28 '15 at 11:56
  • alright, so I modified it to return Vector3 only, this may sound quite stupid, but what should I do with it to get two points to create the ray? I got really confused about that whole thing. – pzaj May 28 '15 at 12:18
  • the ray you need is the view vector (eye->target) which will gives you the direction. A line may be defined by a point, and a direction. The point you need is the unprojected point. Then, with the resulting line (ray) equation, you should find the only point where y=0... – j-p May 28 '15 at 15:19

0 Answers0