Wednesday, February 10, 2010

GLSL vertex deformer part 2





I began to implement the second part of the GLSL mesh deformer. This part was all about recalculating the surface normals after procedurally moving the vertices of the model. Following the directions provided at this link I was able to perform the steps to calculate a Jacobian matrix based on the original deformation forumla. Using this matrix I was able to correct the surface normals post-deformation.. sort of.

Since this deformation was a radial displacement, I was operating in the polar coordinate system. So before performing the partial derivatives to create the Jacobian matrix, I had to convert some things to polar coordinates. The steps were as follows:

- Convert the vertex position into polar
- Create the Binormal and tangent vectors as described in this link
- Convert the binormal and tangent vectors to polar coordinates
- Convert the incoming surface normal to polar
- Plug all the data into the hard coded Jacobian matrix
- Calculate the new surface normal
- Convert the new surface normal back into cartesian 3 space

With this method, I think I got very close to the desired effect of perfectly deformed surface normals to go along with the deformed mesh. However visually there are still some problems.

I believe the cartesian-to-polar function has some discontinuities that result in holes in the mesh. Also the shading looks off in some way, possibly related to the double coordinate system translation being slightly off. But its getting closer!


Here's the vertex shader as it stands..


const float TWO_PI=6.28318531;
const float PI=3.14159265;
const float HALF_PI=1.57079633;

varying vec4 screenPos, worldPos;

varying vec3 normal, lightDir, halfVector;
varying vec4 diffuse, ambient;

varying float radius,redShift,greenShift,blueShift;

uniform float time;
uniform float displaceAmount1;
uniform float displaceAmount2;

uniform float frequency1;
uniform float frequency2;

varying vec4 eyePosition;
varying vec3 diffuseColor;
varying vec3 specularColor;
varying vec3 emissiveColor;
varying vec3 ambientColor;
varying float shininess;
//varying vec3 normal;

vec3 va;//={0,0,1};
vec3 vb;//={0,1,0};

vec3 renormalizeA;
vec3 renormalizeB;
vec3 renormalizeC;


vec3 vertexSpherical;

float d0;
float d1;
float d2;
float x,y,z;
// float theta,phi,r;

vec4 displacedPoint;

