#include #include #include #include "Go.h" #include "GoText.h" #include "GoGlutInterface.h" /* NOTE: * * The following include file is for implementing the * method getTimeMillis(). In this example a Unix * implementation of the getTimeMillis() method is * provided. The appropriate include file and system * specific calls for computing the current time in * in milliseconds via the getTimeMillis() method * is necessary to compile and work correctly. */ #include #define PI 3.14159265358979324 class GoTeapot : public GoGlutInterface { public: // Data & text. GoTriangles *data; GoText *frameRateText; // View variables. double eyeX; double eyeY; double eyeZ; double centerX; double centerY; double centerZ; double upX; double upY; double upZ; double radius; boolean perspective; // Timing variables. long time; long startTime; long lastTime; long secondsPassed; int frameCount; // Coordinate reference. enum { X, Y, Z, W }; GoTeapot(void) { // // Background and foreground colors. // go->background(0.078, 0.361, 0.753); go->color(1.0, 0.5, 0.1); // // Enable a light. (Use the default values) // go->light(Go::LIGHT_0, true); // // Create the teapot data. // createTeapot(); // // Initialize the frames/sec variables. // frameRateText = new GoText(4.9, 0.9, 0.0, // position 1.0, 0.0, // path 0.58, 0.58, // scale GoText::LEFT_CENTER, // alignment new GoHershey("hersheyFonts/futura.l"), // font ""); // text (nothing for now) startTime = getTimeMillis(); lastTime = startTime; frameCount = 0; secondsPassed = 0; // // Calculate the teapot's bounding box. // go->renderMode(Go::BOUND_BOX); go->render(data); go->renderMode(Go::IMAGE); GoBoundBox *boundBox = go->boundBox(); double xMin = boundBox->xMin(); double yMin = boundBox->yMin(); double zMin = boundBox->zMin(); double xMax = boundBox->xMax(); double yMax = boundBox->yMax(); double zMax = boundBox->zMax(); // // Define the initial view. // eyeX = 4.86; eyeY = 7.2; eyeZ = 7.4; centerX = (xMin + xMax) / 2.0; centerY = (yMin + yMax) / 2.0; centerZ = (zMin + zMax) / 2.0; upX = 0.0; upY = 0.0; upZ = 1.0; radius = 4.3; perspective = true; go->lookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ); } // // Returns the current time in milliseconds. // // NOTE: This method is system dependent. // long getTimeMillis() { struct timeval time; struct timezone tzp; gettimeofday(&time, &tzp); return (time.tv_sec * 1000000L + time.tv_usec) / 1000L; } // // Sets the frame rate text displayed in the lower left corner. // void setFrameRateText() { char str[100]; sprintf(str, "frames/sec = %.2lf\n", (double)frameCount/((double)(time - lastTime)/1000.0)); frameRateText->text(str); } // // Interface render method. // void render(void) { // // Calculate the frames per second. // frameCount++; time = getTimeMillis(); if(secondsPassed != (time - startTime) / 1000) { setFrameRateText(); lastTime = time; secondsPassed = (time - startTime) / 1000; frameCount = 0; } // // Clear the image. // go->clear(Go::IMAGE); // // Draw the teapot. // go->push(Go::MODELVIEW); go->translate(centerX, centerY, centerZ); go->rotate((time - startTime) / 1000.0 * 30.0, -0.4, -0.4, 1); // Rotate at 30 degrees/sec go->translate(-centerX, -centerY, -centerZ); go->render(data); go->pop(Go::MODELVIEW); // // Draw the frames/sec text. // go->push(Go::COLOR); go->color(1.0, 1.0, 0.0); frameRateText->render(go); go->pop(Go::COLOR); // // Display all that has been drawn, and do it again. // swap(); rerender(); } // // Interface resized method. // void resized(int width, int height) { double dx = eyeX - centerX; double dy = eyeY - centerY; double dz = eyeZ - centerZ; double d = sqrt(dx * dx + dy * dy + dz * dz); double fovy = 2.0 * 180.0/PI * atan(radius / d); double near = d - radius; double far = d + radius; double xUnits, yUnits; if(width >= height) { xUnits = 2 * radius * width / height; yUnits = 2 * radius; } else { xUnits = 2 * radius; yUnits = 2 * radius * height / width; } // setup projection matrix go->matrixMode(Go::PROJECTION); go->identity(); if(perspective) { if(width >= height) { go->perspective(fovy, xUnits / yUnits, near, far); } else { double r = radius * yUnits / xUnits; double fovyModified = atan(r / d) * 180.0 / PI * 2.0; go->perspective(fovyModified, xUnits / yUnits, near, far); } } else { go->ortho(-xUnits / 2.0, xUnits / 2.0, -yUnits / 2.0, yUnits / 2.0, near, far); } go->matrixMode(Go::MODELVIEW); } // // Creates the teapot data. // void createTeapot(void) { // Resolution of teapot. int SIZE_FACTOR = 5; // Number of spline surfaces that define the teapot. int NUM_PATCHES = 32; int patches[][4][4] = { /* rim */ {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}, {12, 13, 14, 15}}, {{3, 16, 17, 18}, {7, 19, 20, 21}, {11, 22, 23, 24}, {15, 25, 26, 27}}, {{18, 28, 29, 30}, {21, 31, 32, 33}, {24, 34, 35, 36}, {27, 37, 38, 39}}, {{30, 40, 41, 0}, {33, 42, 43, 4}, {36, 44, 45, 8}, {39, 46, 47, 12}}, /* body */ {{12, 13, 14, 15}, {48, 49, 50, 51}, {52, 53, 54, 55}, {56, 57, 58, 59}}, {{15, 25, 26, 27}, {51, 60, 61, 62}, {55, 63, 64, 65}, {59, 66, 67, 68}}, {{27, 37, 38, 39}, {62, 69, 70, 71}, {65, 72, 73, 74}, {68, 75, 76, 77}}, {{39, 46, 47, 12}, {71, 78, 79, 48}, {74, 80, 81, 52}, {77, 82, 83, 56}}, {{56, 57, 58, 59}, {84, 85, 86, 87}, {88, 89, 90, 91}, {92, 93, 94, 95}}, {{59, 66, 67, 68}, {87, 96, 97, 98}, {91, 99, 100, 101}, {95, 102, 103, 104}}, {{68, 75, 76, 77}, {98, 105, 106, 107}, {101, 108, 109, 110}, {104, 111, 112, 113}}, {{77, 82, 83, 56}, {107, 114, 115, 84}, {110, 116, 117, 88}, {113, 118, 119, 92}}, /* handle */ {{120, 121, 122, 123}, {124, 125, 126, 127}, {128, 129, 130, 131}, {132, 133, 134, 135}}, {{123, 136, 137, 120}, {127, 138, 139, 124}, {131, 140, 141, 128}, {135, 142, 143, 132}}, {{132, 133, 134, 135}, {144, 145, 146, 147}, {148, 149, 150, 151}, {68, 152, 153, 154}}, {{135, 142, 143, 132}, {147, 155, 156, 144}, {151, 157, 158, 148}, {154, 159, 160, 68}}, /* spout */ {{161, 162, 163, 164}, {165, 166, 167, 168}, {169, 170, 171, 172}, {173, 174, 175, 176}}, {{164, 177, 178, 161}, {168, 179, 180, 165}, {172, 181, 182, 169}, {176, 183, 184, 173}}, {{173, 174, 175, 176}, {185, 186, 187, 188}, {189, 190, 191, 192}, {193, 194, 195, 196}}, {{176, 183, 184, 173}, {188, 197, 198, 185}, {192, 199, 200, 189}, {196, 201, 202, 193}}, /* lid */ {{203, 203, 203, 203}, {204, 205, 206, 207}, {208, 208, 208, 208}, {209, 210, 211, 212}}, {{203, 203, 203, 203}, {207, 213, 214, 215}, {208, 208, 208, 208}, {212, 216, 217, 218}}, {{203, 203, 203, 203}, {215, 219, 220, 221}, {208, 208, 208, 208}, {218, 222, 223, 224}}, {{203, 203, 203, 203}, {221, 225, 226, 204}, {208, 208, 208, 208}, {224, 227, 228, 209}}, {{209, 210, 211, 212}, {229, 230, 231, 232}, {233, 234, 235, 236}, {237, 238, 239, 240}}, {{212, 216, 217, 218}, {232, 241, 242, 243}, {236, 244, 245, 246}, {240, 247, 248, 249}}, {{218, 222, 223, 224}, {243, 250, 251, 252}, {246, 253, 254, 255}, {249, 256, 257, 258}}, {{224, 227, 228, 209}, {252, 259, 260, 229}, {255, 261, 262, 233}, {258, 263, 264, 237}}, /* bottom */ {{265, 265, 265, 265}, {266, 267, 268, 269}, {270, 271, 272, 273}, {92, 119, 118, 113}}, {{265, 265, 265, 265}, {269, 274, 275, 276}, {273, 277, 278, 279}, {113, 112, 111, 104}}, {{265, 265, 265, 265}, {276, 280, 281, 282}, {279, 283, 284, 285}, {104, 103, 102, 95}}, {{265, 265, 265, 265}, {282, 286, 287, 266}, {285, 288, 289, 270}, {95, 94, 93, 92}} }; double verts[][3] = { {1.4, 0, 2.4}, {1.4, -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125}, {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375, 0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375, 2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84, 2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {-0.784, -1.4, 2.4}, {-1.4, -0.784, 2.4}, {-1.4, 0, 2.4}, {-0.749, -1.3375, 2.53125}, {-1.3375, -0.749, 2.53125}, {-1.3375, 0, 2.53125}, {-0.805, -1.4375, 2.53125}, {-1.4375, -0.805, 2.53125}, {-1.4375, 0, 2.53125}, {-0.84, -1.5, 2.4}, {-1.5, -0.84, 2.4}, {-1.5, 0, 2.4}, {-1.4, 0.784, 2.4}, {-0.784, 1.4, 2.4}, {0, 1.4, 2.4}, {-1.3375, 0.749, 2.53125}, {-0.749, 1.3375, 2.53125}, {0, 1.3375, 2.53125}, {-1.4375, 0.805, 2.53125}, {-0.805, 1.4375, 2.53125}, {0, 1.4375, 2.53125}, {-1.5, 0.84, 2.4}, {-0.84, 1.5, 2.4}, {0, 1.5, 2.4}, {0.784, 1.4, 2.4}, {1.4, 0.784, 2.4}, {0.749, 1.3375, 2.53125}, {1.3375, 0.749, 2.53125}, {0.805, 1.4375, 2.53125}, {1.4375, 0.805, 2.53125}, {0.84, 1.5, 2.4}, {1.5, 0.84, 2.4}, {1.75, 0, 1.875}, {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75, 1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35}, {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2, 0.9}, {0, -2, 0.9}, {-0.98, -1.75, 1.875}, {-1.75, -0.98, 1.875}, {-1.75, 0, 1.875}, {-1.12, -2, 1.35}, {-2, -1.12, 1.35}, {-2, 0, 1.35}, {-1.12, -2, 0.9}, {-2, -1.12, 0.9}, {-2, 0, 0.9}, {-1.75, 0.98, 1.875}, {-0.98, 1.75, 1.875}, {0, 1.75, 1.875}, {-2, 1.12, 1.35}, {-1.12, 2, 1.35}, {0, 2, 1.35}, {-2, 1.12, 0.9}, {-1.12, 2, 0.9}, {0, 2, 0.9}, {0.98, 1.75, 1.875}, {1.75, 0.98, 1.875}, {1.12, 2, 1.35}, {2, 1.12, 1.35}, {1.12, 2, 0.9}, {2, 1.12, 0.9}, {2, 0, 0.45}, {2, -1.12, 0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225}, {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225}, {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0, -1.5, 0.15}, {-1.12, -2, 0.45}, {-2, -1.12, 0.45}, {-2, 0, 0.45}, {-0.84, -1.5, 0.225},{-1.5, -0.84, 0.225}, {-1.5, 0, 0.225}, {-0.84, -1.5, 0.15}, {-1.5, -0.84, 0.15}, {-1.5, 0, 0.15}, {-2, 1.12, 0.45}, {-1.12, 2, 0.45}, {0, 2, 0.45}, {-1.5, 0.84, 0.225}, {-0.84, 1.5, 0.225}, {0, 1.5, 0.225}, {-1.5, 0.84, 0.15}, {-0.84, 1.5, 0.15}, {0, 1.5, 0.15}, {1.12, 2, 0.45}, {2, 1.12, 0.45}, {0.84, 1.5, 0.225}, {1.5, 0.84, 0.225}, {0.84, 1.5, 0.15}, {1.5, 0.84, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5, -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3, 2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0, 2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0, 2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8}, {-3, 0, 1.8}, {-1.5, 0.3, 2.25}, {-1.6, 0.3, 2.025}, {-2.5, 0.3, 2.25}, {-2.3, 0.3, 2.025}, {-3, 0.3, 2.25}, {-2.7, 0.3, 2.025}, {-3, 0.3, 1.8}, {-2.7, 0.3, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3, -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3, 1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2, -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {-3, 0.3, 1.35}, {-2.7, 0.3, 1.575}, {-2.65, 0.3, 0.9375}, {-2.5, 0.3, 1.125}, {-1.9, 0.3, 0.6}, {-2, 0.3, 0.9}, {1.7, 0, 1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0, 0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66, 0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1}, {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7, -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {1.7, 0.66, 0.6}, {1.7, 0.66, 1.425}, {3.1, 0.66, 0.825}, {2.6, 0.66, 1.425}, {2.4, 0.25, 2.025}, {2.3, 0.25, 2.1}, {3.3, 0.25, 2.4}, {2.7, 0.25, 2.4}, {2.8, 0, 2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375}, {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475}, {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4}, {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {3.525, 0.25, 2.49375}, {2.8, 0.25, 2.475}, {3.45, 0.15, 2.5125}, {2.9, 0.15, 2.475}, {3.2, 0.15, 2.4}, {2.8, 0.15, 2.4}, {0, 0, 3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8, 3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0, -0.2, 2.7}, {-0.45, -0.8, 3.15}, {-0.8, -0.45, 3.15}, {-0.8, 0, 3.15}, {-0.112, -0.2, 2.7}, {-0.2, -0.112, 2.7}, {-0.2, 0, 2.7}, {-0.8, 0.45, 3.15}, {-0.45, 0.8, 3.15}, {0, 0.8, 3.15}, {-0.2, 0.112, 2.7}, {-0.112, 0.2, 2.7}, {0, 0.2, 2.7}, {0.45, 0.8, 3.15}, {0.8, 0.45, 3.15}, {0.112, 0.2, 2.7}, {0.2, 0.112, 2.7}, {0.4, 0, 2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4, 2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3, 2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4}, {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {-0.224, -0.4, 2.55}, {-0.4, -0.224, 2.55}, {-0.4, 0, 2.55}, {-0.728, -1.3, 2.55}, {-1.3, -0.728, 2.55}, {-1.3, 0, 2.55}, {-0.728, -1.3, 2.4}, {-1.3, -0.728, 2.4}, {-1.3, 0, 2.4}, {-0.4, 0.224, 2.55}, {-0.224, 0.4, 2.55}, {0, 0.4, 2.55}, {-1.3, 0.728, 2.55}, {-0.728, 1.3, 2.55}, {0, 1.3, 2.55}, {-1.3, 0.728, 2.4}, {-0.728, 1.3, 2.4}, {0, 1.3, 2.4}, {0.224, 0.4, 2.55}, {0.4, 0.224, 2.55}, {0.728, 1.3, 2.55}, {1.3, 0.728, 2.55}, {0.728, 1.3, 2.4}, {1.3, 0.728, 2.4}, {0, 0, 0}, {1.425, 0, 0}, {1.425, 0.798, 0}, {0.798, 1.425, 0}, {0, 1.425, 0}, {1.5, 0, 0.075}, {1.5, 0.84, 0.075}, {0.84, 1.5, 0.075}, {0, 1.5, 0.075}, {-0.798, 1.425, 0}, {-1.425, 0.798, 0}, {-1.425, 0, 0}, {-0.84, 1.5, 0.075}, {-1.5, 0.84, 0.075}, {-1.5, 0, 0.075}, {-1.425, -0.798, 0}, {-0.798, -1.425, 0}, {0, -1.425, 0}, {-1.5, -0.84, 0.075}, {-0.84, -1.5, 0.075}, {0, -1.5, 0.075}, {0.798, -1.425, 0}, {1.425, -0.798, 0}, {0.84, -1.5, 0.075}, {1.5, -0.84, 0.075} }; /* bezier form */ static double ms[4][4] = { -1.0, 3.0, -3.0, 1.0, 3.0, -6.0, 3.0, 0.0, -3.0, 3.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0 } ; int surf, i, r, c, sstep, tstep, num_tri, num_vert, num_tri_vert; double s[3]; double t[3]; double vert[4][3]; double norm[4][3]; double mst[4][4]; double g[4][4]; double mgm[3][4][4]; double tmtx[4][4]; int count = 0; data = new GoTriangles(NUM_PATCHES * SIZE_FACTOR * SIZE_FACTOR * 6, Go::NORMAL); transpose_matrix( mst, ms ) ; for ( surf = 0 ; surf < NUM_PATCHES ; surf++ ) { /* get M * G * M matrix for x,y,z */ for ( i = 0 ; i < 3 ; i++ ) { /* get control patches */ for ( r = 0 ; r < 4 ; r++ ) { for ( c = 0 ; c < 4 ; c++ ) { g[r][c] = verts[patches[surf][r][c]][i] ; } } matrix_multiply( tmtx, ms, g ) ; matrix_multiply( mgm[i], tmtx, mst ) ; } /* step along, get points, and output */ for ( sstep = 0 ; sstep < SIZE_FACTOR ; sstep++ ) { for ( tstep = 0 ; tstep < SIZE_FACTOR ; tstep++ ) { for ( num_tri = 0 ; num_tri < 2 ; num_tri++ ) { for ( num_vert = 0 ; num_vert < 3 ; num_vert++ ) { num_tri_vert = ( num_vert + num_tri * 2 ) % 4 ; /* trickiness: add 1 to sstep if 1 or 2 */ s[num_vert] = (double)(sstep + (num_tri_vert/2 ? 1:0) ) / (double)SIZE_FACTOR ; /* trickiness: add 1 to tstep if 2 or 3 */ t[num_vert] = (double)(tstep + (num_tri_vert%3 ? 1:0) ) / (double)SIZE_FACTOR ; } points_from_basis( 3, s, t, mgm, vert, norm ); /* don't output degenerate polygons */ if ( check_for_cusp( 3, vert, norm ) ) { for (i = 0; i < 3; ++i) { data->xyz(count+i, vert[i][X], vert[i][Y], vert[i][Z]); data->ijk(count+i, norm[i][X], norm[i][Y], norm[i][Z]); } count += 3; } } } } } /* remove vertices not needed due to degenerate triangles */ data->remove(count, data->vertexNumber() - count); } // // Normalize the vector (X,Y,Z) so that X*X + Y*Y + Z*Z = 1. // // The normalization divisor is returned. If the divisor is zero, no // normalization occurs. // double normalize_vector(double cvec[]) { double divisor; divisor = sqrt( (double)DOT_PRODUCT(cvec, cvec) ); if (divisor > 0.0) { cvec[X] /= divisor; cvec[Y] /= divisor; cvec[Z] /= divisor; } return divisor; } // // Multiply a 4 element vector by a matrix. Typically used for // homogenous transformation from world space to screen space. // void transform_coord(double vres[], double vec[], double mx[4][4]) { double vtemp[4]; vtemp[X] = vec[X]*mx[0][0]+vec[Y]*mx[1][0]+vec[Z]*mx[2][0]+vec[W]*mx[3][0]; vtemp[Y] = vec[X]*mx[0][1]+vec[Y]*mx[1][1]+vec[Z]*mx[2][1]+vec[W]*mx[3][1]; vtemp[Z] = vec[X]*mx[0][2]+vec[Y]*mx[1][2]+vec[Z]*mx[2][2]+vec[W]*mx[3][2]; vtemp[W] = vec[X]*mx[0][3]+vec[Y]*mx[1][3]+vec[Z]*mx[2][3]+vec[W]*mx[3][3]; vres[X] = vtemp[X]; vres[Y] = vtemp[Y]; vres[Z] = vtemp[Z]; vres[W] = vtemp[W]; } // // Compute transpose of matrix. // void transpose_matrix( double mxres[4][4], double mx[4][4] ) { int i, j; for (i=0;i<4;i++) for (j=0;j<4;j++) mxres[j][i] = mx[i][j]; } // // Multiply two 4x4 matrices. Note that mxres had better not be // the same as either mx1 or mx2 or bad results will be returned. // void matrix_multiply(double mxres[4][4], double mx1[4][4], double mx2[4][4]) { int i, j; for (i=0;i<4;i++) for (j=0;j<4;j++) mxres[i][j] = mx1[i][0]*mx2[0][j] + mx1[i][1]*mx2[1][j] + mx1[i][2]*mx2[2][j] + mx1[i][3]*mx2[3][j]; } // // At the center of the lid's handle and at bottom are cusp points - // check if normal is (0 0 0), if so, check that polygon is not degenerate. // If degenerate, return FALSE, else set normal. // boolean check_for_cusp(int tot_vert, double vert[][3], double norm[][3]) { int count, i, nv ; for ( count = 0, i = tot_vert ; i-- ; ) { /* check if vertex is at cusp */ if ( IS_VAL_ALMOST_ZERO( vert[i][X], 0.0001 ) && IS_VAL_ALMOST_ZERO( vert[i][Y], 0.0001 ) ) { count++ ; nv = i ; } } if ( count > 1 ) { /* degenerate */ return( false ) ; } if ( count == 1 ) { /* check if point is somewhere above the middle of the teapot */ if ( vert[nv][Z] > 1.5 ) { /* cusp at lid */ SET_COORD3( norm[nv], 0.0, 0.0, 1.0 ) ; } else { /* cusp at bottom */ SET_COORD3( norm[nv], 0.0, 0.0, -1.0 ) ; } } return( true ) ; } void points_from_basis(int tot_vert, double s[], double t[], double mgm[3][4][4], double vert[][3], double norm[][3]) { int i, num_vert, p; double sval, tval, dsval, dtval, sxyz, txyz; double sdir[3]; double tdir[3]; double sp[4]; double tp[4]; double dsp[4]; double dtp[4]; double tcoord[4]; for ( num_vert = 0 ; num_vert < tot_vert ; num_vert++ ) { sxyz = s[num_vert] ; txyz = t[num_vert] ; /* get power vectors and their derivatives */ for ( p = 4, sval = tval = 1.0 ; p-- ; ) { sp[p] = sval ; tp[p] = tval ; sval *= sxyz ; tval *= txyz ; if ( p == 3 ) { dsp[p] = dtp[p] = 0.0 ; dsval = dtval = 1.0 ; } else { dsp[p] = dsval * (double)(3-p) ; dtp[p] = dtval * (double)(3-p) ; dsval *= sxyz ; dtval *= txyz ; } } /* do for x,y,z */ for ( i = 0 ; i < 3 ; i++ ) { /* multiply power vectors times matrix to get value */ transform_coord( tcoord, sp, mgm[i] ) ; vert[num_vert][i] = DOT4( tcoord, tp ) ; /* get s and t tangent vectors */ transform_coord( tcoord, dsp, mgm[i] ) ; sdir[i] = DOT4( tcoord, tp ) ; transform_coord( tcoord, sp, mgm[i] ) ; tdir[i] = DOT4( tcoord, dtp ) ; } /* find normal */ CROSS( norm[num_vert], tdir, sdir ) ; (void)normalize_vector( norm[num_vert] ) ; } } // // Inline. // inline void CROSS(double *r, double *a, double *b) { r[X] = a[Y] * b[Z] - a[Z] * b[Y]; r[Y] = a[Z] * b[X] - a[X] * b[Z]; r[Z] = a[X] * b[Y] - a[Y] * b[X]; } inline double DOT4(double *a, double *b) { return a[X] * b[X] + a[Y] * b[Y] + a[Z] * b[Z] + a[W] * b[W]; } inline boolean IS_VAL_ALMOST_ZERO(double A, double E) { return ( (A) < 0 ? -(A) : (A) ) <= (E); } inline void SET_COORD3(double *r, double A, double B, double C) { r[X] = A; r[Y] = B; r[Z] = C; } inline double DOT_PRODUCT(double *a, double *b) { return a[X] * b[X] + a[Y] * b[Y] + a[Z] * b[Z]; } }; int main(int argc, char *argv[]) { GoGlutInterface::init(&argc, argv); GoGlutInterface::windowSize(250, 250); new GoTeapot(); GoGlutInterface::mainLoop(); return(0); }