(none)

michael zyda zyda at NPS-CS.ARPA
Thu Sep 1 12:17:05 AEST 1988


31 August 1988

Split apart the following programs into separate files and you will have
a sample lighting program... My suggestion for learning about lighting for
the first time is to read chapter 14 of Hearn/Baker's Computer Graphics
text... 


     Michael Zyda
     Associate Professor of Computer Science
     Naval Postgraduate School
     Code 52, Dept. of Computer Science
     Monterey, CA 93943-5100
     zyda at nps-cs.arpa
     (408) 646-2305 (work)

***** file Makefile *****
CFLAGS = -O

ALL = mylight

all: $(ALL)

clean:
	rm -f *.o

delete:
	rm -f *.o $(ALL)

mylight: mylight.o rotate.h lightdefs.h lightdefs.o fpsm.o
	cc -o mylight mylight.o lightdefs.o fpsm.o -Zg $(CFLAGS)

mylight.o: lightdefs.h

lightdefs.o: lightdefs.h

***** file fpsm.c *****
/* fpsm.c

   startthemeter -- initialize the cpu times (done on first time through).
   framespersecondmeter -- return number of frames per second
   displayframespersecond -- display a meter of how many frames
                             per second we are achieving.

*/

#include "gl.h"
#include <sys/types.h>
#include <sys/times.h>

struct tms mytimes,oldtimes;


startthemeter()
{
   /* record the current clock values */
   times(&oldtimes);

}

float framespersecondmeter()
{
   long utime,stime,cutime,cstime;   /* temp time values */
   float xutime,xstime,xcutime,xcstime;   /* temp time values */
   float thistotal,childtotal;

   float retframes;   /* number of frames per second we are running */

   times(&mytimes);

   /* we add user time to system time for both this and all
      child processes...
   */
   utime = mytimes.tms_utime - oldtimes.tms_utime;
   xutime=utime/100.0;
   stime = mytimes.tms_stime - oldtimes.tms_stime;
   xstime=stime/100.0;
   thistotal=xutime+xstime;
   cutime = mytimes.tms_cutime - oldtimes.tms_cutime;
   xcutime=cutime/100.0;
   cstime = mytimes.tms_cstime - oldtimes.tms_cstime;
   xcstime=cstime/100.0;
   childtotal=xcutime+xcstime;

   /* compute the number of frames per second */
   if((thistotal + childtotal) > 0.0)
   {
      retframes = (1.0/(thistotal+childtotal));
   }
   else
   {
      retframes = 0.0;
   }

   /* read the clock again */
   times(&oldtimes);

   return(retframes);

}

displayframespersecond(x,y,z,radius,maxframes)

float x,y,z;   /* where to put the display */

float radius;  /* radius of the arc to use */

float maxframes;  /* max number of frames per second */

{

   float framespersecondmeter();


   /* draw the meter */
   drawthemeter(x,y,z,radius,framespersecondmeter(),maxframes);


}

drawthemeter(x,y,z,radius,value,maxvalue)

float x,y,z;   /* where to put the display */

float radius;  /* radius of the arc to use */

float value;   /* value to display     */

float maxvalue;/* max value on the display */

{

   short coverage;   /* coverage angle */

   short i;   /* loop temp */

   static char tmp[100];   /* chars for the maxframes text display */

   static float oldmaxvalue = 0.0;   /* hold last maxframe value */


   /* save the matrix */
   pushmatrix();

   /* translate by the z coord */
   translate(0.0,0.0,z);

   /* draw the 180 degree arc for the background */
   if(getdisplaymode() == 2)
   {
      color(WHITE);
   }
   else
   {
      RGBcolor(255,255,255);
   }

   arcf(x,y,radius*1.1,3578,1822);

   /* put some tick marks on the meter */
   if(getdisplaymode() == 2)
   {
      color(BLACK);
   }
   else
   {
      RGBcolor(0,0,0);
   }

   for(i=0; i <= 1800; i=i+180)
   {
      arcf(x,y,radius*1.1,i,i+20);
   }

   /* draw the 180 degree arc for the background */
   if(getdisplaymode() == 2)
   {
      color(WHITE);
   }
   else
   {
      RGBcolor(255,255,255);
   }

   arcf(x,y,radius,3578,1822);

   /* draw a black border */
   if(getdisplaymode() == 2)
   {
      color(BLACK);
   }
   else
   {
      RGBcolor(0,0,0);
   }

   linewidth(5);
   arc(x,y,radius*1.1,3578,1822);

   /* draw a line across the bottom to close the meter */
   move2(x-(radius*1.1),y);
   draw2(x+(radius*1.1),y);
   
   /* restore the linewidth */
   linewidth(1);

   /* compute how much of the arc should be covered */
   if(value/maxvalue <= 1.0)
   {
      coverage = (1.0 - (value/maxvalue))*1800;
   }
   else
   {
      coverage = 0.0;
   }

   /* draw the coverage arc */
   if(getdisplaymode() == 2)
   {
      color(BLACK);
   }
   else
   {
      RGBcolor(0,0,0);
   }

   arcf(x,y,radius,coverage,1800);

   /* put up the display of the max meter reading */
   cmov2(x+(radius*1.1),y);

   /* do we have to compute the string again ? */
   if(oldmaxvalue != maxvalue)
   {
      sprintf(tmp," %d",(long)maxvalue);
      oldmaxvalue = maxvalue;
   }

   charstr(tmp);

   /* restore the matrix */
   popmatrix();

}
***** file lightdefs.c *****
/* this is file lightdefs.c

   These routines define the materials/lights/lighting models needed...

*/

