From: airey@woof.asd.sgi.com (John Airey)
Newsgroups: comp.sys.sgi.graphics
Subject: Source for stereo demo...
Date: 27 Jan 1993 22:25:09 GMT
Organization: Silicon Graphics, Inc.  Mountain View, CA
NNTP-Posting-Host: woof.asd.sgi.com

Here is some source for a demo that uses stereo in a window.
For RealityEngine.

No promises or guarantees okay? It works for me.


#include <stdio.h>
#include <math.h>
#include <gl/image.h>
#include <gl/gl.h>
#include <gl/device.h>

#define X 0
#define Y 1
#define Z 2

static int Colors[] = 
{ 0xff7f1f9f,
  0xff5f0f9f,
  0xff9f0f3f,
  0xff0f9fff,
  0xffff1fff,
  0xff3f5f4f,
  0xff9f3f0f,
  0xff1f2f1f,
};

#define CFACES 6
#define VERTS_PER_CFACE 4
static float    cdata[8][3] =
{{-1., -1., -1.,},
 { 1., -1., -1.,},
 { 1.,  1., -1.,},
 {-1.,  1., -1.,},

 {-1., -1., 1.,},
 { 1., -1., 1.,},
 { 1.,  1., 1.,},
 {-1.,  1., 1.,},};

static int cndex[CFACES][VERTS_PER_CFACE] = 
{{3, 2, 1, 0},
 {4, 5, 6, 7},
 {0, 1, 5, 4},
 {1, 2, 6, 5},
 {2, 3, 7, 6},
 {3, 0, 4, 7},};

static float tex[4][2] = 
{{ 0., 0., },
 { 1., 0., },
 { 1., 1., },
 { 0., 1., },};

static int NumFaces = 6;
static int NumVertsPerFace = 3;

static int LeftBuffer = 1;
static float IOD  = 2.3;

maketexture(unsigned long t[], char *name, int x, int y)
{
   int j,i,n=0;
   int r,g,b,a;
   IMAGE *iimage;
   unsigned short *st = (unsigned short *) t;

   short rbuf[1024],gbuf[1024],bbuf[1024],abuf[1024];

   if ( (iimage = iopen(name,"r")) == NULL){
      fprintf(stderr,"\nCANT OPEN %s\n\n",name);
      exit(1);
   }

   for (j= 0; j< x; j++){
      getrow(iimage,rbuf,j,0);

      for (i= 0; i < y; i++){
	 st[n++]= (rbuf[i]) | (rbuf[i]<<8);
      }
   }
   iclose(iimage);
}

#define TEXSIZE 64
unsigned long tt1[TEXSIZE*TEXSIZE];
unsigned long tt2[TEXSIZE*TEXSIZE];
unsigned long tt3[TEXSIZE*TEXSIZE];
unsigned long tt4[TEXSIZE*TEXSIZE];
unsigned long tt5[TEXSIZE*TEXSIZE];
unsigned long tt6[TEXSIZE*TEXSIZE];

float Ztranslation = 0.;

#define CONVERGENCETRACK 0 
#define PARALLELVIEWS    1
#define SCREENCONVERGE   2
int StereoModel = CONVERGENCETRACK;

float texps[] = { TX_MAGFILTER, TX_SHARPEN,
		  TX_MINFILTER, TX_MIPMAP_TRILINEAR,
		  TX_INTERNAL_FORMAT, TX_IA_8, TX_NULL };

float tevps[] = { TV_MODULATE, TV_NULL };

float ConvergenceFudge = 0.0;

