Monday, January 11, 2016

geometry - Morph a sphere to a cube and a cube to a sphere with GLSL


I'm getting started with GLSL with quartz composer. I have a patch with a particle system in which each particle is mapped into a sphere with a blend value. With blend=0 particles are in random positions, blend=1 particles are in the sphere. The code is here:


vec3 sphere(vec2 domain)
{
vec3 range;
range.x = radius * cos(domain.y) * sin(domain.x);
range.y = radius * sin(domain.y) * sin(domain.x);
range.z = radius * cos(domain.x);

return range;
}

// in main:

vec2 p0 = gl_Vertex.xy * twopi;
vec3 normal = sphere(p0);;
vec3 r0 = radius * normal;
vec3 vertex = r0;


normal = normal * blend + gl_Normal * (1.0 - blend);
vertex = vertex * blend + gl_Vertex.xyz * (1.0 - blend);

I'd like the particle to be on a cube if blend=0


I've tried to find but I can't figure out some parametric equation for the cube. Maybe it is not the right way?



Answer



edit: source shader code tested, updated and works...


morph teapot to cube


there is also video...


Once you use a 3D coord instead 2D to sample cube, it is possible (but not parametric :)).



First theory:


Use normalize(GL_Vertex - cubeOrigin) as sampling vector.


You have to know to which face of cube vertex belongs. It is the biggest componnent in sampling vector.


Once you have face, you can specify face normal. Than compute angle between face normal and sampling vector. Use Law of sines to get distance of point in space from cube origin(in middle). Multiply this distance with normal and you got it :)


// this code sucks for shader ... it would be slow it is written to be clear not optimal.


uniform int timer;

//return face's ID based on sampling vector

int face(vec3 coord)
{
if((abs(coord.x) > abs(coord.y)) && (abs(coord.x) > abs(coord.z)))
{
if (coord.x > 0)
return 0;
else
return 1;
}
if( abs(coord.y) > abs(coord.z))

{
if (coord.y > 0)
return 2;
else
return 3;
}
if (coord.z > 0)
return 4;
return 5;
}


vec3 cube(vec3 position,vec3 cubeOrigin)
{
int CUBE_SIZE = 2;
vec3 coord = normalize(position - cubeOrigin);
int face = face(coord);
vec3 faceNormal = vec3(0);
switch (face)
{
case 0: faceNormal = vec3(1,0,0); break;

case 1: faceNormal = vec3(-1,0,0); break;
case 2: faceNormal = vec3(0,1,0); break;
case 3: faceNormal = vec3(0,-1,0); break;
case 4: faceNormal = vec3(0,0,1); break;
case 5: faceNormal = vec3(0,0,-1); break;
}

float gamma = acos (dot(faceNormal,coord));
float alfa = 3.14 - 1.57 - gamma; //there is no PI or HALF_PI in glsl you have to define it on your own.
//this is little hard stuff. You want to know length from origin to place on cube. It is simple triangle and can be solved by law of sines.

//It should be multiplied with sin(HALF_PI) but it is 1.
float posFactor = (CUBE_SIZE/2.0)/sin(alfa) ;

return (cubeOrigin + coord * posFactor);
}

void main(void)
{
vec3 transformed = cube(gl_Vertex.xyz,vec3(0.0,0.0,0.0));
vec4 cubetrans = vec4 (transformed,1.0);

gl_Position = mix(gl_ModelViewProjectionMatrix * cubetrans,gl_ModelViewProjectionMatrix * gl_Vertex,timer/200.0);

gl_FrontColor = gl_Color;
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...