#include "gl.h"

#include "lightdefs.h"


/* set up all the materials */

initializematerials()
{

   /* make the definition calls for the materials */

   /* make the defs for the checkerboard */
   lmdef(DEFMATERIAL,REDBOARD,19,redboard);
   lmdef(DEFMATERIAL,WHITEBOARD,19,whiteboard);

   /* make the defs for the cube sides */
   lmdef(DEFMATERIAL,WHITECUBEMATERIAL,19,whitecube);
   lmdef(DEFMATERIAL,BLUECUBEMATERIAL,19,bluecube);
   lmdef(DEFMATERIAL,GREENCUBEMATERIAL,19,greencube);
   lmdef(DEFMATERIAL,REDCUBEMATERIAL,19,redcube);
   lmdef(DEFMATERIAL,YELLOWCUBEMATERIAL,19,yellowcube);
   lmdef(DEFMATERIAL,MAGENTACUBEMATERIAL,19,magentacube);

   /* make the material for where the light is */
   lmdef(DEFMATERIAL,LIGHTMATERIAL,19,lightmaterial);

}

/* this routine sets up the light for the scene */

initializelights()
{

   /* define the light */
   lmdef(DEFLIGHT,MYLIGHT,14,light);

   /* turn this light on */
   lmbind(LIGHT0,MYLIGHT);

}

/* define the lighting model */

initializelmodel()
{

   /* define the lighting model */
   lmdef(DEFLMODEL,MYMODEL,10,lmodel);

   /* turn on the model */
   lmbind(LMODEL,MYMODEL);

}

/* the following routine calls routine normal() with 3 args */

xyznormal(x,y,z)

float x,y,z;   /* input normal vector */

{

   float tmp[3];   /* array to hold the normal */

   tmp[0] = x;
   tmp[1] = y;
   tmp[2] = z;

   normal(tmp);

}
***** file lightdefs.h *****
/* this is file lightdefs.h

   It is the file containing the material/light/lighting model defs

*/


#define REDBOARD 1

static float redboard[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.2, 0.0, 0.0,
                            DIFFUSE,  1.0, 0.0, 0.0,
                            SPECULAR, 1.0, 0.0, 0.0,
                            SHININESS, 0.0,
                            LMNULL
                          };

#define WHITEBOARD 2

static float whiteboard[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.2, 0.2, 0.2,
                            DIFFUSE,  1.0, 1.0, 1.0,
                            SPECULAR, 1.0, 1.0, 1.0,
                            SHININESS, 0.0,
                            LMNULL
                          };


#define MYSHININESS 10.0  /* my value for E(mss)   */

#define WHITECUBEMATERIAL 3

static float whitecube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.2, 0.2, 0.2,
                            DIFFUSE,  1.0, 1.0, 1.0,
                            SPECULAR, 1.0, 1.0, 1.0,
                            SHININESS, MYSHININESS,
                            LMNULL
                          };

#define BLUECUBEMATERIAL 4

static float bluecube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.0, 0.2, 0.2,
                            DIFFUSE,  0.0, 0.5, 0.75,
                            SPECULAR, 0.0, 0.5, 0.75,
                            SHININESS, MYSHININESS,
                            LMNULL
                          };

#define GREENCUBEMATERIAL 5

static float greencube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.0, 0.2, 0.0,
                            DIFFUSE,  0.0, 1.0, 0.0,
                            SPECULAR, 0.0, 1.0, 0.0,
                            SHININESS, MYSHININESS,
                            LMNULL
                          };

#define REDCUBEMATERIAL 6   /* make this the copper defs */