float tri(float phase)
{
float ramppoint;
phase =mod(phase,TWO_PI);
ramppoint=mod(phase,HALF_PI)/(HALF_PI);
if(phase>=0.0 && phase else if(phase>=HALF_PI && phase else if(phase>=PI && phase<(HALF_PI*3.0)) return(-ramppoint);
else if(phase>=(HALF_PI*3.0) && phase<=TWO_PI) return(-1.+ramppoint);
else return(1.0);
}

vec3 sphericalToCartesian( vec3 sphericalCoord)
{
vec3 o;
o.x=sphericalCoord[0]*sin(sphericalCoord[1])*cos(sphericalCoord[2]);
o.y=sphericalCoord[0]*sin(sphericalCoord[1])*sin(sphericalCoord[2]);
o.z=sphericalCoord[0]*cos(sphericalCoord[1]);

return o;

}
vec3 cartesianToSpherical( vec3 cartesianCoord)
{
vec3 o;

float S;

o[0]=length(cartesianCoord);

S=length(cartesianCoord.xy);

o[1]=acos(cartesianCoord.z / o[0]);


//o[2]=atan(cartesianCoord.y/cartesianCoord.x);
if(cartesianCoord.x>=0.0) o[2]=asin(cartesianCoord.y/S);
else o[2]=PI-asin(cartesianCoord.y/S);



return o;

}


float f_r(float rOriginal)
{

return rOriginal+cos(vertexSpherical[1]*frequency1+time)*displaceAmount1 +cos(vertexSpherical[2]*frequency2+time)*displaceAmount2;

}

float f_theta(float thetaOriginal)
{

return thetaOriginal;

}

float f_phi(float phiOriginal)
{

return phiOriginal;

}


void main()
{

x=gl_Vertex[0];
y=gl_Vertex[1]; //flip flopped, so angular parts map to sides ("walls"), instead of along top
z=gl_Vertex[2];

vertexSpherical=cartesianToSpherical(gl_Vertex.xyz);


vec4 displaceVect;


vec4 Vertex=gl_Vertex;

vertexSpherical[0]=f_r(vertexSpherical[0]);
vertexSpherical[1]=f_theta(vertexSpherical[1]);
vertexSpherical[2]=f_phi(vertexSpherical[2]);

displacedPoint[0]=vertexSpherical[0]*sin(vertexSpherical[1])*cos(vertexSpherical[2]);
displacedPoint[1]=vertexSpherical[0]*sin(vertexSpherical[1])*sin(vertexSpherical[2]);
displacedPoint[2]=vertexSpherical[0]*cos(vertexSpherical[1]);
displacedPoint[3]=1.0;

Vertex=displacedPoint;

redShift=0.0;//abs(r);
greenShift=0.0;//abs(theta/6.0);
blueShift=0.0;//abs(phi/6.0);



worldPos=Vertex;
screenPos=gl_ModelViewProjectionMatrix * Vertex ;

gl_Position = screenPos;

eyePosition = gl_ModelViewMatrix * gl_Vertex;

normal = gl_Normal;//normalize(gl_Normal + normalize( gl_Normal-worldPos.xyz));




//Post-deform renormalization:

//Create a couple utility vectors:
va.x=0.0;
va.y=0.0;
va.z=1.0;

vb.x=0.0;
vb.y=1.0;
vb.z=0.0;

va=cartesianToSpherical(va);
vb=cartesianToSpherical(vb);
normal=cartesianToSpherical(normal);




//Generate tangent vector:
vec3 tangent, transformedTangent;
if(length(cross(normal,va))>length(cross(normal,vb))) { tangent=cross(normal,va);}
else { tangent = cross(normal,vb); }

//Generate binormal vector
vec3 binormal, transformedBinormal;
binormal=cross(normal, tangent);


//The Jacobian Matrix :
renormalizeA[0]=1.0;
renormalizeA[1]=-displaceAmount1*sin(frequency1*vertexSpherical[1]+time)*frequency1;
renormalizeA[2]=-displaceAmount2*sin(frequency2*vertexSpherical[2]+time)*frequency2;
renormalizeB[0]=0.0;
renormalizeB[1]=1.0;
renormalizeB[2]=0.0;
renormalizeC[0]=0.0;
renormalizeC[1]=0.0;
renormalizeC[2]=1.0;


transformedTangent.x=tangent.x*renormalizeA[0]+tangent.y*renormalizeA[1]+tangent.z*renormalizeA[2];
transformedTangent.y=tangent.x*renormalizeB[0]+tangent.y*renormalizeB[1]+tangent.z*renormalizeB[2];
transformedTangent.z=tangent.x*renormalizeC[0]+tangent.y*renormalizeC[1]+tangent.z*renormalizeC[2];

transformedBinormal.x=binormal.x*renormalizeA[0]+binormal.y*renormalizeA[1]+binormal.z*renormalizeA[2];
transformedBinormal.y=binormal.x*renormalizeB[0]+binormal.y*renormalizeB[1]+binormal.z*renormalizeB[2];
transformedBinormal.z=binormal.x*renormalizeC[0]+binormal.y*renormalizeC[1]+binormal.z*renormalizeC[2];


vec3 transformedNormal=normalize(cross(transformedTangent,transformedBinormal));

normal=sphericalToCartesian(transformedNormal);


normal = gl_NormalMatrix * normal;//gl_Normal;


diffuseColor = vec3(gl_FrontMaterial.diffuse);
specularColor = vec3(gl_FrontMaterial.specular);
emissiveColor = vec3(gl_FrontMaterial.emission);
ambientColor = vec3(gl_FrontMaterial.ambient);
shininess = gl_FrontMaterial.shininess;

}






No comments: