132001f49Smrg/*
232001f49Smrg * Copyright (c) 1991, 1992, 1993 Silicon Graphics, Inc.
332001f49Smrg *
432001f49Smrg * Permission to use, copy, modify, distribute, and sell this software and
532001f49Smrg * its documentation for any purpose is hereby granted without fee, provided
632001f49Smrg * that (i) the above copyright notices and this permission notice appear in
732001f49Smrg * all copies of the software and related documentation, and (ii) the name of
832001f49Smrg * Silicon Graphics may not be used in any advertising or
932001f49Smrg * publicity relating to the software without the specific, prior written
1032001f49Smrg * permission of Silicon Graphics.
1132001f49Smrg *
1232001f49Smrg * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF
1332001f49Smrg * ANY KIND,
1432001f49Smrg * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
1532001f49Smrg * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
1632001f49Smrg *
1732001f49Smrg * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR
1832001f49Smrg * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
1932001f49Smrg * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2032001f49Smrg * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
2132001f49Smrg * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2232001f49Smrg * OF THIS SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg#include <stdio.h>
2632001f49Smrg#include <stdlib.h>
2732001f49Smrg#include <math.h>
2832001f49Smrg#include <string.h>
2932001f49Smrg#include <time.h>
3032001f49Smrg#include "glut_wrap.h"
3132001f49Smrg
3232001f49Smrg
3332001f49Smrg#define MAXOBJS 10000
3432001f49Smrg#define MAXSELECT 100
3532001f49Smrg#define MAXFEED 300
3632001f49Smrg#define	SOLID 1
3732001f49Smrg#define	LINE 2
3832001f49Smrg#define	POINT 3
3932001f49Smrg
4032001f49Smrg
4132001f49SmrgGLint windW, windH;
4232001f49Smrg
4332001f49SmrgGLuint selectBuf[MAXSELECT];
4432001f49SmrgGLfloat feedBuf[MAXFEED];
4532001f49SmrgGLint vp[4];
4632001f49Smrgfloat zRotation = 90.0;
4732001f49Smrgfloat zoom = 1.0;
4832001f49SmrgGLint objectCount;
4932001f49SmrgGLint numObjects;
5032001f49Smrgstruct object {
5132001f49Smrg    float v1[2];
5232001f49Smrg    float v2[2];
5332001f49Smrg    float v3[2];
5432001f49Smrg    float color[3];
5532001f49Smrg} objects[MAXOBJS];
5632001f49SmrgGLenum linePoly = GL_FALSE;
5732001f49Smrg
5832001f49Smrg
5932001f49Smrgstatic void InitObjects(GLint num)
6032001f49Smrg{
6132001f49Smrg    GLint i;
6232001f49Smrg    float x, y;
6332001f49Smrg
6432001f49Smrg    if (num > MAXOBJS) {
6532001f49Smrg	num = MAXOBJS;
6632001f49Smrg    }
6732001f49Smrg    if (num < 1) {
6832001f49Smrg	num = 1;
6932001f49Smrg    }
7032001f49Smrg    objectCount = num;
7132001f49Smrg
7232001f49Smrg    srand((unsigned int)time(NULL));
7332001f49Smrg    for (i = 0; i < num; i++) {
7432001f49Smrg	x = (rand() % 300) - 150;
7532001f49Smrg	y = (rand() % 300) - 150;
7632001f49Smrg
7732001f49Smrg	objects[i].v1[0] = x + (rand() % 50) - 25;
7832001f49Smrg	objects[i].v2[0] = x + (rand() % 50) - 25;
7932001f49Smrg	objects[i].v3[0] = x + (rand() % 50) - 25;
8032001f49Smrg	objects[i].v1[1] = y + (rand() % 50) - 25;
8132001f49Smrg	objects[i].v2[1] = y + (rand() % 50) - 25;
8232001f49Smrg	objects[i].v3[1] = y + (rand() % 50) - 25;
8332001f49Smrg	objects[i].color[0] = ((rand() % 100) + 50) / 150.0;
8432001f49Smrg	objects[i].color[1] = ((rand() % 100) + 50) / 150.0;
8532001f49Smrg	objects[i].color[2] = ((rand() % 100) + 50) / 150.0;
8632001f49Smrg    }
8732001f49Smrg}
8832001f49Smrg
8932001f49Smrgstatic void Init(void)
9032001f49Smrg{
9132001f49Smrg
9232001f49Smrg    numObjects = 10;
9332001f49Smrg    InitObjects(numObjects);
9432001f49Smrg    glGetIntegerv(GL_VIEWPORT, vp);
9532001f49Smrg
9632001f49Smrg#if 0 /* debug - test culling */
9732001f49Smrg    glCullFace(GL_BACK);
9832001f49Smrg    glFrontFace(GL_CW);
9932001f49Smrg    glEnable(GL_CULL_FACE);
10032001f49Smrg#endif
10132001f49Smrg}
10232001f49Smrg
10332001f49Smrgstatic void Reshape(int width, int height)
10432001f49Smrg{
10532001f49Smrg
10632001f49Smrg    windW = (GLint)width;
10732001f49Smrg    windH = (GLint)height;
10832001f49Smrg}
10932001f49Smrg
11032001f49Smrgstatic void Render(GLenum mode)
11132001f49Smrg{
11232001f49Smrg    GLint i;
11332001f49Smrg
11432001f49Smrg    for (i = 0; i < objectCount; i++) {
11532001f49Smrg	if (mode == GL_SELECT) {
11632001f49Smrg	    glLoadName(i);
11732001f49Smrg	}
11832001f49Smrg	glColor3fv(objects[i].color);
11932001f49Smrg	glBegin(GL_POLYGON);
12032001f49Smrg	    glVertex2fv(objects[i].v1);
12132001f49Smrg	    glVertex2fv(objects[i].v2);
12232001f49Smrg	    glVertex2fv(objects[i].v3);
12332001f49Smrg	glEnd();
12432001f49Smrg    }
12532001f49Smrg}
12632001f49Smrg
12732001f49Smrgstatic GLint DoSelect(GLint x, GLint y)
12832001f49Smrg{
12932001f49Smrg    GLint hits;
13032001f49Smrg
13132001f49Smrg    glSelectBuffer(MAXSELECT, selectBuf);
13232001f49Smrg    (void)glRenderMode(GL_SELECT);
13332001f49Smrg    glInitNames();
13432001f49Smrg    glPushName(~0);
13532001f49Smrg
13632001f49Smrg    glPushMatrix();
13732001f49Smrg
13832001f49Smrg    glViewport(0, 0, windW, windH);
13932001f49Smrg    glGetIntegerv(GL_VIEWPORT, vp);
14032001f49Smrg
14132001f49Smrg    glMatrixMode(GL_PROJECTION);
14232001f49Smrg    glLoadIdentity();
14332001f49Smrg    gluPickMatrix(x, windH-y, 4, 4, vp);
14432001f49Smrg    gluOrtho2D(-175, 175, -175, 175);
14532001f49Smrg    glMatrixMode(GL_MODELVIEW);
14632001f49Smrg
14732001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
14832001f49Smrg    glClear(GL_COLOR_BUFFER_BIT);
14932001f49Smrg
15032001f49Smrg    glScalef(zoom, zoom, zoom);
15132001f49Smrg    glRotatef(zRotation, 0, 0, 1);
15232001f49Smrg
15332001f49Smrg    Render(GL_SELECT);
15432001f49Smrg
15532001f49Smrg    glPopMatrix();
15632001f49Smrg
15732001f49Smrg    hits = glRenderMode(GL_RENDER);
15832001f49Smrg    if (hits <= 0) {
15932001f49Smrg	return -1;
16032001f49Smrg    }
16132001f49Smrg
16232001f49Smrg    return selectBuf[(hits-1)*4+3];
16332001f49Smrg}
16432001f49Smrg
16532001f49Smrgstatic void RecolorTri(GLint h)
16632001f49Smrg{
16732001f49Smrg
16832001f49Smrg    objects[h].color[0] = ((rand() % 100) + 50) / 150.0;
16932001f49Smrg    objects[h].color[1] = ((rand() % 100) + 50) / 150.0;
17032001f49Smrg    objects[h].color[2] = ((rand() % 100) + 50) / 150.0;
17132001f49Smrg}
17232001f49Smrg
17332001f49Smrgstatic void DeleteTri(GLint h)
17432001f49Smrg{
17532001f49Smrg
17632001f49Smrg    objects[h] = objects[objectCount-1];
17732001f49Smrg    objectCount--;
17832001f49Smrg}
17932001f49Smrg
18032001f49Smrgstatic void GrowTri(GLint h)
18132001f49Smrg{
18232001f49Smrg    float v[2];
18332001f49Smrg    float *oldV = NULL;
18432001f49Smrg    GLint i;
18532001f49Smrg
18632001f49Smrg    v[0] = objects[h].v1[0] + objects[h].v2[0] + objects[h].v3[0];
18732001f49Smrg    v[1] = objects[h].v1[1] + objects[h].v2[1] + objects[h].v3[1];
18832001f49Smrg    v[0] /= 3;
18932001f49Smrg    v[1] /= 3;
19032001f49Smrg
19132001f49Smrg    for (i = 0; i < 3; i++) {
19232001f49Smrg	switch (i) {
19332001f49Smrg	  case 0:
19432001f49Smrg	    oldV = objects[h].v1;
19532001f49Smrg	    break;
19632001f49Smrg	  case 1:
19732001f49Smrg	    oldV = objects[h].v2;
19832001f49Smrg	    break;
19932001f49Smrg	  case 2:
20032001f49Smrg	    oldV = objects[h].v3;
20132001f49Smrg	    break;
20232001f49Smrg	}
20332001f49Smrg	oldV[0] = 1.5 * (oldV[0] - v[0]) + v[0];
20432001f49Smrg	oldV[1] = 1.5 * (oldV[1] - v[1]) + v[1];
20532001f49Smrg    }
20632001f49Smrg}
20732001f49Smrg
20832001f49Smrgstatic void Mouse(int button, int state, int mouseX, int mouseY)
20932001f49Smrg{
21032001f49Smrg    GLint hit;
21132001f49Smrg
21232001f49Smrg    if (state != GLUT_DOWN)
21332001f49Smrg	return;
21432001f49Smrg
21532001f49Smrg    hit = DoSelect((GLint)mouseX, (GLint)mouseY);
21632001f49Smrg    if (hit != -1) {
21732001f49Smrg	if (button == GLUT_LEFT_BUTTON) {
21832001f49Smrg	    RecolorTri(hit);
21932001f49Smrg	}
22032001f49Smrg	if (button == GLUT_MIDDLE_BUTTON) {
22132001f49Smrg	    GrowTri(hit);
22232001f49Smrg	}
22332001f49Smrg	if (button == GLUT_RIGHT_BUTTON) {
22432001f49Smrg	    DeleteTri(hit);
22532001f49Smrg	}
22632001f49Smrg    }
22732001f49Smrg
22832001f49Smrg    glutPostRedisplay();
22932001f49Smrg}
23032001f49Smrg
23132001f49Smrgstatic void Draw(void)
23232001f49Smrg{
23332001f49Smrg
23432001f49Smrg    glPushMatrix();
23532001f49Smrg
23632001f49Smrg    glViewport(0, 0, windW, windH);
23732001f49Smrg    glGetIntegerv(GL_VIEWPORT, vp);
23832001f49Smrg
23932001f49Smrg    glMatrixMode(GL_PROJECTION);
24032001f49Smrg    glLoadIdentity();
24132001f49Smrg    gluOrtho2D(-175, 175, -175, 175);
24232001f49Smrg    glMatrixMode(GL_MODELVIEW);
24332001f49Smrg
24432001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
24532001f49Smrg    glClear(GL_COLOR_BUFFER_BIT);
24632001f49Smrg
24732001f49Smrg    glScalef(zoom, zoom, zoom);
24832001f49Smrg    glRotatef(zRotation, 0, 0, 1);
24932001f49Smrg
25032001f49Smrg    Render(GL_RENDER);
25132001f49Smrg
25232001f49Smrg    glPopMatrix();
25332001f49Smrg
25432001f49Smrg    glFlush();
25532001f49Smrg}
25632001f49Smrg
25732001f49Smrgstatic void DrawZoom(GLint x, GLint y)
25832001f49Smrg{
25932001f49Smrg
26032001f49Smrg    glPushMatrix();
26132001f49Smrg
26232001f49Smrg    glViewport(0, 0, windW, windH);
26332001f49Smrg    glGetIntegerv(GL_VIEWPORT, vp);
26432001f49Smrg
26532001f49Smrg    glMatrixMode(GL_PROJECTION);
26632001f49Smrg    glLoadIdentity();
26732001f49Smrg    gluPickMatrix(x, windH-y, 4, 4, vp);
26832001f49Smrg    gluOrtho2D(-175, 175, -175, 175);
26932001f49Smrg    glMatrixMode(GL_MODELVIEW);
27032001f49Smrg
27132001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
27232001f49Smrg    glClear(GL_COLOR_BUFFER_BIT);
27332001f49Smrg
27432001f49Smrg    glScalef(zoom, zoom, zoom);
27532001f49Smrg    glRotatef(zRotation, 0, 0, 1);
27632001f49Smrg
27732001f49Smrg    Render(GL_RENDER);
27832001f49Smrg
27932001f49Smrg    glPopMatrix();
28032001f49Smrg}
28132001f49Smrg
28232001f49Smrgstatic void DumpFeedbackVert(GLint *i, GLint n)
28332001f49Smrg{
28432001f49Smrg    GLint index;
28532001f49Smrg
28632001f49Smrg    index = *i;
28732001f49Smrg    if (index+7 > n) {
28832001f49Smrg	*i = n;
28932001f49Smrg	printf("  ???\n");
29032001f49Smrg	return;
29132001f49Smrg    }
29232001f49Smrg    printf("  (%g %g %g), color = (%4.2f %4.2f %4.2f)\n",
29332001f49Smrg	   feedBuf[index],
29432001f49Smrg	   feedBuf[index+1],
29532001f49Smrg	   feedBuf[index+2],
29632001f49Smrg	   feedBuf[index+3],
29732001f49Smrg	   feedBuf[index+4],
29832001f49Smrg	   feedBuf[index+5]);
29932001f49Smrg    index += 7;
30032001f49Smrg    *i = index;
30132001f49Smrg}
30232001f49Smrg
30332001f49Smrgstatic void DrawFeedback(GLint n)
30432001f49Smrg{
30532001f49Smrg    GLint i;
30632001f49Smrg    GLint verts;
30732001f49Smrg
30832001f49Smrg    printf("Feedback results (%d floats):\n", n);
30932001f49Smrg    for (i = 0; i < n; i++) {
31032001f49Smrg	switch ((GLint)feedBuf[i]) {
31132001f49Smrg	  case GL_POLYGON_TOKEN:
31232001f49Smrg	    printf("Polygon");
31332001f49Smrg	    i++;
31432001f49Smrg	    if (i < n) {
31532001f49Smrg		verts = (GLint)feedBuf[i];
31632001f49Smrg		i++;
31732001f49Smrg		printf(": %d vertices", verts);
31832001f49Smrg	    } else {
31932001f49Smrg		verts = 0;
32032001f49Smrg	    }
32132001f49Smrg	    printf("\n");
32232001f49Smrg	    while (verts) {
32332001f49Smrg		DumpFeedbackVert(&i, n);
32432001f49Smrg		verts--;
32532001f49Smrg	    }
32632001f49Smrg	    i--;
32732001f49Smrg	    break;
32832001f49Smrg	  case GL_LINE_TOKEN:
32932001f49Smrg	    printf("Line:\n");
33032001f49Smrg	    i++;
33132001f49Smrg	    DumpFeedbackVert(&i, n);
33232001f49Smrg	    DumpFeedbackVert(&i, n);
33332001f49Smrg	    i--;
33432001f49Smrg	    break;
33532001f49Smrg	  case GL_LINE_RESET_TOKEN:
33632001f49Smrg	    printf("Line Reset:\n");
33732001f49Smrg	    i++;
33832001f49Smrg	    DumpFeedbackVert(&i, n);
33932001f49Smrg	    DumpFeedbackVert(&i, n);
34032001f49Smrg	    i--;
34132001f49Smrg	    break;
34232001f49Smrg	  default:
34332001f49Smrg	    printf("%9.2f\n", feedBuf[i]);
34432001f49Smrg	    break;
34532001f49Smrg	}
34632001f49Smrg    }
34732001f49Smrg    if (i == MAXFEED) {
34832001f49Smrg	printf("...\n");
34932001f49Smrg    }
35032001f49Smrg    printf("\n");
35132001f49Smrg}
35232001f49Smrg
35332001f49Smrgstatic void DoFeedback(void)
35432001f49Smrg{
35532001f49Smrg    GLint x;
35632001f49Smrg
35732001f49Smrg    glFeedbackBuffer(MAXFEED, GL_3D_COLOR, feedBuf);
35832001f49Smrg    (void)glRenderMode(GL_FEEDBACK);
35932001f49Smrg
36032001f49Smrg    glPushMatrix();
36132001f49Smrg
36232001f49Smrg    glViewport(0, 0, windW, windH);
36332001f49Smrg    glGetIntegerv(GL_VIEWPORT, vp);
36432001f49Smrg
36532001f49Smrg    glMatrixMode(GL_PROJECTION);
36632001f49Smrg    glLoadIdentity();
36732001f49Smrg    gluOrtho2D(-175, 175, -175, 175);
36832001f49Smrg    glMatrixMode(GL_MODELVIEW);
36932001f49Smrg
37032001f49Smrg    glClearColor(0.0, 0.0, 0.0, 0.0);
37132001f49Smrg    glClear(GL_COLOR_BUFFER_BIT);
37232001f49Smrg
37332001f49Smrg    glScalef(zoom, zoom, zoom);
37432001f49Smrg    glRotatef(zRotation, 0, 0, 1);
37532001f49Smrg
37632001f49Smrg    Render(GL_FEEDBACK);
37732001f49Smrg
37832001f49Smrg    glPopMatrix();
37932001f49Smrg
38032001f49Smrg    x = glRenderMode(GL_RENDER);
38132001f49Smrg    if (x == -1) {
38232001f49Smrg	x = MAXFEED;
38332001f49Smrg    }
38432001f49Smrg
38532001f49Smrg    DrawFeedback((GLint)x);
38632001f49Smrg}
38732001f49Smrg
38832001f49Smrgstatic void Key2(int key, int x, int y)
38932001f49Smrg{
39032001f49Smrg    switch (key) {
39132001f49Smrg      case GLUT_KEY_LEFT:
39232001f49Smrg	zRotation += 0.5;
39332001f49Smrg	break;
39432001f49Smrg      case GLUT_KEY_RIGHT:
39532001f49Smrg	zRotation -= 0.5;
39632001f49Smrg	break;
39732001f49Smrg      default:
39832001f49Smrg	return;
39932001f49Smrg    }
40032001f49Smrg
40132001f49Smrg    glutPostRedisplay();
40232001f49Smrg}
40332001f49Smrg
40432001f49Smrgstatic void Key(unsigned char key, int x, int y)
40532001f49Smrg{
40632001f49Smrg    switch (key) {
40732001f49Smrg      case 27:
40832001f49Smrg	exit(1);
40932001f49Smrg      case 'Z':
41032001f49Smrg	zoom /= 0.75;
41132001f49Smrg	break;
41232001f49Smrg      case 'z':
41332001f49Smrg	zoom *= 0.75;
41432001f49Smrg	break;
41532001f49Smrg      case 'f':
41632001f49Smrg	DoFeedback();
41732001f49Smrg	break;
41832001f49Smrg      case 'd':
41932001f49Smrg	DrawZoom(x, y);
42032001f49Smrg	break;
42132001f49Smrg      case 'l':
42232001f49Smrg	linePoly = !linePoly;
42332001f49Smrg	if (linePoly) {
42432001f49Smrg	    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
42532001f49Smrg	} else {
42632001f49Smrg	    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
42732001f49Smrg	}
42832001f49Smrg	break;
42932001f49Smrg      default:
43032001f49Smrg	return;
43132001f49Smrg    }
43232001f49Smrg
43332001f49Smrg    glutPostRedisplay();
43432001f49Smrg}
43532001f49Smrg
43632001f49Smrgint main(int argc, char **argv)
43732001f49Smrg{
43832001f49Smrg    GLenum type;
43932001f49Smrg
44032001f49Smrg    glutInit(&argc, argv);
44132001f49Smrg
44232001f49Smrg    windW = 300;
44332001f49Smrg    windH = 300;
44432001f49Smrg    glutInitWindowPosition(0, 0); glutInitWindowSize( windW, windH);
44532001f49Smrg
44632001f49Smrg    type = GLUT_RGB | GLUT_SINGLE;
44732001f49Smrg    glutInitDisplayMode(type);
44832001f49Smrg
44932001f49Smrg    if (glutCreateWindow("Select Test") == GL_FALSE) {
45032001f49Smrg	exit(1);
45132001f49Smrg    }
45232001f49Smrg
45332001f49Smrg    Init();
45432001f49Smrg
45532001f49Smrg    glutReshapeFunc(Reshape);
45632001f49Smrg    glutKeyboardFunc(Key);
45732001f49Smrg    glutSpecialFunc(Key2);
45832001f49Smrg    glutMouseFunc(Mouse);
45932001f49Smrg    glutDisplayFunc(Draw);
46032001f49Smrg    glutMainLoop();
46132001f49Smrg	return 0;
46232001f49Smrg}
463