static float redcube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.1, 0.06, 0.04,
                            DIFFUSE,  0.0, 0.0, 0.0,
                            SPECULAR, 0.7, 0.42, 0.28,
                            SHININESS, 32.0,
                            LMNULL
                          };

#define YELLOWCUBEMATERIAL 7

static float yellowcube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.2, 0.2, 0.0,
                            DIFFUSE,  1.0, 1.0, 0.0,
                            SPECULAR, 1.0, 1.0, 0.0,
                            SHININESS, MYSHININESS,
                            LMNULL
                          };

#define MAGENTACUBEMATERIAL 8

static float magentacube[] = {
                            EMISSION, 0.0, 0.0, 0.0,
                            AMBIENT,  0.2, 0.0, 0.2,
                            DIFFUSE,  1.0, 0.0, 1.0,
                            SPECULAR, 1.0, 0.0, 1.0,
                            SHININESS, MYSHININESS,
                            LMNULL
                          };

#define LIGHTMATERIAL 9

static float lightmaterial[] = {
                            EMISSION, 1.0, 0.0, 0.0,
                            AMBIENT,  0.0, 0.0, 0.0,
                            DIFFUSE,  0.0, 0.0, 0.0,
                            SPECULAR, 0.0, 0.0, 0.0,
                            SHININESS, 0.0,
                            LMNULL
                          };


/* set up the light defs for the program */


#define MYLIGHT 10

#define LIGHTX 200.0   /* loc of the light */
#define LIGHTY 100.0
#define LIGHTZ -350.0

static float light[] = {
                          AMBIENT, 0.2, 0.2, 0.2,
                          LCOLOR,  1.0, 1.0, 1.0,
                          POSITION, LIGHTX, LIGHTY, LIGHTZ, 1.0,
                          LMNULL
                       };

/* define the lighting model */

#define MYMODEL 11

static float lmodel[] = {
                          AMBIENT, 0.0, 0.0, 0.0,
                          LOCALVIEWER, 1.0,
                          ATTENUATION, 0.0, 0.0001,
                          LMNULL
                        };


***** file mylight.c *****
/* this is an IRIS-4D Program */

/* this is file mylight.c

   It is program rotate2.c with z-buffering and rgbmode instead of backface
   polygon removal and lighting routines...

*/


#include "gl.h"
#include "device.h"

#include "rotate.h"

#include "lightdefs.h"   /* get the material/light/lighting model defs */

#define NEARDEPTH 0x0000
#define FARDEPTH  0x3fff

#define NEARCLIPPING 10.0   /* near clipping plane is at -10.0 */
#define FARCLIPPING  1023.0 /* far clipping plane is at -1023.0 */

#define CUBEX      0.0   /* location of the cube */
#define CUBEY      0.0   
#define CUBEZ   -511.0
#define CUBESIZE 100.0

#define VIEWX      0.0   /* location of the viewpoint */
#define VIEWY      0.0
#define VIEWZ    200.0

#define REFX     CUBEX   /* reference point we are looking towards */
#define REFY     CUBEY
#define REFZ     CUBEZ

#define FLOORX   CUBEX   /* x center point of the floor */
#define FLOORY  -200.0   /* the plane of the floor    */
#define FLOORZ   CUBEZ   /* z center point of the floor */
#define FLOORWIDTH 500.0


