View Full Version : texture-space to object-space

AdrianPi

11-03-2009, 10:50 AM

I need to go from texture space to object space.

Having a triangle with vertices p0, p1, p2 and texture coordinates t0, t1, t2, i'm constructing a 3x3 matrix 'A' as:

| v1.x v2.x n.x |

| v1.y v2.y n.y |

| v1.z v2.z n.z |

where v1 and v2 are the vectos lying on the 2 sides of the triangle:

v1 = p0 - p1

v2 = p2 - p1

and n is the normal:

n = |v1 x v2| (normal)

This matrix would go from "triangle-space" to object space.

Then I'm constructing another matrix ('B') as:

| uv1.x uv2.x 0 |

| uv1.y uv2.y 0 |

| uv1.z uv2.z 1 |

Where uv1 is t0-t1 and uv2 is t2-t1 (as before).

This matrix would go from "texture-space" to triangle-space

Finally to convert from texture-space to object-space I'm calculating the final matrix as:

m = B * A

But it doesn't work. What am I doing wrong?

Any help will be appreciated.

DmitryM

11-03-2009, 11:29 AM

As far as I see you want a tangent space basis matrix.

Instead of looking for the error in your code, I'll provide some links with working code.

http://www.terathon.com/code/tangent.html

http://jerome.jouvie.free.fr/OpenGl/Lessons/Lesson8.php

AdrianPi

11-03-2009, 12:30 PM

Thanks, but I want to understand what I'm doing, and not borrow someone else's code/method.

DmitryM

11-03-2009, 12:52 PM

Ok, but take in account that links provided contain the extensive explanation, not just plain working code.

As far as I see, your B matrix transforms from triangle space to tangent space (inverse of what you are saying). So, assuming that you put the vector to the left of a matrix when multiplying, you need the following matrix in the result:

m = inv(B) * A

AdrianPi

11-03-2009, 01:40 PM

I've seen the links, but after posting I realized that for what I want to do what I need is the full transformation (including translation). I need texture points (W=1) in space (and vice-versa), no just vectors (W=0) for tangent-space lighting.

Thus I expanded A to

| v1.x v2.x n.x 0 |

| v1.y v2.y n.y 0 |

| v1.z v2.z n.z 0 |

| p1.x p1.y p1.z 1 |

and B to

| uv1.x uv2.x 0 0 |

| uv1.y uv2.y 0 0 |

| uv1.z uv2.z 1 0 |

| t1.x t1.y t1.z 1 |

Even so, (also with inv(B)) I cannot make it work. I cannot grasp why. After all is two consecutive linear transformations: From texture-space to triangle-space and from triangle-space to object-space...

DmitryM

11-03-2009, 02:51 PM

You are not correct.

==A==:

transform from triangle space to object space:

v' = v.x * v1 + v.y * v2 + v.z * n + p1

So, your matrix should have p1 on the right column instead of bottom row:

| v1.x v2.x n.x p1.x |

| v1.y v2.y n.y p1.y |

| v1.z v2.z n.z p1.z |

| 0 0 0 1 |

==B==:

the same mistake, should be:

| uv1.x uv2.x 0 t1.x |

| uv1.y uv2.y 0 t1.y |

| uv1.z uv2.z 1 t1.z |

| 0 0 0 1 |

AdrianPi

11-03-2009, 03:31 PM

You are right. My mistake.

Is wrong in the post, but done right in the code:

c#:

Matrix4f A = new Matrix4f(v0, v1, n, p0);

*****

public Matrix4f(Vector3f xaxis, Vector3f yaxis, Vector3f zaxis, Vector3f pos)

{

m00 = xaxis.X;

m01 = xaxis.Y;

m02 = xaxis.Z;

m03 = 0.0f;

m10 = yaxis.X;

m11 = yaxis.Y;

m12 = yaxis.Z;

m13 = 0.0f;

m20 = zaxis.X;

m21 = zaxis.Y;

m22 = zaxis.Z;

m23 = 0.0f;

m30 = pos.X;

m31 = pos.Y;

m32 = pos.Z;

m33 = 1.0f;

}

DmitryM

11-03-2009, 04:05 PM

I hope you have a correct matrix * vector multiplication.

How do you test the correctness of the tangental space basis?

You should try to use the working equations for the start, just to be sure everything else works correctly.

marshats

11-03-2009, 04:40 PM

DmitryM has the solution:

==A==:

| v1.x v2.x n.x p1.x |

| v1.y v2.y n.y p1.y |

| v1.z v2.z n.z p1.z |

| 0 0 0 1 |

==B==:

| uv1.x uv2.x 0 t1.x |

| uv1.y uv2.y 0 t1.y |

| uv1.z uv2.z 1 t1.z |

| 0 0 0 1 |

Those definitions explicitly mean:

object_coord=A*Triangle_coord

Textre_coord=B*Triangle_coord

so you can solve for Triangle_coord

Triangle_coord=Inverse(B)*Textre_coord

hence

object_coord=A*Triangle_coord

=A*Inverse(B)*Textre_coord

Note the order of operations though!

AdrianPi

11-03-2009, 05:54 PM

This is craving my brain. It's a small test app in C# using OpenTK:

private void myGLControl1_Paint(object sender, PaintEventArgs e)

