0
\$\begingroup\$

I am creating a 3D ray tracer and want to add textured planes.

My planes are stored using a position vector and a normal vector.

I want to use a square texture and map it repetitively onto the plane.

How do I figure out a transformation from points (3D vectors) on the plane and points (2D vectors) on a texture? Once I know how to do this transformation, I don't think making it repetitive will be hard, as we can just apply modulo arithmetic.

I thought I could make a basis on the plane by calculating a vector B1 perpendicular to the normal, and then another one, B2, perpendicular to the normal and B1. But once I have these two vectors, I still don't know how to express the point (which is the argument for the function below) in this basis.

Vector3 position, normal;
Bitmap texture;

public override Vector3 GetColor(Vector3 point) {
    int u = ? 
    int v = ? 

    return texture.GetPixel(u, v);
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Have you consulted existing questions about texture mapping planes in worldspace? Did you run into any particular difficulty applying those answers to your situation? \$\endgroup\$ – DMGregory May 27 at 18:27
  • \$\begingroup\$ @DMGregory Yes, but I'm not using shaders or anything like that, so I didn't know how to apply that. I just want to convert world coordinates into a coordinate system that I create on the plane. \$\endgroup\$ – The Coding Wombat May 27 at 19:08
  • \$\begingroup\$ That's fine, a texture coordinate vector is a texture coordinate vector, whether you compute it on the CPU ot GPU. So this shouldn't change the fundamental operations you need to perform. \$\endgroup\$ – DMGregory May 27 at 19:09
  • \$\begingroup\$ @DMGregory It worked. Thank you. \$\endgroup\$ – The Coding Wombat May 27 at 21:49
  • 1
    \$\begingroup\$ Please feel free to share your solution as an Answer, so we have a non-Unity/non-shader example to share with future users. :) \$\endgroup\$ – DMGregory May 27 at 21:51
1
\$\begingroup\$

To go from a point in worldspace, p = (x, y, z) and on the plane to texture coordinates u, v, you must first create a basis of 2 vectors, e1, e2 of the plane.

Given that N is the plane's normalized normal vector, we first create a vector perpendicular to this normal and some random other vector not parallel to the normal:

e1 = Vector3.Normalize(Vector3.Cross(N, new Vector3(1, 0, 0)));

//If normal and (1,0,0) are parallel, change e1
if (e1 == new Vector3(0, 0, 0)) {
    e1 = Vector3.Normalize(Vector3.Cross(N, new Vector3(0, 0, 1)));
}

And then we create the second basis vector by taking the cross product of the first basis vector and the normal, so that it is perpendicular to the normal, not parallel to the other basis vector, and thus in the plane:

e2 = Vector3.Normalize(Vector3.Cross(N, e1));

Then we can get the texture coordinates u, v by taking the dot product of the point in worldspace, p, with e1 and e2 respectively:

u = Vector3.Dot(e1, p);
v = Vector3.Dot(e2, p);

You might still have to do some scaling by texture sizes.

Source: UV World mapping in shader with Unity. and @DMGregory

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.