Chris Pollett > Old Classes >
CS116a

( Print View )

Student Corner:
  [Grades Sec1]

  [Submit Sec1]

  [Email List Sec1]

  [
Lecture Notes]

Course Info:
  [Texts & Links]
  [Topics]
  [Grading]
  [HW Info]
  [Exam Info]
  [Regrades]
  [Honesty]
  [Announcements]

HW Assignments:
  [Hw1]  [Hw2]  [Hw3]
  [Hw4]  [Hw5]

Practice Exams:
  [Mid1]  [Mid2]  [Final]

                           












HW4 Solutions Page

Return to homework page.

In the interest of getting up solutions in a timely fashion and since I had a cold for a couple weeks, I am using student solutions for HW4 and HW5. Below is the homework the grader thought was the best:

/*************************************************
Project: CS116A Homework #4
File: viewport.cpp
Purpose: to play with clipping window
Date: Nov, 17, 2004
Programmer: Gabriel Laden
**************************************************/
#include <stdlib.h>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <GL/glut.h>
using namespace std;

#define XSTATE 1
#define YSTATE 2
#define ZSTATE 3
#define LEFT 0
#define RIGHT 1
#define STRAIGHT 2
#define FORWARD 0
#define REVERSE 1

static int windowID1, windowID2;
static int state = ZSTATE;
static int xMax, yMax, zMax;
static int xMaxScreen, yMaxScreen;
static int theta;
static float xTrans, yTrans;
static int** list;
static GLint*** ptsWindow1;
static GLint*** ptsWindow2;
static GLint* rectangle;
static GLint* origRectangle;

/*************************************************/
void init1(void)
/*
PURPOSE: Initializes window1 with some OpenGL methods
*/
{
   glutSetWindow(windowID1);
   glClearColor(0.0, 0.0, 0.0, 1.0);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();

   //rotation accumulator
   theta = 0;

   //translation accumulator
   xTrans = 0;
   yTrans = 0;

   //this is the red dashed rectangle
   rectangle = (GLint*)malloc(sizeof(GLint)*8);
   rectangle[0] = 0;
   rectangle[1] = 0;
   rectangle[2] = 0;
   rectangle[7] = 0;

   if(state == XSTATE){
      xMaxScreen = yMax;
      yMaxScreen = zMax;
      glutReshapeWindow(yMax, zMax);
      gluOrtho2D(0.0, yMax, 0.0, zMax);
      rectangle[3] = zMax/2;
      rectangle[4] = yMax/2;
      rectangle[5] = zMax/2;
      rectangle[6] = yMax/2;
   }
   if(state == YSTATE){
      xMaxScreen = zMax;
      yMaxScreen = xMax;
      glutReshapeWindow(zMax, xMax);
      gluOrtho2D(0.0, zMax, 0.0, xMax);
      rectangle[3] = xMax/2;
      rectangle[4] = zMax/2;
      rectangle[5] = xMax/2;
      rectangle[6] = zMax/2;
   }
   if(state == ZSTATE){
      xMaxScreen = xMax;
      yMaxScreen = yMax;
      glutReshapeWindow(xMax, yMax);
      gluOrtho2D(0.0, xMax, 0.0, yMax);
      rectangle[3] = yMax/2;
      rectangle[4] = xMax/2;
      rectangle[5] = yMax/2;
      rectangle[6] = xMax/2;
   }
   //save a copy of this original
   origRectangle = (GLint*)malloc(sizeof(GLint)*8);
   for(int i=0; i<8; i++){
      origRectangle[i] = rectangle[i];
   }
}

/*************************************************/
void init2(void)
//PURPOSE: Initializes window2 with some OpenGL methods
{
   glutSetWindow(windowID2);
   glClearColor(0.0, 0.0, 0.0, 1.0);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();

   if(state == XSTATE){
      gluOrtho2D(0.0, yMax/2, 0.0, zMax/2);
      glutReshapeWindow(yMax/2, zMax/2);
   }
   if(state == YSTATE){
      gluOrtho2D(0.0, zMax/2, 0.0, xMax/2);
      glutReshapeWindow(zMax/2, xMax/2);
   }
   if(state == ZSTATE){
      gluOrtho2D(0.0, xMax/2, 0.0, yMax/2);
      glutReshapeWindow(xMax/2, yMax/2);
   }
}

/*************************************************/
void drawview1(void)
/*
PURPOSE: draw the two windows with view of scene
*/
{
   glutSetWindow(windowID1);
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(0.0, 0.0, 1.0);

   int listLength = list[0][0];
   ptsWindow1 = (int***)malloc(sizeof(int**)*listLength);
   for(int i=0; i<listLength; i++){
      int rowLength = list[i+1][0];
      ptsWindow1[i] = (int**)malloc(sizeof(int*)*rowLength);
      if(state == XSTATE){
         //pick out the y-z coords
         int index = 2;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow1[i][j][0] = list[i+1][index];
            ptsWindow1[i][j][1] = list[i+1][index+1];
         }
      }
      if(state == YSTATE){
         //pick out the z-x coords
         int index = 3;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow1[i][j][0] = list[i+1][index];
            ptsWindow1[i][j][1] = list[i+1][index-2];
         }
      }
      if(state == ZSTATE){
         //pick out the x-y coords
         int index = 1;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow1[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow1[i][j][0] = list[i+1][index];
            ptsWindow1[i][j][1] = list[i+1][index+1];
         }
      }
   }

   //ok, now draw the lines in window1
   for(int i=0; i<listLength; i++){
      glBegin(GL_LINE_LOOP);
         for(int j=0; j<list[i+1][0]; j++){
            glVertex2iv(ptsWindow1[i][j]);
         }
      glEnd();
   }

   //draw the red rectangle box
   glColor3f(1.0, 0.0, 0.0);
   glEnable(GL_LINE_STIPPLE);
   glLineStipple(1, 0x00FF);
   glBegin(GL_LINE_LOOP);
      glVertex2i(rectangle[0],rectangle[1]);
      glVertex2i(rectangle[2],rectangle[3]);
      glVertex2i(rectangle[4],rectangle[5]);
      glVertex2i(rectangle[6],rectangle[7]);
   glEnd();
   glDisable(GL_LINE_STIPPLE);
   glFlush();
}

/*************************************************/
void drawview2(void)
//PURPOSE:  draw the two windows with view of scene
{
   glutSetWindow(windowID2);
   glutPositionWindow(400, 400);
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f(0.0, 0.0, 1.0);

   int listLength = list[0][0];
   ptsWindow2 = (int***)malloc(sizeof(int**)*listLength);
   for(int i=0; i<listLength; i++){
      int rowLength = list[i+1][0];
      ptsWindow2[i] = (int**)malloc(sizeof(int*)*rowLength);
      if(state == XSTATE){
         //pick out the y-z coords
         int index = 2;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow2[i][j][0] = list[i+1][index];
            ptsWindow2[i][j][1] = list[i+1][index+1];
         }
      }
      if(state == YSTATE){
         //pick out the z-x coords
         int index = 3;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow2[i][j][0] = list[i+1][index];
            ptsWindow2[i][j][1] = list[i+1][index-2];
         }
      }
      if(state == ZSTATE){
         //pick out the x-y coords
         int index = 1;
         for(int j=0; j<rowLength; j++, index+=3){
            ptsWindow2[i][j] = (int*)malloc(sizeof(int)*2);
            ptsWindow2[i][j][0] = list[i+1][index];
            ptsWindow2[i][j][1] = list[i+1][index+1];
         }
      }
   }

   //reverse translate the points
   //reverse rotate the points
   float x, y;
   float COSDEG = cos(-theta * 3.1415926536/180);
   float SINDEG = sin(-theta * 3.1415926536/180);
   for(int i=0; i<list[0][0]; i++){
      glBegin(GL_LINE_LOOP);
      for(int j=0; j<list[i+1][0]; j++){
            x = ptsWindow2[i][j][0] - xTrans;
            y = ptsWindow2[i][j][1] - yTrans;
            glVertex2i(x*COSDEG - y*SINDEG, x*SINDEG + y*COSDEG);
      }
      glEnd();
   }
   glFlush();
}


/*-----------------------------------------------*/
bool rotate(int direction)
/*
PURPOSE: Rotates the rectangle, if possible
RECEIVES: direction - use LEFT or RIGHT
*/
{
   /* translate first point back to origin
      and translate other points by that amount
      first point is fixed at origin,
      rotate the other points +/-
      translate points back
      check to see if in bounds
   */

   //save a copy of rectangle, if we have to restore
   GLint* temp =(GLint*)malloc(sizeof(GLint)*8);
   for(int i=0; i<8; i++){
      temp[i] = rectangle[i];
   }
   int tempTheta = theta;

   //rotate initial rectangle by accumulated theta
   if(direction == LEFT){
      theta++;
   }
   else if(direction == RIGHT){
      theta--;
   }
   float x, y;
   float COSDEG = cos(theta * 3.1415926536/180);
   float SINDEG = sin(theta * 3.1415926536/180);
   for(int i=2; i<8; i+=2){
      x = origRectangle[i]*COSDEG - origRectangle[i+1]*SINDEG;
      y = origRectangle[i]*SINDEG + origRectangle[i+1]*COSDEG;
      rectangle[i] = x;
      rectangle[i+1] = y;
   }
   //translate back
   for(int i=2; i<8; i+=2){
      rectangle[i] += xTrans;
      rectangle[i+1] += yTrans;
   }
   //check if points still inbounds
   bool fail = false;
   for(int i=0; i<8 && !fail; i+=2){
      if(rectangle[i] < 0 || rectangle[i] > xMaxScreen){
         fail = true;
      }
      if(rectangle[i+1] < 0 || rectangle[i+1] > yMaxScreen){
         fail = true;
      }
   }
   if(fail){
      //write back the temp array to the rectangle
      for(int i=0; i<8; i++){
         rectangle[i] = temp[i];
      }
      theta = tempTheta;
      return false;
   }
   return true;
}