main()
{

   /* popup menu's name */
   int mainmenu;

   int hititem; /* variable holding hit name */

   short value; /* value returned from the event queue */


   /* initialize the IRIS system */
   initialize();

   /* initialize the material definitions */
   initializematerials();

   /* initialize the light definitions */
   initializelights();

   /* initialize the lighting model */
   initializelmodel();

   /* make the popup menus */
   mainmenu = makethemenus();

   /* set all the accumulative matrices to unit matrices */
   resetallaccumulativematrices();

   /* get the initial clock value */
   startthemeter();


   while(TRUE)
   {

      /* do we have something on the event queue ?*/
      if(qtest())
      {

         switch(qread(&value))
         {

            case MENUBUTTON:
            
               if(value == 1)
               {
                  /* we must be in MSINGLE mode to do popup menus!!! */
                  mmode(MSINGLE);

                  /* which popup selection do we want? */
                  hititem = dopup(mainmenu);

                  /* put us back into MVIEWING mode */
                  mmode(MVIEWING);
                  
                  /* do something with the popup hit */
                  processmenuhit(hititem);

               }

               break;

            case REDRAW:

               reshapeviewport();

               break;

            default:

               break;

         }   /* end switch on event queue item */

      }   /* endif qtest()  */


      /* draw the background color */
      RGBcolor(150,150,150); /* grey */
      clear();

      /* turn on Z-buffering */
      zbuffer(TRUE);

      /* clear the z-buffer */
      zclear();

      /* put up the non-moving viewing matrix for the floor */
      buildnonmovingviewingmatrix(VIEWX,VIEWY,VIEWZ,REFX,REFY,REFZ);

      /* draw the floor */
      /* x and z are the center of the floor.
         y is the plane for the floor.
         the last value is the width of the floor
      */
      drawthefloor(FLOORX,FLOORY,FLOORZ,FLOORWIDTH);

      /* draw a symbolic spot where the light is */
      drawthelight(LIGHTX,LIGHTY,LIGHTZ,10.0);


      /* display the number of frames per second
         (0.0,40.0,-20.0) is the loc of the meter in world coords.
         15.0 is the radius to use for the meter.
         20.0 is maximum frames per second.
         Note: this measures actual CPU time used by your
               process and other users on the system will
               make the output meter view strange.
      */
      zbuffer(FALSE);
      lmbind(LMODEL,0);   /* turn off lighting model */

      displayframespersecond(0.0,40.0,-20.0,15.0,20.0);

      zbuffer(TRUE);
      lmbind(LMODEL,MYMODEL);   /* turn my lighting back on */

      /* put up the moving viewing matrix.
         The input arguments are the center point for the object
         we want to move and the reference point in the scene.
         We need this guy so we can always rotate around
         the screen frame of reference.
      */
      buildmovingviewingmatrix(VIEWX,VIEWY,VIEWZ,REFX,REFY,REFZ);

      /* draw the cube */
      drawcube(CUBEX,CUBEY,CUBEZ,CUBESIZE);

      /* turn z-buffering off */
      zbuffer(FALSE);


      /* change the buffers ... */
      swapbuffers();

   }

}

initialize()
{

   /* set up the preferred aspect ratio */
   keepaspect(XMAXSCREEN+1,YMAXSCREEN+1);

   /* open a window for the program */
   winopen("mylight");

   /* make a title */
   wintitle("mylight");

   /* put the IRIS into double buffer mode */
   doublebuffer();

   /* put the iris into rgb mode */
   RGBmode();

   /* configure the IRIS (means use the above command settings) */
   gconfig();

   /* set the depth for z-buffering */
   setdepth(NEARDEPTH,FARDEPTH);

   /* queue the redraw device */
   qdevice(REDRAW);

   /* queue the menubutton */
   qdevice(MENUBUTTON);

   /* turn the cursor on */
   curson();

   /* select gouraud shading */
   /* only works on the 4D*/
   shademodel(GOURAUD);

   /* turn on the new projection matrix mode */
   mmode(MVIEWING);

}

/* this routine performs all the menu construction calls */

int makethemenus()
{

   int topmenu;   /* top level menu's name */

   int rotmenu;   /* rotate menu */

   int transmenu; /* trans menu  */

   int scalemenu; /* scale menu  */


   /* define the low level menus first */
   rotmenu = newpup();
   addtopup(rotmenu,"Rotate Menu %t ");
   addtopup(rotmenu,"+X %x2 | 0X %x3 | -X %x4 ");
   addtopup(rotmenu,"+Y %x5 | 0Y %x6 | -Y %x7 ");
   addtopup(rotmenu,"+Z %x8 | 0Z %x9 | -Z %x10 ");

   transmenu = newpup();
   addtopup(transmenu,"Translate Menu %t ");
   addtopup(transmenu,"+X %x12 | 0X %x13 | -X %x14 ");
   addtopup(transmenu,"+Y %x15 | 0Y %x16 | -Y %x17 ");
   addtopup(transmenu,"+Z %x18 | 0Z %x19 | -Z %x20 ");

   scalemenu = newpup();
   addtopup(scalemenu,"Scale Menu %t ");
   addtopup(scalemenu,"+X %x22 | 0X %x23 | -X %x24 ");
   addtopup(scalemenu,"+Y %x25 | 0Y %x26 | -Y %x27 ");
   addtopup(scalemenu,"+Z %x28 | 0Z %x29 | -Z %x30 ");

   /* build the top level menu */
   topmenu = defpup("Roll Off Side %t | Rotate %x1 %m | Translate %x11 %m | Scale %x21 %m | Reset %x31 | Exit %x32 ",
                    rotmenu,transmenu,scalemenu);

   /* return the name of this menu */
   return(topmenu);

}

/* this routine builds the moving viewing matrix each time through
   the display loop...

   P' = P . T(to origin) . S(acc) . R(x acc) . R(y acc) . R(z acc)
            . T(to acc. loc) . T(back to specified center) . perspective()

*/

buildmovingviewingmatrix(vx,vy,vz,refx,refy,refz)

float vx,vy,vz;   /* view point */