extern void draw_frame(float , float , float );
main()
{
   short           val, mval[2], lastval[2];
   long            org[2], size[2];
   Device          dev, mdev[2];
   Boolean         run;
   int             leftmouse_down = 0;
   int             middlemouse_down = 0;
   float rx,ry;
   float from[3];
   float at[3];
   char buf[80];

   lastval[X] = -1;

   maketexture(tt1,"t1.rgba",TEXSIZE,TEXSIZE);
   maketexture(tt2,"t2.rgba",TEXSIZE,TEXSIZE);
   maketexture(tt3,"t3.rgba",TEXSIZE,TEXSIZE);
   maketexture(tt4,"t4.rgba",TEXSIZE,TEXSIZE);
   maketexture(tt5,"t5.rgba",TEXSIZE,TEXSIZE);
   maketexture(tt6,"t6.rgba",TEXSIZE,TEXSIZE);

   foreground();
   noborder();
   prefposition(0,959,0,679);
   winopen("StereoSpin");
   RGBmode();
   doublebuffer();
   subpixel(1);
   zbuffer(1);
   stereobuffer();
   gconfig();

   if (!getgconfig(GC_STEREO)){
      fprintf(stderr,"stereo not available\n");
      exit(1);
   }

   tevdef(1,0,tevps);
   tevbind(0,1);

   texdef2d(1,2,TEXSIZE,TEXSIZE,tt1,0,texps);
   texdef2d(2,2,TEXSIZE,TEXSIZE,tt2,0,texps);
   texdef2d(3,2,TEXSIZE,TEXSIZE,tt3,0,texps);
   texdef2d(4,2,TEXSIZE,TEXSIZE,tt4,0,texps);
   texdef2d(5,2,TEXSIZE,TEXSIZE,tt5,0,texps);
   texdef2d(6,2,TEXSIZE,TEXSIZE,tt6,0,texps);

   mmode(MVIEWING);

   getorigin(&org[X], &org[Y]);
   getsize(&size[X], &size[Y]);
   mdev[X] = MOUSEX;
   mdev[Y] = MOUSEY;
   getdev(2, mdev, lastval);	/* initialize lastval[] */
   lastval[X] -= org[X];
   lastval[Y] -= org[Y];
   qdevice(LEFTMOUSE);
   qdevice(MIDDLEMOUSE);
   qdevice(ESCKEY);
   qdevice(MOUSEX);
   qdevice(MOUSEY);

   qdevice(SPACEKEY);
   qdevice(RETKEY);

   qdevice(UPARROWKEY);
   qdevice(DOWNARROWKEY);

   qdevice(LEFTARROWKEY);
   qdevice(RIGHTARROWKEY);

   while (1){

      while (qtest()) {

	 switch (dev = qread(&val)) {
	 case LEFTMOUSE:
	    leftmouse_down = val;
	    break;

	 case MIDDLEMOUSE:
	    middlemouse_down = val;
	    break;

	 case MOUSEX:
	    mval[X] = val - org[X];
	    break;
	 case MOUSEY:
	    mval[Y] = val - org[Y];
	    if (leftmouse_down) {
	       rx += (mval[Y] - lastval[Y]);
	       ry += (mval[X] - lastval[X]); 
	    }
	    if (middlemouse_down){
	       Ztranslation += (mval[X] - lastval[X])*(1./8.);
	    }
	    lastval[X] = mval[X];
	    lastval[Y] = mval[Y];
	    break;

	 case SPACEKEY:
	    if (val){
	       StereoModel = (StereoModel+1)%3;
	    }
	    break;
	 
	 case RETKEY:
	    if (val){
	       IOD = 2.3;
	       StereoModel = CONVERGENCETRACK;
	       ConvergenceFudge = 0.0;
	    }
	    break;

	 case UPARROWKEY:
	    if (val)
	       ConvergenceFudge += 0.5;
	    break;

	 case DOWNARROWKEY:
	    if (val)
	       ConvergenceFudge -= 0.5;
	    break;

	 case LEFTARROWKEY:
	    if (val)
	       IOD -= .1;
	    break;

	 case RIGHTARROWKEY:
	    if (val)
	       IOD += .1;
	    break;

	 case ESCKEY:
	    exit(0);
	 }
      }


/* 
 * try to define everything in inches 
 *
 */

#define SCREEN_WIDTH  15.       /* width of screen in inches*/
#define SCREEN_HEIGHT 10.625    /* height of screen in inches*/
#define DISTANCE_TO_SCREEN 19.  /* distance from eye to screen (nearclip)*/

#define CLIP_FACTOR (1./8.00) /* to move near clip in */

#define NEAR_CLIP_DISTANCE	(DISTANCE_TO_SCREEN*CLIP_FACTOR)
#define FAR_CLIP_DISTANCE	(DISTANCE_TO_SCREEN*30.)  

#define DESIRED_SIZE_ON_SCREEN	2.
#define WORLD_SPACE_SIZE	2.


      if (LeftBuffer = !LeftBuffer){

	 leftbuffer(1);
	 rightbuffer(0); 

	 from[X] = -IOD/2.;
	 from[Y] =    0.0;
	 from[Z] =    DISTANCE_TO_SCREEN;

	 at[X] = 0.0;
	 at[Y] = 0.0;
	 at[Z] = 0.0;
      }
      else{

	 leftbuffer(0);
	 rightbuffer(1);

	 from[X] =  IOD/2.;
	 from[Y] =    0.0;
	 from[Z] =    DISTANCE_TO_SCREEN;

	 at[X] = 0.0;
	 at[Y] = 0.0;
	 at[Z] = 0.0;
      }

      if (StereoModel == CONVERGENCETRACK) {

	 float dir[3],new_dir[3],mag, new_mag;

	 /* compute old magnitude of lookat vector */
	 dir[X] = at[X]-from[X];
	 dir[Y] = at[Y]-from[Y];
	 dir[Z] = at[Z]-from[Z];
	 mag = dir[X]*dir[X] + dir[Y]*dir[Y] + dir[Z]*dir[Z];
	 mag = fsqrt(mag);

	 /* compute new lookat direction */
	 new_dir[X] = dir[X];
	 new_dir[Y] = dir[Y];
	 new_dir[Z] = dir[Z]+Ztranslation+ConvergenceFudge;
	 new_mag = new_dir[X]*new_dir[X]  + 
		   new_dir[Y]*new_dir[Y]  + 
		   new_dir[Z]*new_dir[Z];
	 new_mag = fsqrt(new_mag);
	 new_dir[X] /= new_mag;
	 new_dir[Y] /= new_mag;
	 new_dir[Z] /= new_mag;

	 /* make sure new lookat direction has same mag as old lookat vector */
	 at[X] = new_dir[X]*mag + from[X];
	 at[Y] = new_dir[Y]*mag + from[Y];
	 at[Z] = new_dir[Z]*mag + from[Z];

      }
      else if (StereoModel == PARALLELVIEWS){

	 if (LeftBuffer) at[X] = -IOD/2.;
	 else            at[X] =  IOD/2.;

      }
      else if (StereoModel == SCREENCONVERGE){
      }

      cpack(0x2f2f2f2f);
      zclear();
      clear();


      ortho2(0.,1.,0.,1.);
      cpack(0xffffffff);

      switch (StereoModel){
	 case CONVERGENCETRACK:
	    sprintf(buf,"StereModel: CONVERGENCETRACK");
	    break;
	 case PARALLELVIEWS:
	    sprintf(buf,"StereModel: PARALLELVIEWS");
	    break;
	 case SCREENCONVERGE:
	    sprintf(buf,"StereModel: SCREENCONVERGE");
	    break;
      }
      cmov2(0.1,0.96);
      charstr(buf);

      sprintf(buf,"IOD: %2.1f",IOD);
      cmov2(0.4,0.96);
      charstr(buf);

      sprintf(buf,"centroid at: %3.1f inches",
	  DISTANCE_TO_SCREEN-Ztranslation);
      cmov2(0.5,0.96);
      charstr(buf);

      /*
      sprintf(buf,"centroid at: %3.1f inches",
	  DISTANCE_TO_SCREEN-Ztranslation);
      cmov2(0.5,0.96);
      charstr(buf);
      */

      pushmatrix();

      window(-CLIP_FACTOR*SCREEN_WIDTH/2.,  CLIP_FACTOR*SCREEN_WIDTH/2.,   
	     -CLIP_FACTOR*SCREEN_HEIGHT/2., CLIP_FACTOR*SCREEN_HEIGHT/2.,
	      NEAR_CLIP_DISTANCE,  FAR_CLIP_DISTANCE);

      lookat(from[X], from[Y], from[Z], at[X],  at[Y],  at[Z], 0);

      draw_frame(ry,-rx, DESIRED_SIZE_ON_SCREEN/WORLD_SPACE_SIZE);

      popmatrix();

      if (LeftBuffer)
	 swapbuffers();
   }
}

