1/* 2 * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc. 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and 5 * its documentation for any purpose is hereby granted without fee, provided 6 * that (i) the above copyright notices and this permission notice appear in 7 * all copies of the software and related documentation, and (ii) the name of 8 * Silicon Graphics may not be used in any advertising or 9 * publicity relating to the software without the specific, prior written 10 * permission of Silicon Graphics. 11 * 12 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF 13 * ANY KIND, 14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR 18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 22 * OF THIS SOFTWARE. 23 */ 24 25#include <stdio.h> 26#include <stdlib.h> 27#include <math.h> 28#include <string.h> 29#include <time.h> 30#include "glut_wrap.h" 31 32 33#define MAXOBJS 10000 34#define MAXSELECT 100 35#define MAXFEED 300 36#define SOLID 1 37#define LINE 2 38#define POINT 3 39 40 41GLint windW, windH; 42 43GLuint selectBuf[MAXSELECT]; 44GLfloat feedBuf[MAXFEED]; 45GLint vp[4]; 46float zRotation = 90.0; 47float zoom = 1.0; 48GLint objectCount; 49GLint numObjects; 50struct object { 51 float v1[2]; 52 float v2[2]; 53 float v3[2]; 54 float color[3]; 55} objects[MAXOBJS]; 56GLenum linePoly = GL_FALSE; 57 58 59static void InitObjects(GLint num) 60{ 61 GLint i; 62 float x, y; 63 64 if (num > MAXOBJS) { 65 num = MAXOBJS; 66 } 67 if (num < 1) { 68 num = 1; 69 } 70 objectCount = num; 71 72 srand((unsigned int)time(NULL)); 73 for (i = 0; i < num; i++) { 74 x = (rand() % 300) - 150; 75 y = (rand() % 300) - 150; 76 77 objects[i].v1[0] = x + (rand() % 50) - 25; 78 objects[i].v2[0] = x + (rand() % 50) - 25; 79 objects[i].v3[0] = x + (rand() % 50) - 25; 80 objects[i].v1[1] = y + (rand() % 50) - 25; 81 objects[i].v2[1] = y + (rand() % 50) - 25; 82 objects[i].v3[1] = y + (rand() % 50) - 25; 83 objects[i].color[0] = ((rand() % 100) + 50) / 150.0; 84 objects[i].color[1] = ((rand() % 100) + 50) / 150.0; 85 objects[i].color[2] = ((rand() % 100) + 50) / 150.0; 86 } 87} 88 89static void Init(void) 90{ 91 92 numObjects = 10; 93 InitObjects(numObjects); 94 glGetIntegerv(GL_VIEWPORT, vp); 95 96#if 0 /* debug - test culling */ 97 glCullFace(GL_BACK); 98 glFrontFace(GL_CW); 99 glEnable(GL_CULL_FACE); 100#endif 101} 102 103static void Reshape(int width, int height) 104{ 105 106 windW = (GLint)width; 107 windH = (GLint)height; 108} 109 110static void Render(GLenum mode) 111{ 112 GLint i; 113 114 for (i = 0; i < objectCount; i++) { 115 if (mode == GL_SELECT) { 116 glLoadName(i); 117 } 118 glColor3fv(objects[i].color); 119 glBegin(GL_POLYGON); 120 glVertex2fv(objects[i].v1); 121 glVertex2fv(objects[i].v2); 122 glVertex2fv(objects[i].v3); 123 glEnd(); 124 } 125} 126 127static GLint DoSelect(GLint x, GLint y) 128{ 129 GLint hits; 130 131 glSelectBuffer(MAXSELECT, selectBuf); 132 (void)glRenderMode(GL_SELECT); 133 glInitNames(); 134 glPushName(~0); 135 136 glPushMatrix(); 137 138 glViewport(0, 0, windW, windH); 139 glGetIntegerv(GL_VIEWPORT, vp); 140 141 glMatrixMode(GL_PROJECTION); 142 glLoadIdentity(); 143 gluPickMatrix(x, windH-y, 4, 4, vp); 144 gluOrtho2D(-175, 175, -175, 175); 145 glMatrixMode(GL_MODELVIEW); 146 147 glClearColor(0.0, 0.0, 0.0, 0.0); 148 glClear(GL_COLOR_BUFFER_BIT); 149 150 glScalef(zoom, zoom, zoom); 151 glRotatef(zRotation, 0, 0, 1); 152 153 Render(GL_SELECT); 154 155 glPopMatrix(); 156 157 hits = glRenderMode(GL_RENDER); 158 if (hits <= 0) { 159 return -1; 160 } 161 162 return selectBuf[(hits-1)*4+3]; 163} 164 165static void RecolorTri(GLint h) 166{ 167 168 objects[h].color[0] = ((rand() % 100) + 50) / 150.0; 169 objects[h].color[1] = ((rand() % 100) + 50) / 150.0; 170 objects[h].color[2] = ((rand() % 100) + 50) / 150.0; 171} 172 173static void DeleteTri(GLint h) 174{ 175 176 objects[h] = objects[objectCount-1]; 177 objectCount--; 178} 179 180static void GrowTri(GLint h) 181{ 182 float v[2]; 183 float *oldV = NULL; 184 GLint i; 185 186 v[0] = objects[h].v1[0] + objects[h].v2[0] + objects[h].v3[0]; 187 v[1] = objects[h].v1[1] + objects[h].v2[1] + objects[h].v3[1]; 188 v[0] /= 3; 189 v[1] /= 3; 190 191 for (i = 0; i < 3; i++) { 192 switch (i) { 193 case 0: 194 oldV = objects[h].v1; 195 break; 196 case 1: 197 oldV = objects[h].v2; 198 break; 199 case 2: 200 oldV = objects[h].v3; 201 break; 202 } 203 oldV[0] = 1.5 * (oldV[0] - v[0]) + v[0]; 204 oldV[1] = 1.5 * (oldV[1] - v[1]) + v[1]; 205 } 206} 207 208static void Mouse(int button, int state, int mouseX, int mouseY) 209{ 210 GLint hit; 211 212 if (state != GLUT_DOWN) 213 return; 214 215 hit = DoSelect((GLint)mouseX, (GLint)mouseY); 216 if (hit != -1) { 217 if (button == GLUT_LEFT_BUTTON) { 218 RecolorTri(hit); 219 } 220 if (button == GLUT_MIDDLE_BUTTON) { 221 GrowTri(hit); 222 } 223 if (button == GLUT_RIGHT_BUTTON) { 224 DeleteTri(hit); 225 } 226 } 227 228 glutPostRedisplay(); 229} 230 231static void Draw(void) 232{ 233 234 glPushMatrix(); 235 236 glViewport(0, 0, windW, windH); 237 glGetIntegerv(GL_VIEWPORT, vp); 238 239 glMatrixMode(GL_PROJECTION); 240 glLoadIdentity(); 241 gluOrtho2D(-175, 175, -175, 175); 242 glMatrixMode(GL_MODELVIEW); 243 244 glClearColor(0.0, 0.0, 0.0, 0.0); 245 glClear(GL_COLOR_BUFFER_BIT); 246 247 glScalef(zoom, zoom, zoom); 248 glRotatef(zRotation, 0, 0, 1); 249 250 Render(GL_RENDER); 251 252 glPopMatrix(); 253 254 glFlush(); 255} 256 257static void DrawZoom(GLint x, GLint y) 258{ 259 260 glPushMatrix(); 261 262 glViewport(0, 0, windW, windH); 263 glGetIntegerv(GL_VIEWPORT, vp); 264 265 glMatrixMode(GL_PROJECTION); 266 glLoadIdentity(); 267 gluPickMatrix(x, windH-y, 4, 4, vp); 268 gluOrtho2D(-175, 175, -175, 175); 269 glMatrixMode(GL_MODELVIEW); 270 271 glClearColor(0.0, 0.0, 0.0, 0.0); 272 glClear(GL_COLOR_BUFFER_BIT); 273 274 glScalef(zoom, zoom, zoom); 275 glRotatef(zRotation, 0, 0, 1); 276 277 Render(GL_RENDER); 278 279 glPopMatrix(); 280} 281 282static void DumpFeedbackVert(GLint *i, GLint n) 283{ 284 GLint index; 285 286 index = *i; 287 if (index+7 > n) { 288 *i = n; 289 printf(" ???\n"); 290 return; 291 } 292 printf(" (%g %g %g), color = (%4.2f %4.2f %4.2f)\n", 293 feedBuf[index], 294 feedBuf[index+1], 295 feedBuf[index+2], 296 feedBuf[index+3], 297 feedBuf[index+4], 298 feedBuf[index+5]); 299 index += 7; 300 *i = index; 301} 302 303static void DrawFeedback(GLint n) 304{ 305 GLint i; 306 GLint verts; 307 308 printf("Feedback results (%d floats):\n", n); 309 for (i = 0; i < n; i++) { 310 switch ((GLint)feedBuf[i]) { 311 case GL_POLYGON_TOKEN: 312 printf("Polygon"); 313 i++; 314 if (i < n) { 315 verts = (GLint)feedBuf[i]; 316 i++; 317 printf(": %d vertices", verts); 318 } else { 319 verts = 0; 320 } 321 printf("\n"); 322 while (verts) { 323 DumpFeedbackVert(&i, n); 324 verts--; 325 } 326 i--; 327 break; 328 case GL_LINE_TOKEN: 329 printf("Line:\n"); 330 i++; 331 DumpFeedbackVert(&i, n); 332 DumpFeedbackVert(&i, n); 333 i--; 334 break; 335 case GL_LINE_RESET_TOKEN: 336 printf("Line Reset:\n"); 337 i++; 338 DumpFeedbackVert(&i, n); 339 DumpFeedbackVert(&i, n); 340 i--; 341 break; 342 default: 343 printf("%9.2f\n", feedBuf[i]); 344 break; 345 } 346 } 347 if (i == MAXFEED) { 348 printf("...\n"); 349 } 350 printf("\n"); 351} 352 353static void DoFeedback(void) 354{ 355 GLint x; 356 357 glFeedbackBuffer(MAXFEED, GL_3D_COLOR, feedBuf); 358 (void)glRenderMode(GL_FEEDBACK); 359 360 glPushMatrix(); 361 362 glViewport(0, 0, windW, windH); 363 glGetIntegerv(GL_VIEWPORT, vp); 364 365 glMatrixMode(GL_PROJECTION); 366 glLoadIdentity(); 367 gluOrtho2D(-175, 175, -175, 175); 368 glMatrixMode(GL_MODELVIEW); 369 370 glClearColor(0.0, 0.0, 0.0, 0.0); 371 glClear(GL_COLOR_BUFFER_BIT); 372 373 glScalef(zoom, zoom, zoom); 374 glRotatef(zRotation, 0, 0, 1); 375 376 Render(GL_FEEDBACK); 377 378 glPopMatrix(); 379 380 x = glRenderMode(GL_RENDER); 381 if (x == -1) { 382 x = MAXFEED; 383 } 384 385 DrawFeedback((GLint)x); 386} 387 388static void Key2(int key, int x, int y) 389{ 390 switch (key) { 391 case GLUT_KEY_LEFT: 392 zRotation += 0.5; 393 break; 394 case GLUT_KEY_RIGHT: 395 zRotation -= 0.5; 396 break; 397 default: 398 return; 399 } 400 401 glutPostRedisplay(); 402} 403 404static void Key(unsigned char key, int x, int y) 405{ 406 switch (key) { 407 case 27: 408 exit(1); 409 case 'Z': 410 zoom /= 0.75; 411 break; 412 case 'z': 413 zoom *= 0.75; 414 break; 415 case 'f': 416 DoFeedback(); 417 break; 418 case 'd': 419 DrawZoom(x, y); 420 break; 421 case 'l': 422 linePoly = !linePoly; 423 if (linePoly) { 424 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 425 } else { 426 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 427 } 428 break; 429 default: 430 return; 431 } 432 433 glutPostRedisplay(); 434} 435 436int main(int argc, char **argv) 437{ 438 GLenum type; 439 440 glutInit(&argc, argv); 441 442 windW = 300; 443 windH = 300; 444 glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH); 445 446 type = GLUT_RGB | GLUT_SINGLE; 447 glutInitDisplayMode(type); 448 449 if (glutCreateWindow("Select Test") == GL_FALSE) { 450 exit(1); 451 } 452 453 Init(); 454 455 glutReshapeFunc(Reshape); 456 glutKeyboardFunc(Key); 457 glutSpecialFunc(Key2); 458 glutMouseFunc(Mouse); 459 glutDisplayFunc(Draw); 460 glutMainLoop(); 461 return 0; 462} 463