float refx,refy,refz;   /* ref point we are looking towards */

{


   /* Build the accumulative rotation matrices */

   loadmatrix(rxacc); /* get the accumulative rotation */
   rotate(rx,'x');    /* concatenate on the new rotation (if any) */
   getmatrix(rxacc);  /* we now have a new accumulative... */

   loadmatrix(ryacc); /* get the accumulative rotation */
   rotate(ry,'y');    /* concatenate on the new rotation (if any) */
   getmatrix(ryacc);  /* we now have a new accumulative... */

   loadmatrix(rzacc); /* get the accumulative rotation */
   rotate(rz,'z');    /* concatenate on the new rotation (if any) */
   getmatrix(rzacc);  /* we now have a new accumulative... */

   /* Build the accumulative translation matrix */

   loadmatrix(transacc); /* get the accumulative translation   */
   translate(tx,ty,tz);  /* concatenate on the new translation */
   getmatrix(transacc);  /* we now have a new accumulative translation */


   /* Build the accumulative scale matrix */

   loadmatrix(scaleacc); /* get the accumulative scale */
   scale(sx,sy,sz);      /* concatenate on the new scale */
   getmatrix(scaleacc);  /* we now have the new accumulative scale */


   /* in mmode(MVIEWING), we must add a load of a unit matrix */
   loadunit();

   /* put up the projection and viewing matrix */
   projectionandviewingmatrix(vx,vy,vz,refx,refy,refz);


   /* translate center of box back to original location */
   translate(refx,refy,refz);

   /* translate the object to the location specified
      by the accumulative translation...
   */
   multmatrix(transacc);

   multmatrix(rzacc);  /* z accumulative matrix */

   multmatrix(ryacc);  /* y accumulative matrix */

   multmatrix(rxacc);  /* x accumulative matrix */

   multmatrix(scaleacc); /* accumulative scale matrix */


   /* translate center of box to the origin */
   translate(-refx,-refy,-refz);

}

/* for objects that are in the same coordinate system but aren't moving
   with the continuous rotations/translations/scalings, we use this
   routine ...

*/


buildnonmovingviewingmatrix(vx,vy,vz,refx,refy,refz)

float vx,vy,vz;   /* view point */

float refx,refy,refz; /* reference point we are looking towards    */

{

   /* we must call loadunit before we get the projection
      and viewing stuff... */
   loadunit();

   /* just call the perspective + viewing matrices */
   projectionandviewingmatrix(vx,vy,vz,refx,refy,refz);

}

/* put up the projection and viewing matrix */

projectionandviewingmatrix(vx,vy,vz,refx,refy,refz)

float vx,vy,vz;   /* view point */

float refx,refy,refz;   /* reference point */

{

   /* perspective projection 3D for the world coord sys */
   /* the near and far values are distances from the viewer
      to the near and far clipping planes.
      We are at (vx,vy,vz) and looking towards
      the center point of the object..
      (towards (refx,refy,refz)).
   */
   perspective(450,1.25,NEARCLIPPING,FARCLIPPING);

   lookat(vx,vy,vz,refx,refy,refz,0);

}

/* process the popup menu selection */

processmenuhit(hititem)

int hititem;   /* item hit on the popup menus */

{

   switch(hititem)
   {
         case ROTATE: 
                        break;

         case PLUSXROT:
                        rx = XROTAMOUNT;
                        break;
         case ZEROXROT:
                        rx = 0;
                        break;
         case MINUSXROT:
                        rx = - XROTAMOUNT;
                        break;

         case PLUSYROT:
                        ry = YROTAMOUNT;
                        break;
         case ZEROYROT:
                        ry = 0;
                        break;
         case MINUSYROT:
                        ry = - YROTAMOUNT;
                        break;

         case PLUSZROT:
                        rz = ZROTAMOUNT;
                        break;
         case ZEROZROT:
                        rz = 0;
                        break;
         case MINUSZROT:
                        rz = - ZROTAMOUNT;
                        break;


         case TRANSLATE:
                        break;

         case PLUSXTRANS:
                        tx = XTRANSAMOUNT;
                        break;
         case ZEROXTRANS:
                        tx=0;
                        break;
         case MINUSXTRANS:
                        tx= -XTRANSAMOUNT;
                        break;

         case PLUSYTRANS:
                        ty=YTRANSAMOUNT;
                        break;
         case ZEROYTRANS:
                        ty=0.0;
                        break;
         case MINUSYTRANS:
                        ty= -YTRANSAMOUNT;
                        break;

         case PLUSZTRANS:
                        tz=ZTRANSAMOUNT;
                        break;
         case ZEROZTRANS:
                        tz=0.0;
                        break;
         case MINUSZTRANS:
                        tz= -ZTRANSAMOUNT;
                        break;

         case SCALE:
                       break;

         case PLUSXSCALE:
                       sx = POSSCALEAMOUNT;
                       break;
         case ZEROXSCALE:
                       sx = 1.0;
                       break;
         case MINUSXSCALE:
                       sx = NEGSCALEAMOUNT;
                       break;

         case PLUSYSCALE:
                       sy = POSSCALEAMOUNT;
                       break;
         case ZEROYSCALE:
                       sy = 1.0;
                       break;
         case MINUSYSCALE:
                       sy = NEGSCALEAMOUNT;
                       break;

         case PLUSZSCALE:
                       sz = POSSCALEAMOUNT;
                       break;
         case ZEROZSCALE:
                       sz = 1.0;
                       break;
         case MINUSZSCALE:
                       sz = NEGSCALEAMOUNT;
                       break;

         case RESET:
                      /* zap all values...*/
                      resetallaccumulativematrices();

                      break;

         case EXIT:
                      exit(0);
                      break;

         default:
                      break;

      } /* end switch */

}

/* the following routine sets all accumulative matrices to unit matrices */

resetallaccumulativematrices()
{

   unit(transacc);   /* set the trans accumulative */

   unit(rxacc);      /* set the x rotation accumulative */
   unit(ryacc);      /* set the y rotation accumulative */
   unit(rzacc);      /* set the z rotation accumulative */

   unit(scaleacc);   /* set the scale accumulative */

   /* reset all the ON values to off... */
   rx = 0;
   ry = 0;
   rz = 0;

   tx = 0.0; 
   ty = 0.0;
   tz = 0.0;

   sx = 1.0;
   sy = 1.0;
   sz = 1.0;

}

/* the following routine loads a unit matrix into the input array */

unit(m)
Matrix m;
{
   static Matrix un = { 1.0, 0.0, 0.0, 0.0,
                        0.0, 1.0, 0.0, 0.0,
                        0.0, 0.0, 1.0, 0.0,
                        0.0, 0.0, 0.0, 1.0 };

   long i,j;


   /* copy the matrix elements...*/
   for(i=0; i < 4; i=i+1)
   {
      for(j=0; j < 4; j=j+1)
      {
         m[i][j]=un[i][j];
      }
   }

}

/* this routine loads a unit matrix onto the top of the stack */

loadunit()
{

   static Matrix un = { 1.0, 0.0, 0.0, 0.0,
                        0.0, 1.0, 0.0, 0.0,
                        0.0, 0.0, 1.0, 0.0,
                        0.0, 0.0, 0.0, 1.0 };

   /* load the matrix */
   loadmatrix(un);

}

/* this is function drawthefloor()

   It draws the checkerboard floor of the picture.

*/

drawthefloor(x,y,z,sidelength)

float x,y,z;  /* x and z are the center of the floor.
                 y is the plane where we should draw the floor */

float sidelength;   /* width and length of the floor */

{

   long i,j;   /* loop temps */

   float tilewidth;   /* width of the tiles on the floor */

   float tx,tz;   /* lowerleft coord of the floor */

   short flopcolor;   /* color flop for the checkerboard */


   /* compute the tilewidth */
   tilewidth = sidelength/8.0;

   /* compute the lowerleft coord */
   tx = x - (4.0*tilewidth);
   tz = z - (4.0*tilewidth);

   /* set the initial color for the color flop */
   flopcolor = RED;

   /* only one normal vector for the floor */
   xyznormal(0.0,1.0,0.0);


   /* draw the checkerboard */
   for(j=0; j < 8; j=j+1)
   {
   
      /* flop the color for the next time */
      if(flopcolor == RED)
      {
         flopcolor = WHITE;
      }
      else
      {
         flopcolor = RED;
      }

      for(i=0; i < 8; i=i+1)
      {

         /* set the color for this square */
         if(flopcolor == RED)
         {
            /* set the desired surface characteristic for the square */
            lmbind(MATERIAL,REDBOARD);
         }
         else
         {
            /* set the desired surface characteristic for the square */
            lmbind(MATERIAL,WHITEBOARD);
         }

         /* flop the color for the next time */
         if(flopcolor == RED)
         {
            flopcolor = WHITE;
         }
         else
         {
            flopcolor = RED;
         }

         /* draw the square for the board */
         pmv(tx+(i*tilewidth),y,tz+(j*tilewidth));
         pdr(tx+((i+1)*tilewidth),y,tz+(j*tilewidth));
         pdr(tx+((i+1)*tilewidth),y,tz+((j+1)*tilewidth));
         pdr(tx+(i*tilewidth),y,tz+((j+1)*tilewidth));
         pclos();

      }   /* endfor i */

   }   /* endfor j */

}

/* draw a cube with center (x,y,z), having the designated sidelength */

drawcube(x,y,z,sidelength)

float x,y,z;   /* center of the cube in 3-space */

float sidelength;  /* length of cube's side */

{
   float halfside;   /* length of half the side of the cube */

   float p[4][3];    /* array to hold coords for the cube faces */


   /* compute the halfside */
   halfside=sidelength/2.0;

   /* back face */
   p[0][0]=x-halfside;
   p[0][1]=y+halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y+halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y-halfside;
   p[2][2]=z-halfside;

   p[3][0]=x-halfside;
   p[3][1]=y-halfside;
   p[3][2]=z-halfside;

   /* make it the new material */
   lmbind(MATERIAL,WHITECUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(0.0,0.0,-1.0);

   polf(4,p);   /* draw a filled white face */

   /* draw the front face */
   p[0][0]=x+halfside;
   p[0][1]=y+halfside;
   p[0][2]=z+halfside;

   p[1][0]=x-halfside;
   p[1][1]=y+halfside;
   p[1][2]=z+halfside;

   p[2][0]=x-halfside;
   p[2][1]=y-halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* make it the new material */
   lmbind(MATERIAL,BLUECUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(0.0,0.0,1.0);

   polf(4,p);   /* draw a blue filled face */

   /* draw the top */
   p[0][0]=x-halfside;
   p[0][1]=y+halfside;
   p[0][2]=z-halfside;

   p[1][0]=x-halfside;
   p[1][1]=y+halfside;
   p[1][2]=z+halfside;

   p[2][0]=x+halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y+halfside;
   p[3][2]=z-halfside;

   /* make it the new material */
   lmbind(MATERIAL,GREENCUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(0.0,1.0,0.0);

   polf(4,p);   /* draw a filled green face */

   /* draw the bottom */
   p[0][0]=x-halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y-halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y-halfside;
   p[2][2]=z+halfside;

   p[3][0]=x-halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* make it the new material */
   lmbind(MATERIAL,REDCUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(0.0,-1.0,0.0);

   polf(4,p);   /* draw a filled red face */

   /* draw the left side */
   p[0][0]=x-halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x-halfside;
   p[1][1]=y-halfside;
   p[1][2]=z+halfside;

   p[2][0]=x-halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x-halfside;
   p[3][1]=y+halfside;
   p[3][2]=z-halfside;

   /* make it the new material */
   lmbind(MATERIAL,YELLOWCUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(-1.0,0.0,0.0);

   polf(4,p);   /* draw a filled yellow face */

   /* draw the right side */
   p[0][0]=x+halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y+halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* make it the new material */
   lmbind(MATERIAL,MAGENTACUBEMATERIAL);

   /* set the normal for the polygon */
   xyznormal(1.0,0.0,0.0);

   polf(4,p);   /* draw a magenta filled face */

   /* the cube is drawn */

}

/* draw a cube with center (x,y,z), having the designated sidelength */
/* this is the location of the light...                              */

drawthelight(x,y,z,sidelength)

float x,y,z;   /* center of the cube in 3-space */

float sidelength;  /* length of cube's side */

{
   float halfside;   /* length of half the side of the cube */

   float p[4][3];    /* array to hold coords for the cube faces */


   /* compute the halfside */
   halfside=sidelength/2.0;

   /* back face */
   p[0][0]=x-halfside;
   p[0][1]=y+halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y+halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y-halfside;
   p[2][2]=z-halfside;

   p[3][0]=x-halfside;
   p[3][1]=y-halfside;
   p[3][2]=z-halfside;

   /* make it the new material */
   lmbind(MATERIAL,LIGHTMATERIAL);

   /* set the normal for the polygon */
   xyznormal(0.0,0.0,-1.0);

   polf(4,p);   /* draw a filled white face */

   /* draw the front face */
   p[0][0]=x+halfside;
   p[0][1]=y+halfside;
   p[0][2]=z+halfside;

   p[1][0]=x-halfside;
   p[1][1]=y+halfside;
   p[1][2]=z+halfside;

   p[2][0]=x-halfside;
   p[2][1]=y-halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* set the normal for the polygon */
   xyznormal(0.0,0.0,1.0);

   polf(4,p);   /* draw a blue filled face */

   /* draw the top */
   p[0][0]=x-halfside;
   p[0][1]=y+halfside;
   p[0][2]=z-halfside;

   p[1][0]=x-halfside;
   p[1][1]=y+halfside;
   p[1][2]=z+halfside;

   p[2][0]=x+halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y+halfside;
   p[3][2]=z-halfside;

   /* set the normal for the polygon */
   xyznormal(0.0,1.0,0.0);

   polf(4,p);   /* draw a filled green face */

   /* draw the bottom */
   p[0][0]=x-halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y-halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y-halfside;
   p[2][2]=z+halfside;

   p[3][0]=x-halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* set the normal for the polygon */
   xyznormal(0.0,-1.0,0.0);

   polf(4,p);   /* draw a filled red face */

   /* draw the left side */
   p[0][0]=x-halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x-halfside;
   p[1][1]=y-halfside;
   p[1][2]=z+halfside;

   p[2][0]=x-halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x-halfside;
   p[3][1]=y+halfside;
   p[3][2]=z-halfside;

   /* set the normal for the polygon */
   xyznormal(-1.0,0.0,0.0);

   polf(4,p);   /* draw a filled yellow face */

   /* draw the right side */
   p[0][0]=x+halfside;
   p[0][1]=y-halfside;
   p[0][2]=z-halfside;

   p[1][0]=x+halfside;
   p[1][1]=y+halfside;
   p[1][2]=z-halfside;

   p[2][0]=x+halfside;
   p[2][1]=y+halfside;
   p[2][2]=z+halfside;

   p[3][0]=x+halfside;
   p[3][1]=y-halfside;
   p[3][2]=z+halfside;

   /* set the normal for the polygon */
   xyznormal(1.0,0.0,0.0);

   polf(4,p);   /* draw a magenta filled face */

   /* the cube is drawn */

}
***** file rotate.h *****
/* this is an IRIS-4D Program */

/* this is file rotate.h

   It is the include file for program rotate.c
   This file holds the defines and the global variables
   for programs:
   rotate.c
   rotate2.c

*/

/* defines for the menu definition routine */

#define ROTATE 1

#define PLUSXROT 2
#define ZEROXROT 3
#define MINUSXROT 4

#define PLUSYROT 5
#define ZEROYROT 6
#define MINUSYROT 7

#define PLUSZROT 8
#define ZEROZROT 9
#define MINUSZROT 10


#define TRANSLATE 11

#define PLUSXTRANS 12
#define ZEROXTRANS 13
#define MINUSXTRANS 14

#define PLUSYTRANS 15
#define ZEROYTRANS 16
#define MINUSYTRANS 17

#define PLUSZTRANS 18
#define ZEROZTRANS 19
#define MINUSZTRANS 20


#define SCALE 21

#define PLUSXSCALE 22
#define ZEROXSCALE 23
#define MINUSXSCALE 24

#define PLUSYSCALE 25
#define ZEROYSCALE 26
#define MINUSYSCALE 27

#define PLUSZSCALE 28
#define ZEROZSCALE 29
#define MINUSZSCALE 30


#define RESET 31


#define EXIT 32


/* the following defines are the amounts concatenated
   each frame if the matrix concatenation is selected
   as ON
*/

#define XROTAMOUNT 25  /* 2.5 degrees of rotation each picture */
#define YROTAMOUNT 25  /* 2.5 degrees of rotation each picture */
#define ZROTAMOUNT 25  /* 2.5 degrees of rotation each picture */

#define XTRANSAMOUNT 5.0; /* 5 units of translation in the x direction */
#define YTRANSAMOUNT 5.0; /* 5 units of translation in the y direction */
#define ZTRANSAMOUNT 5.0; /* 5 units of translation in the z direction */

#define NEGSCALEAMOUNT 0.99; /* 0.99 scale each frame if ON */
#define POSSCALEAMOUNT 1.01; /* 1.01 scale each frame if ON */


/* the following variables are set when the particular matrix
   concatenation is turned ON. Otherwise they are zero...
*/

static float tx; /* translation on in the x direction */
static float ty; /* translation on in the y direction */
static float tz; /* translation on in the z direction */

static short rx; /* rotation on in the x direction */
static short ry; /* rotation on in the y direction */
static short rz; /* rotation on in the z direction */

static float sx; /* scale on in the x direction */
static float sy; /* scale on in the y direction */
static float sz; /* scale on in the z direction */


/* some globally defined matrices for the viewing matrix computation */

static Matrix transacc; /* accumulative translation matrix */

static Matrix rxacc;    /* accumulative x rotation matrix */
static Matrix ryacc;    /* accumulative y rotation matrix */
static Matrix rzacc;    /* accumulative z rotation matrix */

static Matrix scaleacc; /* accumulative scale matrix */



More information about the Comp.sys.sgi mailing list