🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Mapping textured triangle to sphere

Started by
8 comments, last by JoeJ 2 years, 6 months ago

For a project I'm working on I need to map a textured triangle to a sphere. The triangle should be centered around the sphere.

What I need is the texture color, texture normal, whether or not the triangle is facing the center of the sphere and the distance of the texel from the center of the sphere.

This should be done as efficiently as possible because I'll need to do this a lot.

Anyone that could help me out?

Advertisement

This is what I have so far… but for some reason it doesn't really look right. It's just colored by the x y and z positions so far.

Let me know if you see a problem.

Vector3 p1 = new Vector3(0, 1f, 0f);

Vector3 p2 = new Vector3(1f, 0, 0f);

Vector3 p3 = new Vector3(0f, 0, 1f);

float yv1 = Mathf.Acos(p1.z);

float yv2 = Mathf.Acos(p3.z);

yv1 *= Mathf.Rad2Deg;

yv2 = Mathf.Rad2Deg;

float la = 1f / (yv1 - yv2);

float ii = 0f;

for(float y= yv2; y < yv1; y+=1f)

{

Vector3 lp = Vector3.Lerp(p1, p2, la * ii);

Vector3 rp = Vector3.Lerp(p1, p3, la * ii);

float xv1 = Mathf.Atan(lp.y / lp.x);

float xv2 = Mathf.Atan(rp.y / rp.x);

xv1 *= Mathf.Rad2Deg;

xv2 *= Mathf.Rad2Deg;

float ys = Mathf.Sin((y) * Mathf.Deg2Rad);

float z = Mathf.Cos((y) * Mathf.Deg2Rad);

if(xv2>xv1)

{

float tmp = xv1;

xv1 = xv2;

xv2 = tmp;

}

for(float x = xv2; x <xv1; x+=1f)

{

float xx = ys * Mathf.Cos(x*Mathf.Deg2Rad);

float yy = ys * Mathf.Sin(x*Mathf.Deg2Rad);

float xxx = xx * 50f + t.width / 2;

float yyy = yy * 100f + t.height / 2;

c[(int)(xxx) + (int)(yyy) * t.width] = new Color(xx, yy, z, 1f);

}

ii += 1f;

}

Turbo14 said:
I need to map a textured triangle to a sphere.

Neither your descriptions nor the code make clear to me what you try to do.
I would guess you want something like this:

Which would be a projection to the surface of a sphere, resulting in a spherical triangle where straight edges now become curved arcs.
And how do you need this, if so? Arc coordinates, or rasterized to a texture the sphere is using?
You might to draw such image to illustrate your problem.

I'm working on a new ray tracing acceleration method that needs triangles mapped to spheres to work.

The speed of it mostly depends on the speed of the triangle to sphere mapping.

Anyways, here's what I have now that seems to work as far as I can tell.

It doesn't work for spheres of all resolutions but for the resolution I'm aiming for it works.

Vector3 p1 = new Vector3(0f, 1f, 0f);

Vector3 p2 = new Vector3(1f,0f, 0f);

Vector3 p3 = new Vector3(0f,0f, 1f);

p1.Normalize();

p2.Normalize();

p3.Normalize();

float d = Vector3.Distance(p1*4, p3*4);

d *= 22.5f;

float la = 1f / d;

for(float i = 0; i < d; i+=1f)

{

Vector3 lp = Vector3.Lerp(p1, p3, la * i);

Vector3 rp = Vector3.Lerp(p1, p2, la * i);

float dd = Vector3.Distance(lp * 4, rp * 4);

dd *= 45f;

float laa = 1f / dd;

for(float j = 0; j < dd; j++)

{

Vector3 p = Vector3.Lerp(lp, rp, laa * j);

float ddd = Vector3.Distance(p, Vector3.zero);

float x = (2f - ddd) * p.x;

float y = (2f - ddd) * p.y;

float z = (2f - ddd) * p.z;

float xx = x * 45f + t.width / 2;

float yy = y * 90f + t.height / 2;

c[(int)xx + (int)yy * t.width] = new Color(x, y, z, 1f);

}

}

Turbo14 said:
I'm working on a new ray tracing acceleration method that needs triangles mapped to spheres to work.

I'm absolutely sure your idea is not new. But it sounds good. The code however looks more like guesswork and magic numbers fun. It should be much simpler. If you need further help, be more specific… ; )

Updated the code. This time it should actually be correct.

Right now it maps the uv coords to a sphere.

Vector3 p1 = new Vector3(0, -1f, 0);

Vector3 p2 = new Vector3(1f, 1f, 0);

Vector3 p3 = new Vector3(0, 1f, 1f);

Vector2 uv1 = new Vector2(.5f, 1f);

Vector2 uv2 = new Vector2(0, 0);

Vector2 uv3 = new Vector2(0, 1f);

float lat1 = Mathf.Acos(p1.y);

float lat2 = Mathf.Acos(p2.y);

float lat3 = Mathf.Acos(p3.y);

float lon1 = Mathf.Atan(p1.z);

float lon2 = Mathf.Atan(p2.z);

float lon3 = Mathf.Atan(p3.z);

float s = lat3 * Mathf.Rad2Deg;

float e = lat1 * Mathf.Rad2Deg;

float la = 1f / (e - s);

float ii = 0;

for (float i = s; i <e; i+=1f)

{

Vector2 luv = Vector2.Lerp(uv3, uv1, la * ii);

Vector2 ruv = Vector2.Lerp(uv2, uv1, la * ii);

ii += 1f;

float x = Mathf.Sin(i * Mathf.Deg2Rad) * Mathf.Cos(lon2);

float x2 = Mathf.Sin(i * Mathf.Deg2Rad) * Mathf.Cos(lon3);

x *= Mathf.Rad2Deg;

x2 *= Mathf.Rad2Deg;

int i1 = (int)i+(h-180)/2;

int j1 = (int)x + w / 2;

int j2 = (int)x2 + w / 2;

float laa = 1f / (j1 - j2);

float jj = 0;

for(float j = j2; j <= j1; j+=1f)

{

Vector2 uv = Vector2.Lerp(luv, ruv, laa * jj);

jj += 1f;

c[(int)j + (int)i1 * w] = new Color(uv.x, uv.y, 1f, 1f);

}

}

I decided to abandon this approach. Instead, I now store a texture that rasterizes triangles that are in and outside the view of the camera, which is easier to deal with than the sphere mapping approach.

What I'm trying to do is sort of like this:

Mara2016DeepGBuffer-extended-bright.pdf (nvidia.com)

I like this paper, which is a similar idea: https://graphics.tudelft.nl/Publications-new/2021/VSE21/SDAO.pdf
IF

This topic is closed to new replies.

Advertisement