void draw_frame(float ry, float rx, float s)
{

   register int i,j;


#if 0
   cpack(0xafafafaf);
   for (i = 0; i < 20; i++){
      float v1[3];
      float v2[3];

      v1[2] = 0.;
      v1[1] = SCREEN_HEIGHT/2.;
      v1[0] = SCREEN_WIDTH*((float)i/20.) - SCREEN_WIDTH/2;

      v2[2] = 0.;
      v2[1] = -SCREEN_HEIGHT/2.;
      v2[0] = SCREEN_WIDTH*((float)i/20.) - SCREEN_WIDTH/2;
      bgnline();
	 v3f(v1);
	 v3f(v2);
      endline();
   }
#endif


   translate(0.,0.,Ztranslation);
   rot(ry,'y');
   rot(-rx,'x');
   scale(s,s,s);

   for (i = 0; i < NumFaces; i++){
      cpack(Colors[i]);
      texbind(0,(i%6)+1);
      bgnpolygon();
      for (j = 0; j < NumVertsPerFace; j++){
	 t2f(tex[j]); v3f(cdata[cndex[i][j]]);
      }
      endpolygon();
   }
   texbind(0,0);
}

                
john m. airey      airey@asd.sgi.com  (415) 390-5248
                   M/S 7U-553 Silicon Graphics, Advanced Graphics Division
                   2011 N. Shoreline Blvd., Mtn. View, CA 94039  
Newsgroups: comp.sys.sgi.graphics