/* Rotate (ix,iy) or roll (iz) the camera about the focal point ix,iy,iz are flags, 0 do nothing, +- 1 rotates in opposite directions Correctly updating all camera attributes */ void RotateCamera(int ix,int iy,int iz) { XYZ vp,vu,vd; XYZ right; XYZ newvp,newr; double radius,dd,radians; double dx,dy,dz; vu = camera.vu; Normalise(&vu); vp = camera.vp; vd = camera.vd; Normalise(&vd); CROSSPROD(vd,vu,right); Normalise(&right); radians = dtheta * PI / 180.0; /* Handle the roll */ if (iz != 0) { camera.vu.x += iz * right.x * radians; camera.vu.y += iz * right.y * radians; camera.vu.z += iz * right.z * radians; Normalise(&camera.vu); return; } /* Distance from the rotate point */ dx = camera.vp.x - camera.pr.x; dy = camera.vp.y - camera.pr.y; dz = camera.vp.z - camera.pr.z; radius = sqrt(dx*dx + dy*dy + dz*dz); /* Determine the new view point */ dd = radius * radians; newvp.x = vp.x + dd * ix * right.x + dd * iy * vu.x - camera.pr.x; newvp.y = vp.y + dd * ix * right.y + dd * iy * vu.y - camera.pr.y; newvp.z = vp.z + dd * ix * right.z + dd * iy * vu.z - camera.pr.z; Normalise(&newvp); camera.vp.x = camera.pr.x + radius * newvp.x; camera.vp.y = camera.pr.y + radius * newvp.y; camera.vp.z = camera.pr.z + radius * newvp.z; /* Determine the new right vector */ newr.x = camera.vp.x + right.x - camera.pr.x; newr.y = camera.vp.y + right.y - camera.pr.y; newr.z = camera.vp.z + right.z - camera.pr.z; Normalise(&newr); newr.x = camera.pr.x + radius * newr.x - camera.vp.x; newr.y = camera.pr.y + radius * newr.y - camera.vp.y; newr.z = camera.pr.z + radius * newr.z - camera.vp.z; camera.vd.x = camera.pr.x - camera.vp.x; camera.vd.y = camera.pr.y - camera.vp.y; camera.vd.z = camera.pr.z - camera.vp.z; Normalise(&camera.vd); /* Determine the new up vector */ CROSSPROD(newr,camera.vd,camera.vu); Normalise(&camera.vu); }
/* Create a cone/cylinder uncapped between end points p1, p2 radius r1, r2, and precision m Create the cylinder between theta1 and theta2 in radians */ void CreateCone(XYZ p1,XYZ p2,double r1,double r2,int m,double theta1,double theta2) { int i; double theta; XYZ n,p,q,perp; /* Normal pointing from p1 to p2 */ n.x = p1.x - p2.x; n.y = p1.y - p2.y; n.z = p1.z - p2.z; Normalise(&n); /* Create two perpendicular vectors perp and q on the plane of the disk */ perp = n; if (n.x == 0 && n.z == 0) perp.x += 1; else perp.y += 1; CROSSPROD(perp,n,q); CROSSPROD(n,q,perp); Normalise(&perp); Normalise(&q); glBegin(GL_QUAD_STRIP); for (i=0; i<=m; i++) { theta = theta1 + i * (theta2 - theta1) / m; n.x = cos(theta) * perp.x + sin(theta) * q.x; n.y = cos(theta) * perp.y + sin(theta) * q.y; n.z = cos(theta) * perp.z + sin(theta) * q.z; Normalise(&n); p.x = p1.x + r1 * n.x; p.y = p1.y + r1 * n.y; p.z = p1.z + r1 * n.z; glNormal3f(n.x,n.y,n.z); glTexCoord2f(i/(double)m,0.0); glVertex3f(p.x,p.y,p.z); p.x = p2.x + r2 * n.x; p.y = p2.y + r2 * n.y; p.z = p2.z + r2 * n.z; glNormal3f(n.x,n.y,n.z); glTexCoord2f(i/(double)m,1.0); glVertex3f(p.x,p.y,p.z); } glEnd(); }
/* Translate (pan) the camera view point In response to i,j,k,l keys Also move the camera rotate location in parallel */ void TranslateCamera(int ix,int iy) { XYZ vp,vu,vd; XYZ right; XYZ newvp,newr; double radians,delta; vu = camera.vu; Normalise(&vu); vp = camera.vp; vd = camera.vd; Normalise(&vd); CROSSPROD(vd,vu,right); Normalise(&right); radians = dtheta * PI / 180.0; delta = dtheta * camera.focallength / 90.0; camera.vp.x += iy * vu.x * delta; camera.vp.y += iy * vu.y * delta; camera.vp.z += iy * vu.z * delta; camera.pr.x += iy * vu.x * delta; camera.pr.y += iy * vu.y * delta; camera.pr.z += iy * vu.z * delta; camera.vp.x += ix * right.x * delta; camera.vp.y += ix * right.y * delta; camera.vp.z += ix * right.z * delta; camera.pr.x += ix * right.x * delta; camera.pr.y += ix * right.y * delta; camera.pr.z += ix * right.z * delta; }
/* Create a disk centered at c, with normal n, inner radius r0, and outer radius r1, and precision m theta1 and theta2 are the start and end angles in radians */ void CreateDisk(XYZ c,XYZ n,double r0,double r1,int m,double theta1,double theta2) { int i; double theta; XYZ p,q,perp; /* Create two perpendicular vectors perp and q on the plane of the disk */ Normalise(&n); perp = n; if (n.x == 0 && n.z == 0) perp.x += 1; else perp.y += 1; CROSSPROD(perp,n,q); CROSSPROD(n,q,perp); Normalise(&perp); Normalise(&q); glBegin(GL_QUAD_STRIP); for (i=0; i<=m; i++) { theta = theta1 + i * (theta2 - theta1) / m; p.x = c.x + r0 * (cos(theta) * perp.x + sin(theta) * q.x); p.y = c.y + r0 * (cos(theta) * perp.y + sin(theta) * q.y); p.z = c.z + r0 * (cos(theta) * perp.z + sin(theta) * q.z); glNormal3f(n.x,n.y,n.z); glTexCoord2f(i/(double)m,0.0); glVertex3f(p.x,p.y,p.z); p.x = c.x + r1 * (cos(theta) * perp.x + sin(theta) * q.x); p.y = c.y + r1 * (cos(theta) * perp.y + sin(theta) * q.y); p.z = c.z + r1 * (cos(theta) * perp.z + sin(theta) * q.z); glNormal3f(n.x,n.y,n.z); glTexCoord2f(i/(double)m,1.0); glVertex3f(p.x,p.y,p.z); } glEnd(); }
/* This is the basic display callback routine It creates the geometry, lighting, and viewing position In this case it rotates the camera around the scene */ void Display(void) { XYZ r,eyepos; double dist,ratio,radians,scale,wd2,ndfl; double left,right,top,bottom; /* Do we need to recreate the list ? */ if (geometrydirty != NOTDIRTY) { MakeGeometry(); geometrydirty = NOTDIRTY; } /* Clip to avoid extreme stereo */ near = 0.1; far = 1000; if (stereo) near = camera.focallength / 5; /* Misc stuff */ ratio = camera.screenwidth / (double)camera.screenheight; radians = DTOR * camera.aperture / 2; wd2 = near * tan(radians); ndfl = near / camera.focallength; /* Clear the buffers */ glDrawBuffer(GL_BACK_LEFT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); if (stereo) { glDrawBuffer(GL_BACK_RIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } if (stereo) { /* Derive the two eye positions */ CROSSPROD(camera.vd,camera.vu,r); Normalise(&r); r.x *= camera.eyesep / 2.0; r.y *= camera.eyesep / 2.0; r.z *= camera.eyesep / 2.0; eyepos = VectorAdd(camera.vp,r); glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 - 0.5 * camera.eyesep * ndfl; right = ratio * wd2 - 0.5 * camera.eyesep * ndfl; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,near,far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_RIGHT); glLoadIdentity(); gluLookAt(eyepos.x,eyepos.y,eyepos.z, eyepos.x + camera.vd.x, eyepos.y + camera.vd.y, eyepos.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); MakeLighting(); glCallList(1); eyepos = VectorSub(r,camera.vp); glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 + 0.5 * camera.eyesep * ndfl; right = ratio * wd2 + 0.5 * camera.eyesep * ndfl; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,near,far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glLoadIdentity(); gluLookAt(eyepos.x,eyepos.y,eyepos.z, eyepos.x + camera.vd.x, eyepos.y + camera.vd.y, eyepos.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); MakeLighting(); glCallList(1); } else { glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2; right = ratio * wd2; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,near,far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glLoadIdentity(); gluLookAt(camera.vp.x,camera.vp.y,camera.vp.z, camera.vp.x + camera.vd.x, camera.vp.y + camera.vd.y, camera.vp.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); MakeLighting(); glCallList(1); } /* glFlush(); This isn't necessary for double buffers */ glutSwapBuffers(); if (record || windowdump) { WindowDump(camera.screenwidth,camera.screenheight,stereo); windowdump = FALSE; } if (demomode && iterationdepth < 1000) { iterationdepth++; geometrydirty = ADDONE; if (debug) fprintf(stderr,"Iteration: %d\n",iterationdepth); } }
/* This is the basic display callback routine It creates the geometry, lighting, and viewing position */ void HandleDisplay(void) { XYZ r; double ratio,radians,wd2,ndfl; double left,right,top,bottom; /* Misc stuff needed for the frustum */ ratio = camera.screenwidth / (double)camera.screenheight; if (camera.stereo == DUALSTEREO) ratio /= 2; radians = DTOR * camera.aperture / 2; wd2 = camera.near * tan(radians); ndfl = camera.near / camera.focallength; top = wd2; bottom = - wd2; /* Clear the buffers */ if (camera.stereo == ACTIVESTEREO) ClearBuffers(2); else ClearBuffers(1); /* Determine the right eye vector */ CROSSPROD(camera.vd,camera.vu,r); Normalise(&r); r.x *= camera.eyesep / 2.0; r.y *= camera.eyesep / 2.0; r.z *= camera.eyesep / 2.0; if (camera.stereo == ACTIVESTEREO || camera.stereo == DUALSTEREO) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 - 0.5 * camera.eyesep * ndfl; right = ratio * wd2 - 0.5 * camera.eyesep * ndfl; glFrustum(left,right,bottom,top,camera.near,camera.far); if (camera.stereo == DUALSTEREO) glViewport(camera.screenwidth/2,0,camera.screenwidth/2,camera.screenheight); else glViewport(0,0,camera.screenwidth,camera.screenheight); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_RIGHT); glLoadIdentity(); gluLookAt(camera.vp.x + r.x,camera.vp.y + r.y,camera.vp.z + r.z, camera.vp.x + r.x + camera.vd.x, camera.vp.y + r.y + camera.vd.y, camera.vp.z + r.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); DrawGLScene(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 + 0.5 * camera.eyesep * ndfl; right = ratio * wd2 + 0.5 * camera.eyesep * ndfl; glFrustum(left,right,bottom,top,camera.near,camera.far); if (camera.stereo == DUALSTEREO) glViewport(0,0,camera.screenwidth/2,camera.screenheight); else glViewport(0,0,camera.screenwidth,camera.screenheight); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glLoadIdentity(); gluLookAt(camera.vp.x - r.x,camera.vp.y - r.y,camera.vp.z - r.z, camera.vp.x - r.x + camera.vd.x, camera.vp.y - r.y + camera.vd.y, camera.vp.z - r.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); DrawGLScene(); } else { //not stereo glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0,0,camera.screenwidth,camera.screenheight); left = - ratio * wd2; right = ratio * wd2; glFrustum(left,right,bottom,top,camera.near,camera.far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glLoadIdentity(); gluLookAt(camera.vp.x,camera.vp.y,camera.vp.z, camera.vp.x + camera.vd.x, camera.vp.y + camera.vd.y, camera.vp.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); DrawGLScene(); } /* Swap buffers */ glutSwapBuffers(); }
/*------------------------------------------------------------------------ * Display call back * * Input: none * Output: * it will draw a box (which is the same size as the brain) and a yellow * sphere, if no datafile is specified (when running ./stereoTest -stereo) * * Otherwise, it will draw a box and a brain. * (when running ./stereoTest -stereo -f ./test.data) * * The model is set to be behind the screen when it is first loaded. */ static void draw(void) { XYZ r; double ratio, radians, wd2, ndfl; double left, right, top, bottom; /* Clip to avoid extreme stereo */ double near = camera.focallength / 5; double far = (Yminmax[1]-Yminmax[2]) * 40.0; /* Misc stuff */ ratio = camera.screenwidth / (double) camera.screenheight; radians = DTOR * camera.aperture / 2.; wd2 = near * tan(radians); ndfl = near / camera.focallength; /* Clear the buffers */ glDrawBuffer(GL_BACK_LEFT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDrawBuffer(GL_BACK_RIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Derive the two eye positions */ CROSSPROD(camera.vd, camera.vu, r); Normalise(&r); r.x *= camera.eyesep / 2.0; r.y *= camera.eyesep / 2.0; r.z *= camera.eyesep / 2.0; // left eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = -ratio * wd2 - 0.5 * camera.eyesep * ndfl; right = ratio * wd2 - 0.5 * camera.eyesep * ndfl; top = wd2; bottom = -wd2; glFrustum(left, right, bottom, top, near*2, far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_RIGHT); glLoadIdentity(); gluLookAt(camera.vp.x + r.x, camera.vp.y + r.y, camera.vp.z + r.z, camera.vp.x + r.x + camera.vd.x, camera.vp.y + r.y + camera.vd.y, camera.vp.z + r.z + camera.vd.z, camera.vu.x, camera.vu.y, camera.vu.z); do_draw(); // right eye glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = -ratio * wd2 + 0.5 * camera.eyesep * ndfl; right = ratio * wd2 + 0.5 * camera.eyesep * ndfl; top = wd2; bottom = -wd2; glFrustum(left, right, bottom, top, near*2, far); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK_LEFT); glLoadIdentity(); gluLookAt(camera.vp.x - r.x, camera.vp.y - r.y, camera.vp.z - r.z, camera.vp.x - r.x + camera.vd.x, camera.vp.y - r.y + camera.vd.y, camera.vp.z - r.z + camera.vd.z, camera.vu.x, camera.vu.y, camera.vu.z); do_draw(); //glutSwapBuffers(); }
void display() { double nearp = 0.1; double farp = 10000; XYZ r; double dist, ratio, radians, scale, wd2, ndfl; double left, right, top, bottom; /* Clip to avoid extreme stereo */ #ifdef STEREO_3D nearp = camera.focallength / 5; #endif /* Misc stuff */ ratio = camera.screenwidth / (double)camera.screenheight; radians = DTOR * camera.aperture / 2; wd2 = nearp * tan(radians); ndfl = nearp / camera.focallength; glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); #ifdef STEREO_3D update(); /* Derive the two eye positions */ CROSSPROD(camera.vd,camera.vu,r); Normalise(&r); r.x *= camera.eyesep / 2.0; r.y *= camera.eyesep / 2.0; r.z *= camera.eyesep / 2.0; glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 - 0.5 * camera.eyesep * ndfl; right = ratio * wd2 - 0.5 * camera.eyesep * ndfl; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,nearp,farp); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK); #ifdef INVERT_STEREO glViewport ( camera.screenwidth / 2, 0, camera.screenwidth / 2, camera.screenheight); #else glViewport ( 0, 0, camera.screenwidth / 2, camera.screenheight); #endif glLoadIdentity(); gluLookAt(camera.vp.x + r.x,camera.vp.y + r.y,camera.vp.z + r.z, camera.vp.x + r.x + camera.vd.x, camera.vp.y + r.y + camera.vd.y, camera.vp.z + r.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); glTranslatef(-0.5f, -0.5f, -2.0f); MakeLighting(); MakeGeometry(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2 + 0.5 * camera.eyesep * ndfl; right = ratio * wd2 + 0.5 * camera.eyesep * ndfl; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,nearp,farp); glMatrixMode(GL_MODELVIEW); glDrawBuffer(GL_BACK); #ifdef INVERT_STEREO glViewport ( 0, 0, camera.screenwidth / 2, camera.screenheight); #else glViewport ( camera.screenwidth / 2, 0, camera.screenwidth / 2, camera.screenheight); #endif // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(camera.vp.x - r.x,camera.vp.y - r.y,camera.vp.z - r.z, camera.vp.x - r.x + camera.vd.x, camera.vp.y - r.y + camera.vd.y, camera.vp.z - r.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); glTranslatef(-0.5f, -0.5f, -2.0f); MakeLighting(); MakeGeometry(); glutSwapBuffers(); glutPostRedisplay(); #else update(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); left = - ratio * wd2; right = ratio * wd2; top = wd2; bottom = - wd2; glFrustum(left,right,bottom,top,nearp,farp); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(camera.vp.x,camera.vp.y,camera.vp.z, camera.vp.x + camera.vd.x, camera.vp.y + camera.vd.y, camera.vp.z + camera.vd.z, camera.vu.x,camera.vu.y,camera.vu.z); glTranslatef(-0.5f, -0.5f, -2.0f); MakeLighting(); MakeGeometry(); glutSwapBuffers(); glutPostRedisplay(); #endif // STEREO_3D }