/*-----------------------------------------------*/
void move(int direction)
/*
PURPOSE: Moves the rectangle, if possible
RECEIVES: direction - use FORWARD or REVERSE
*/
{
   //save a copy of rectangle, if we have to restore
   GLint* temp =(GLint*)malloc(sizeof(GLint)*8);
   for(int i=0; i<8; i++){
      temp[i] = rectangle[i];
   }
   int tempXTrans = xTrans;
   int tempYTrans = yTrans;

   //points to use for slope
   int x0 = rectangle[0];
   int y0 = rectangle[1];
   int xEnd = rectangle[2];
   int yEnd = rectangle[3];

   //handle special cases first
   if(x0 == xEnd)
   {
      //vertical
      if(direction == FORWARD){
         if(yEnd > y0){
            yTrans++;
         }
         else{
            yTrans--;
         }
         for(int i=0; i<8; i+=2){
            rectangle[i+1] = origRectangle[i+1] + yTrans;
         }
      }
      else if(direction == REVERSE){
         if(yEnd < y0){
            yTrans++;
         }
         else{
            yTrans--;
         }
         for(int i=0; i<8; i+=2){
            rectangle[i+1] = origRectangle[i+1] + yTrans;
         }
      }
   }
   else if(y0 == yEnd)
   {
      //horizontal
      if(direction == FORWARD){
         if(xEnd > x0){
            xTrans++;
         }
         else{
            xTrans--;
         }
         for(int i=0; i<8; i+=2){
            rectangle[i] = origRectangle[i] + xTrans;
         }
      }
      else if(direction == REVERSE){
         if(xEnd < x0){
            xTrans++;
         }
         else{
            xTrans--;
         }
         for(int i=0; i<8; i+=2){
            rectangle[i] = origRectangle[i] + xTrans;
         }
      }
   }
   else
   {
      if((yEnd-y0)/(xEnd-x0) == 1){
         //positive diagonal
         if(direction == FORWARD){
            if(yEnd > y0){
               xTrans++;
               yTrans++;
            }
            else{
               xTrans--;
               yTrans--;
            }
            for(int i=0; i<8; i+=2){
               rectangle[i] = origRectangle[i] + xTrans;
               rectangle[i+1] = origRectangle[i+1] + yTrans;
            }
         }
         else if(direction == REVERSE){
            if(yEnd < y0){
               xTrans++;
               yTrans++;
            }
            else{
               xTrans--;
               yTrans--;
            }
            for(int i=0; i<8; i+=2){
               rectangle[i] = origRectangle[i] + xTrans;
               rectangle[i+1] = origRectangle[i+1] + yTrans;
            }
         }
      }
      if((yEnd-y0)/(xEnd-x0) == -1){
         //negative diagonal
         if(direction == FORWARD){
            if(yEnd > y0){
               xTrans--;
               yTrans++;
            }
            else{
               xTrans++;
               yTrans--;
            }
            for(int i=0; i<8; i+=2){
               rectangle[i] = origRectangle[i] + xTrans;
               rectangle[i+1] = origRectangle[i+1] + yTrans;
            }
         }
         else if(direction == REVERSE){
            if(yEnd < y0){
               xTrans--;
               yTrans++;
            }
            else{
               xTrans++;
               yTrans--;
            }
            for(int i=0; i<8; i+=2){
               rectangle[i] = origRectangle[i] + xTrans;
               rectangle[i+1] = origRectangle[i+1] + yTrans;
            }
         }
      }
      //non special cases
      float dy = yEnd - y0;
      float dx = xEnd - x0;
      float m = dy / dx;

      if(m > 0 && m < 1){
         if((dy > 0 && direction == FORWARD) || (dy < 0 && direction == REVERSE)){
            xTrans++;
            yTrans += m;
         }
         else{
            xTrans--;
            yTrans -= m;
         }
      }
      else if(m > 1){
         if((dy > 0 && direction == FORWARD) || (dy < 0 && direction == REVERSE)){
            yTrans++;
            xTrans += 1/m;
         }
         else{
            yTrans--;
            xTrans -= 1/m;
         }
      }
      else if(m > -1 && m < 0){
         if((dy < 0 && direction == FORWARD) || (dy > 0 && direction == REVERSE)){
            xTrans++;
            yTrans += m;
         }
         else{
            xTrans--;
            yTrans -= m;
         }
      }
      else if (m < -1){
         if((dy < 0 && direction == FORWARD) || (dy > 0 && direction == REVERSE)){
            yTrans--;
            xTrans -= 1/m;
         }
         else{
            yTrans++;
            xTrans += 1/m;
         }
      }
      for(int i=0; i<8; i+=2){
         rectangle[i] = origRectangle[i] + xTrans;
         rectangle[i+1] = origRectangle[i+1] + yTrans;
      }
   }

   bool fail = false;
   //now rotate rectangle
   if(!rotate(STRAIGHT)){
      fail = true;
   }

   //test xy coords
   for(int i=0; i<8 && !fail; i+=2){
      if(rectangle[i] < 0 || rectangle[i] > xMaxScreen){
         fail = true;
      }
      if(rectangle[i+1] < 0 || rectangle[i+1] > yMaxScreen){
         fail = true;
      }
      if(xTrans < 0 || xTrans > xMaxScreen){
         fail = true;
      }
      if(yTrans < 0 || yTrans > yMaxScreen){
         fail = true;
      }
   }
   if(fail){
      //write back the temp array to the rectangle
      for(int i=0; i<8; i++){
         rectangle[i] = temp[i];
      }
      xTrans = tempXTrans;
      yTrans = tempYTrans;
   }
}


