This is mesadraw.c in view mode; [Download] [Up]
#include "mesadraw.h"
#include <3d.h>
extern void perpnorm(GLdouble[3],GLdouble[3],GLdouble[3],GLdouble[3]);
extern unsigned long random();
extern void bcopy(void*,void*,unsigned long);
#define DIM 30
#define MAX_HEIGHT (300/DIM)
#define RADS(x) ((x)/57.29577951)
static GLdouble mesh[DIM][DIM][3];
static GLubyte cols[DIM][DIM][3];
/*
* Create a random matrix of heights and colours
*/
void make_matrix(void)
{
int i,j;
for(i=0;i<DIM;i++)
for(j=0;j<DIM;j++)
{
mesh[i][j][0]=((100.0*i)/(DIM-1.0))-50.0;
mesh[i][j][2]=((100.0*j)/(DIM-1.0))-50.0;
mesh[i][j][1]=(random()%MAX_HEIGHT);
cols[i][j][0]=(mesh[i][j][1]*255)/MAX_HEIGHT;
cols[i][j][1]=255-cols[i][j][0];
cols[i][j][2]=0;
}
}
/*
* Initialise the OpenGL stuff
*/
void my_init (float w, float h)
{
GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_position[] = { 5.0, 3.0, 9.0, 0.0 };
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glShadeModel(GL_SMOOTH);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glViewport(0,0,w,h);
glMatrixMode (GL_PROJECTION);
gluPerspective (60.0, w/h, 1.0, 400.0);
glEnable(GL_DEPTH_TEST);
}
/*
* Set the viewpoint
*/
void set_viewpoint(float zoomDist, float elevAngle, float spinAngle, int white)
{
float flat_radius, x, y, z, xl, zl;
flat_radius=zoomDist*cos(RADS(elevAngle));
x=0.0-(flat_radius*sin(RADS(spinAngle)));
xl=50.0*sin(RADS(spinAngle));
z=flat_radius*cos(RADS(spinAngle));
zl= -50.0*cos(RADS(spinAngle));
y=zoomDist*sin(RADS(elevAngle));
if(white)
glClearColor(1,1,1,1);
else
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
/*
* we make a somewhat spurious "up" vector because we know we are
* looking at the origin and that it's mapped into the plane of
* the screen anyway so the percise direction is irrelevent.
*/
gluLookAt (x, y, z,
0, 0, 0,
xl, 50, zl);
}
/*
* Get a normal to a corner of a quad.
*/
void get_quad_normal(int x, int z, int cx, int cz, GLdouble n[3])
{
GLdouble *c1, *c2, *c3, *c4;
c1 = &mesh[x][z][0];
c2 = &mesh[x+1][z][0];
c3 = &mesh[x+1][z+1][0];
c4 = &mesh[x][z+1][0];
if((cx==0) && (cz==0))
return perpnorm(c4,c1,c2,n);
if((cx==0) && (cz==0))
return perpnorm(c4,c1,c2,n);
if((cx==1) && (cz==0))
return perpnorm(c1,c2,c3,n);
if((cx==1) && (cz==1))
return perpnorm(c2,c3,c4,n);
if((cx==0) && (cz==1))
return perpnorm(c3,c4,c1,n);
}
/*
* Get a normal to a plane as the average of
* the normals at the four corners of the quad.
*/
void get_plane_normal(int x, int z, GLdouble n[3])
{
GLdouble total[3]={0,0,0};
get_quad_normal(x,z,0,0,n);
add3(total,n,total);
get_quad_normal(x,z,0,1,n);
add3(total,n,total);
get_quad_normal(x,z,1,0,n);
add3(total,n,total);
get_quad_normal(x,z,1,1,n);
add3(total,n,total);
normalize(total);
n[0]=total[0];
n[1]=total[1];
n[2]=total[2];
}
/*
* Get a normal to a point as the average
* of the surrounding quads.
*/
void get_vertex_normal(int x, int z, GLdouble n[3])
{
GLdouble total[3]={0,0,0};
if((x>0) && (z>0))
{
get_quad_normal(x-1,z-1,1,1,n);
add3(total,n,total);
}
if((x>0) && (z<(DIM-1)))
{
get_quad_normal(x-1,z,1,0,n);
add3(total,n,total);
}
if((x<(DIM-1)) && (z>0))
{
get_quad_normal(x,z-1,0,1,n);
add3(total,n,total);
}
if((x<(DIM-1)) && (z<(DIM-1)))
{
get_quad_normal(x,z,0,0,n);
add3(total,n,total);
}
normalize(total);
n[0]=total[0];
n[1]=total[1];
n[2]=total[2];
}
/*
* Draw the scene
*/
void draw_scene(int av)
{
int xstrip, zrow;
for(xstrip=0;xstrip<DIM-1;xstrip++)
{
glBegin(GL_QUADS);
for(zrow=0;zrow<DIM-1;zrow++)
{
GLdouble *c1, *c2, *c3, *c4;
GLdouble n1[3], n2[3], n3[3], n4[3];
int passes,toggle;
c1 = &mesh[xstrip][zrow][0];
c2 = &mesh[xstrip+1][zrow][0];
c3 = &mesh[xstrip+1][zrow+1][0];
c4 = &mesh[xstrip][zrow+1][0];
if(av)
{
get_vertex_normal(xstrip,zrow,n1);
get_vertex_normal(xstrip+1,zrow,n2);
get_vertex_normal(xstrip+1,zrow+1,n3);
get_vertex_normal(xstrip,zrow+1,n4);
}
else
{
get_plane_normal(xstrip,zrow,n1);
bcopy(n1,n2,3*sizeof(GLdouble));
bcopy(n1,n3,3*sizeof(GLdouble));
bcopy(n1,n4,3*sizeof(GLdouble));
}
/*
* we do this to draw the quads in the opposite direction for
* each strip as this reduces the effects of the triangluarisation
* of the quad by the rendering algorithm.
*/
for(passes=0;passes<4;passes++)
{
if((xstrip&1) == (zrow&1))
toggle=3-passes;
else
toggle=passes;
switch (toggle)
{
case 0:
glColor3ubv(&cols[xstrip][zrow][0]);
glNormal3dv(n1);
glVertex3dv(c1);
break;
case 1:
glColor3ubv(&cols[xstrip+1][zrow][0]);
glNormal3dv(n2);
glVertex3dv(c2);
break;
case 2:
glColor3ubv(&cols[xstrip+1][zrow+1][0]);
glNormal3dv(n3);
glVertex3dv(c3);
break;
case 3:
glColor3ubv(&cols[xstrip][zrow+1][0]);
glNormal3dv(n4);
glVertex3dv(c4);
break;
}
}
}
glEnd();
}
}
/*
* We use the display postscript operators to send
* an outline of the base area directly into the window
* by projecting points and drawing lines. We also draw
* a small arrow representing "north" to hep orientation.
*/
void outline_scene(void)
{
GLdouble model[16], proj[16];
GLint viewport[4];
GLdouble winx, winy, winz;
glGetDoublev(GL_MODELVIEW_MATRIX, model);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetIntegerv(GL_VIEWPORT, viewport);
/* Having got these we can draw the base */
PSnewpath();
gluProject(-50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
PSmoveto(winx,winy);
gluProject(50.0, 0, -50.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
gluProject(50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
gluProject(-50.0, 0, 50.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
PSclosepath();
PSstroke();
/* draw the "north" arrow */
PSnewpath();
gluProject(-10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
PSmoveto(winx,winy);
gluProject(10.0, 0, 0.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
gluProject(0.0, 0, 10.0, model, proj, viewport, &winx, &winy, &winz);
PSmoveto(winx,winy);
gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
gluProject(-5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
PSmoveto(winx,winy);
gluProject(0.0, 0, -15.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
gluProject(5.0, 0, -10.0, model, proj, viewport, &winx, &winy, &winz);
PSlineto(winx,winy);
PSstroke();
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.