#include "../elmerpost.h"
static colormap_t *CurrentColormap = NULL;
void vsetcolori( int ncolor )
{
float r,g,b;
if ( CurrentColormap )
{
r = CurrentColormap->Values[ncolor].r / 255.0;
g = CurrentColormap->Values[ncolor].g / 255.0;
b = CurrentColormap->Values[ncolor].b / 255.0;
glColor4f( r,g,b,1.0 );
}
}
void vsetcolor( double color )
{
float r,g,b;
int ncolor;
if ( CurrentColormap )
{
ncolor = (CurrentColormap->NumberOfEntries-1) * color + 0.5;
r = CurrentColormap->Values[ncolor].r / 255.0;
g = CurrentColormap->Values[ncolor].g / 255.0;
b = CurrentColormap->Values[ncolor].b / 255.0;
glColor4f( r,g,b,1.0 );
}
}
void gra_set_material( material_t *Material )
{
static material_t *CurrentMaterial = NULL;
if ( !Material ) return;
glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, Material->Shininess );
glMaterialfv( GL_FRONT_AND_BACK, GL_SPECULAR, Material->Specular );
#if 0
if ( Material->Specular[0] != 0.0 ||
Material->Specular[1] != 0.0 ||
Material->Specular[2] != 0.0
) glEnable( GL_NORMALIZE ); else glDisable( GL_NORMALIZE );
#endif
glColor4fv( Material->Diffuse );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
if ( Material->Diffuse[3] < 1 )
{
glDisable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
} else
{
glEnable( GL_DEPTH_TEST );
}
Material->Changed = FALSE;
CurrentMaterial = Material;
}
void gra_set_colormap( colormap_t *ColorMap )
{
static rgb_t v = { 255,255,255 };
int N;
static colormap_t ctr;
colormap_t *ct = ColorMap;
if ( !ct || !ct->Values || ct->NumberOfEntries <= 1 )
{
ct = &ctr;
ct->Changed = TRUE;
ct->Values = &v;
ct->NumberOfEntries = 1;
}
glEnable( GL_TEXTURE_1D );
if ( ct == CurrentColormap && !ct->Changed ) return;
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &N );
if ( ct->NumberOfEntries > N )
{
fprintf( stderr, "gra_set_colormap: Colormap size [%d] too "
"big for this OpenGL-implementation\n", ct->NumberOfEntries );
return;
}
glTexParameterf( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameterf( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );
glTexEnvf( GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE );
glTexImage1D( GL_TEXTURE_1D, 0, 3, ct->NumberOfEntries, 0,
GL_RGB, GL_UNSIGNED_BYTE, ct->Values );
glEnable( GL_TEXTURE_1D );
ct->Changed = FALSE;
CurrentColormap = ct;
}
colormap_t *gra_get_colormap()
{
return CurrentColormap;
}
static void gra_output_triangle( float coords[3][3],float normal[3][3],int ncolor )
{
int i,j;
double x0,y0,z0,x1,y1,z1,n0,n1,n2;
x0 = coords[1][0] - coords[0][0];
y0 = coords[1][1] - coords[0][1];
z0 = coords[1][2] - coords[0][2];
x1 = coords[2][0] - coords[0][0];
y1 = coords[2][1] - coords[0][1];
z1 = coords[2][2] - coords[0][2];
n0 = y0*z1 - y1*z0;
n1 = z0*x1 - z1*x0;
n2 = x0*y1 - x1*y0;
vsetcolori( ncolor );
if ( n0*normal[0][0] + n1*normal[0][1] + n2*normal[0][2] > 0 ) {
glNormal3fv( normal[0] );
glVertex3fv( coords[0] );
glNormal3fv( normal[1] );
glVertex3fv( coords[1] );
glNormal3fv( normal[2] );
glVertex3fv( coords[2] );
} else {
glNormal3fv( normal[2] );
glVertex3fv( coords[2] );
glNormal3fv( normal[1] );
glVertex3fv( coords[1] );
glNormal3fv( normal[0] );
glVertex3fv( coords[0] );
}
glNormal3f( 0.0,0.0,1.0 );
}
static void gra_internal_triangle( float coords[3][3],float normal[3][3],float color[3], int ncolor )
{
float ncoord[3][3], nnorma[3][3], ccolor[3];
double x[2], y[2], z[2], u[2], v[2], w[2], c[2];
double c0=color[0],c1=color[1],c2=color[2],t,K;
int i,n=0,k;
int S, S0, S1, S2;
if ( ncolor >= CurrentColormap->NumberOfEntries-1 )
{
gra_output_triangle( coords, normal, ncolor );
return;
}
K = (double)(ncolor+1) / (double)CurrentColormap->NumberOfEntries;
S0 = color[0] > K;
S1 = color[1] > K;
S2 = color[2] > K;
S = S0 + S1 + S2;
if ( S==0 )
{
gra_output_triangle( coords, normal, ncolor );
return;
}
if ( S==3 )
{
gra_internal_triangle( coords, normal, color, ncolor+1 );
return;
}
n = 0;
if (S0 ^ S1)
{
t = (K - c0) / (c1 - c0);
x[n] = t * ( coords[1][0] - coords[0][0] ) + coords[0][0];
y[n] = t * ( coords[1][1] - coords[0][1] ) + coords[0][1];
z[n] = t * ( coords[1][2] - coords[0][2] ) + coords[0][2];
u[n] = t * ( normal[1][0] - normal[0][0] ) + normal[0][0];
v[n] = t * ( normal[1][1] - normal[0][1] ) + normal[0][1];
w[n] = t * ( normal[1][2] - normal[0][2] ) + normal[0][2];
n++;
}
if (S0 ^ S2)
{
t = (K - c0) / (c2 - c0);
x[n] = t * ( coords[2][0] - coords[0][0] ) + coords[0][0];
y[n] = t * ( coords[2][1] - coords[0][1] ) + coords[0][1];
z[n] = t * ( coords[2][2] - coords[0][2] ) + coords[0][2];
u[n] = t * ( normal[2][0] - normal[0][0] ) + normal[0][0];
v[n] = t * ( normal[2][1] - normal[0][1] ) + normal[0][1];
w[n] = t * ( normal[2][2] - normal[0][2] ) + normal[0][2];
n++;
}
if (S1 ^ S2)
{
t = (K - c1) / (c2 - c1);
x[n] = t * ( coords[2][0] - coords[1][0] ) + coords[1][0];
y[n] = t * ( coords[2][1] - coords[1][1] ) + coords[1][1];
z[n] = t * ( coords[2][2] - coords[1][2] ) + coords[1][2];
u[n] = t * ( normal[2][0] - normal[1][0] ) + normal[1][0];
v[n] = t * ( normal[2][1] - normal[1][1] ) + normal[1][1];
w[n] = t * ( normal[2][2] - normal[1][2] ) + normal[1][2];
n++;
}
k = 3;
if ( (S0 ^ S1) && (S0 ^ S2) ) k = 0;
if ( (S0 ^ S1) && (S1 ^ S2) ) k = 1;
if ( (S0 ^ S2) && (S1 ^ S2) ) k = 2;
for( i=0; i<2; i++ )
{
ncoord[i][0] = x[i];
ncoord[i][1] = y[i];
ncoord[i][2] = z[i];
nnorma[i][0] = u[i];
nnorma[i][1] = v[i];
nnorma[i][2] = w[i];
ccolor[i] = K;
}
ncoord[2][0] = coords[k][0];
ncoord[2][1] = coords[k][1];
ncoord[2][2] = coords[k][2];
nnorma[2][0] = normal[k][0];
nnorma[2][1] = normal[k][1];
nnorma[2][2] = normal[k][2];
ccolor[2] = color[k];
if ( color[k] > K )
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
else
gra_output_triangle( ncoord, nnorma, ncolor );
switch( k )
{
case 2:
for( i=0; i<3; i++ )
{
ncoord[2][i] = coords[0][i];
nnorma[2][i] = normal[0][i];
}
ccolor[2] = color[0];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
for( i=0; i<3; i++ )
{
ncoord[0][i] = coords[1][i];
nnorma[0][i] = normal[1][i];
}
ccolor[0] = color[1];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
break;
case 1:
for( i=0; i<3; i++ )
{
ncoord[2][i] = coords[0][i];
nnorma[2][i] = normal[0][i];
}
ccolor[2] = color[0];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
for( i=0; i<3; i++ )
{
ncoord[0][i] = coords[2][i];
nnorma[0][i] = normal[2][i];
}
ccolor[0] = color[2];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
break;
case 0:
for( i=0; i<3; i++ )
{
ncoord[2][i] = coords[1][i];
nnorma[2][i] = normal[1][i];
}
ccolor[2] = color[1];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
for( i=0; i<3; i++ )
{
ncoord[0][i] = coords[2][i];
nnorma[0][i] = normal[2][i];
}
ccolor[0] = color[2];
if ( color[k] > K )
gra_output_triangle( ncoord, nnorma, ncolor );
else
gra_internal_triangle( ncoord, nnorma, ccolor, ncolor+1 );
break;
}
}
void gra_triangle( float coords[3][3],float normal[3][3],float color[3] )
{
int i;
if ( GlobalOptions.OutputPS ) {
gra_internal_triangle( coords, normal, color, 0 );
} else {
for( i=0; i<3; i++ )
{
glTexCoord1f( color[i] );
glNormal3fv( normal[i] );
glVertex3fv( coords[i] );
}
}
glNormal3f( 0.0, 0.0, 1.0 );
}
void gra_poly3( int n,float *x,float *y,float *z,float *u,float *v,float *w,float *c)
{
float coords[3][3], normal[3][3];
int i;
for( i=0; i<n; i++ )
{
normal[i][0] = u[i];
normal[i][1] = v[i];
normal[i][2] = w[i];
coords[i][0] = x[i];
coords[i][1] = y[i];
coords[i][2] = z[i];
}
gra_triangle( coords,normal,c );
glNormal3f( 0.0, 0.0, 0.0 );
}
void gra_flat_quad( float coords[4][3],double color )
{
int j;
glNormal3f( 0.0,0.0,1.0 );
if ( GlobalOptions.OutputPS )
vsetcolor( color );
else
glTexCoord1f( color );
glVertex3fv( coords[0] );
glVertex3fv( coords[1] );
glVertex3fv( coords[2] );
glVertex3fv( coords[3] );
}
void gra_line(float *x0,double c0,float *x1,double c1,line_style_t style,double width)
{
void gra_cylinder();
if ( style == line_style_line )
{
if ( GlobalOptions.OutputPS )
vsetcolor( c0 );
else
glTexCoord1f( c0 );
glVertex3fv( x0 );
if ( GlobalOptions.OutputPS )
vsetcolor( c1 );
else
glTexCoord1f( c1 );
glVertex3fv( x1 );
} else
{
if ( GlobalOptions.OutputPS ) vsetcolor( c1 );
gra_cylinder( x0[0],x0[1],x0[2],c0,x1[0],x1[1],x1[2],c1,width );
}
}
void gra_arrow(float From[3],float Vector[3],double color,line_style_t line_style,arrow_style_t arrow_style,double width)
{
double x = Vector[0], y = Vector[1], z = Vector[2];
double xo = From[0], yo = From[1], zo = From[2];
double xa = xo + 0.65*x;
double ya = yo + 0.65*y;
double za = zo + 0.65*z;
float r,g,b;
int ncolor;
void gra_cone(), gra_cylinder();
x += xo;
y += yo;
z += zo;
if ( GlobalOptions.OutputPS ) vsetcolor( color );
if ( line_style == line_style_cylinder )
{
if ( arrow_style == arrow_style_arrow )
{
gra_cylinder( xo,yo,zo,color,xa,ya,za,color,width );
gra_cone( xa,ya,za,color,2.0*width,x,y,z,color,0.0 );
} else {
gra_cylinder( xo,yo,zo,color,x,y,z,color,width );
}
} else
{
glDisable( GL_LIGHTING );
glTexCoord1f( color );
glBegin(GL_LINE_STRIP);
glVertex3f( xo,yo,zo );
glVertex3f( x,y,z );
glEnd();
if ( arrow_style == arrow_style_arrow )
{
double xp,yp,zp;
xp = 0.75 * ( x - xo ) + xo;
yp = 0.75 * ( y - yo ) + yo;
zp = 0.75 * ( z - zo ) + zo;
xa = xp + ( y - yp );
ya = yp - ( x - xp );
za = zp;
glBegin(GL_LINE_STRIP);
glVertex3f(x,y,z);
glVertex3f(xa,ya,za);
glVertex3f(xp,yp,zp);
xa = xp - ( y - yp );
ya = yp + ( x - xp );
za = zp;
glVertex3f(xa,ya,za);
glVertex3f(x,y,z);
glEnd();
glBegin(GL_LINE_STRIP);
xa = xp + ( z - zp );
ya = yp;
za = zp - ( x - xp );
glVertex3f(x,y,z);
glVertex3f(xa,ya,za);
glVertex3f(xp,yp,zp);
xa = xp - ( y - yp );
ya = yp;
za = zp + ( x - xp );
glVertex3f(xa,ya,za);
glVertex3f(x,y,z);
glEnd();
}
glEnable( GL_LIGHTING );
}
}