/*-----------------------------------------------*/
void keyHandleFn(int key, int x, int y)
/*
PURPOSE: Handles keyboard events. The keyboard was very useful in testing this project
RECEIVES: key - the special key (non a-z letter) pressed
*/
{
   switch(key)
   {
      case GLUT_KEY_LEFT:
         //rotate left
         rotate(LEFT);
         break;

      case GLUT_KEY_RIGHT:
         //rotate right
         rotate(RIGHT);
         break;

      case GLUT_KEY_UP:
         //forward
         move(FORWARD);
         break;

      case GLUT_KEY_DOWN:
         //reverse
         move(REVERSE);
         break;
   }
   glutPostRedisplay();
   glutSetWindow(windowID2);
   glutPostRedisplay();
}

/*-----------------------------------------------*/
void keyHandleFn1(unsigned char key, int x, int y)
/*
PURPOSE: Handles keyboard events like space and esc.
       The keyboard was very useful in testing this project
RECEIVES: key - the special key (non a-z letter) pressed
          x - screen X position
        y - screen Y position
RETURNS: nothing
REMARKS:
*/
{
   switch(key)
   {
      case 'x':
         state = XSTATE;
         break;
       case 'y':
         state = YSTATE;
         break;
       case 'z':
         state = ZSTATE;
         break;
   }
   init1();
   init2();
}

/*************************************************/
void readParam(char f[])
/*
PURPOSE: reads input parameters.txt, writes to globals
*/
{
   //read the txt file
   ifstream file(f, ios::in);
   char line[80];

   //x, y window dimensions
   file.getline(line, 80);
   xMax = atoi(strtok(line, " "));
   yMax = atoi(strtok(NULL, " "));
   zMax = atoi(strtok(NULL, " "));

   //# of polylines
   file.getline(line, 80);
   int length = atoi(strtok(line, " "));
   list = (int**)malloc(sizeof(int*)*(length + 1));
   list[0] = (int*)malloc(sizeof(int));
   list[0][0] = length;
   for(int i=1; i<=length; i++){
      file.getline(line, 80);
      int polyLength = atoi(strtok(line, " "));
      list[i] = (int*)malloc(sizeof(int)*(polyLength * 3 + 1));
      list[i][0] = polyLength;
      for(int j=1; j<polyLength*3+1; j++){
         list[i][j] = atoi(strtok(NULL, " "));
      }
   }
   file.close();
}

/*************************************************/
void main(int argc, char** argv)
/*
PURPOSE: boilerplate code which launches windows
*/
{
   if(argc != 2){
      cout << "Usage: viewport file\n";
   }
   else{
      readParam(argv[1]);
      glutInit(&argc, argv);
      glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
      glutInitWindowPosition(0, 0);

      //second window
      windowID2 = glutCreateWindow("Second Window");
      init2();
      glutDisplayFunc(drawview2);

      //first window
      windowID1 = glutCreateWindow("First Window");
      init1();
      glutDisplayFunc(drawview1);

      //Set up keyboard handlers
      glutSpecialFunc(keyHandleFn); // for arrow keys
      glutKeyboardFunc(keyHandleFn1); // for space esc

      glutMainLoop();
   }
}

Return to homework page.