{

GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

// Draw triangle with texture

GL.Color3(1.0f, 1.0f, 1.0f);

GL.Enable(EnableCap.Texture2D);

tex.Bind();

GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);

GL.Begin(BeginMode.Triangles);

GL.TexCoord2(t0.X, t0.Y);

GL.Vertex3(p0.X, p0.Y, p0.Z);

GL.TexCoord2(t1.X, t1.Y);

GL.Vertex3(p1.X, p1.Y, p1.Z);

GL.TexCoord2(t2.X, t2.Y);

GL.Vertex3(p2.X, p2.Y, p2.Z);

GL.End();

// Draw triangle in wireframe

GL.Color3(1.0f, 1.0f, 0.0f);

GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line);

GL.LineWidth(3);

GL.Disable(EnableCap.Texture2D);

GL.Begin(BeginMode.Triangles);

GL.Vertex3(p0.X, p0.Y, p0.Z);

GL.Vertex3(p1.X, p1.Y, p1.Z);

GL.Vertex3(p2.X, p2.Y, p2.Z);

GL.End();

// Compute triangle basis

Vector3f v0 = p1 - p0;

Vector3f v1 = p2 - p0;

Vector3f n = Vector3f.CrossProduct(v0, v1);

//n.Normalize(); // not really needed

Matrix4f A = new Matrix4f(v0, v1, n, p0);

// Point to locate tangent and bitangent origin somewhere outside the triangle

Vector3f temp = A.TransformPoint(new Vector3f(-0.1f, -0.1f, 0.0f));

GL.PointSize(4);

GL.Color3(1.0f, 0.0f, 1.0f);

GL.Begin(BeginMode.Points);

GL.Vertex3(temp.X, temp.Y, temp.Z);

GL.End();

// Texture basis

Vector3f uv0 = t1 - t0;

Vector3f uv1 = t2 - t0;

Vector3f uvn = Vector3f.CrossProduct(uv0, uv1);

Matrix4f B = new Matrix4f(uv0, uv1, uvn);

B.Invert();

//Matrix4f C = A * B;

Matrix4f C = B * A;

// Draw tangent vector

Vector3f tan = C.TransformVector(new Vector3f(1.0f, 0.0f, 0.0f)) * 0.5f;

GL.Color3(1.0f, 0.0f, 0.0f);

GL.Begin(BeginMode.Lines);

GL.Vertex3(temp.X, temp.Y, temp.Z);

GL.Vertex3(temp.X+tan.X, temp.Y+tan.Y, temp.Z+tan.Z);

GL.End();

// Draw bitangent (or binormal)

Vector3f bitan = C.TransformVector(new Vector3f(0.0f, 1.0f, 0.0f)) * 0.5f;

GL.Color3(0.0f, 1.0f, 0.0f);

GL.Begin(BeginMode.Lines);

GL.Vertex3(temp.X, temp.Y, temp.Z);

GL.Vertex3(temp.X + bitan.X, temp.Y + bitan.Y, temp.Z + bitan.Z);

GL.End();

// Overimpose full texture quad over the triangle

Vector3f c0 = C.TransformPoint(new Vector3f(0, 0, 0));

Vector3f c1 = C.TransformPoint(new Vector3f(1, 0, 0));

Vector3f c2 = C.TransformPoint(new Vector3f(1, 1, 0));

Vector3f c3 = C.TransformPoint(new Vector3f(0, 1, 0));

GL.Enable(EnableCap.Blend);

GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

GL.Color4(1.0f, 1.0f, 1.0f, 0.5f);

GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);

GL.Enable(EnableCap.Texture2D);

GL.Begin(BeginMode.Quads);

GL.TexCoord2(0, 0);

GL.Vertex3(c0.X, c0.Y, c0.Z);

GL.TexCoord2(1, 0);

GL.Vertex3(c1.X, c1.Y, c1.Z);

GL.TexCoord2(1, 1);

GL.Vertex3(c2.X, c2.Y, c2.Z);

GL.TexCoord2(0, 1);

GL.Vertex3(c3.X, c3.Y, c3.Z);

GL.End();

GL.Disable(EnableCap.Blend);

GL.Disable(EnableCap.Texture2D);

myGLControl1.SwapBuffers();

}

It works perfectly as long as B is identity i.e. tex coords (0,0) (1,0) (0,1)

Matrix multiplication, inversion et al had all been proved good with hierarchical transforms, camera transform (inverse of normal transform) and skinning

AdrianPi

11-03-2009, 06:37 PM

Got it!

Matrix4f B = new Matrix4f(uv0, uv1, uvn);

Should have been:

Matrix4f B = new Matrix4f(uv0, uv1, uvn, t0);

Thank you guys!!!

marshats

11-03-2009, 06:41 PM

quick question, which one worked?

Matrix4f C = A * Inverse(B); ?

or

Matrix4f C = Inverse(B) * A; ?

AdrianPi

11-03-2009, 06:43 PM

http://i35.tinypic.com/x3fvh5.png

AdrianPi

11-03-2009, 06:50 PM

Well, I it will ever depend on how matrix multiplication was written. In my case the latter. For a standard "scale, rotate, translate" I write M = S * R * T

You both where right. Thanks again.

Powered by vBulletin® Version 4.2.3 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.