1 //
2 // Computergraphik I
3 // Prof. Dr. Juergen Doellner
4 // Sommersemester 2001
5 //
6 // Rahmenprogramm fuer Aufgabenzettel 4
7 //
8
9 // Stephan Brumme, 702544
10 // last changes: May 20, 2001
11
12 #include "cgtessellator.h"
13
14 // Function Makro
15 #if defined(__GNUC__) && !defined(__STRICT_ANSI__)
16 #define FUNC GLvoid(*)(...)
17 #elif defined(_MSC_VER)
18 #define FUNC void(__stdcall*)()
19 #else
20 #define FUNC GLvoid(*)()
21 #endif
22
23 // GLU tesselator globale Hilfsfunktionen
24
25 // Fehler abfangen
26 void CALLBACK error(GLenum err) {
27 cerr << gluErrorString(err) << endl;
28 }
29
30 // Schnitt von Kanten, nimmt keine Änderungen vor
31 void CALLBACK combineCallback(GLdouble coords[3],
32 GLdouble *vertex_data[4],
33 GLfloat weight[4], GLdouble **dataOut )
34 {
35 GLdouble* vertex = new GLdouble[3];
36 vertex[0] = coords[0];
37 vertex[1] = coords[1];
38 vertex[2] = coords[2];
39 *dataOut = vertex;
40 }
41
42 // stellt Ecke dar
43 void CALLBACK vertexCallback(GLvoid *vertex)
44 {
45 glVertex3dv((GLdouble*)vertex);
46 }
47
48 // beginnt ein Primitv
49 void CALLBACK beginCallback(GLenum which)
50 {
51 glBegin(which);
52 }
53
54 // beendet ein Primitiv
55 void CALLBACK endCallback()
56 {
57 glEnd();
58 }
59
60
61 // CGTessellator
62 CGTessellator::CGTessellator() {
63 // Anlegen des TessObj
64 tobj_ = gluNewTess();
65 gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD);
66
67 // Datenstruktur initialisieren
68 pos_ = 0;
69 contours_ = 1;
70 contourSize_[0] = 0;
71 }
72
73 CGTessellator::~CGTessellator() {
74 // Zerstoeren des TessObj
75 gluDeleteTess(tobj_);
76 }
77
78 // Setze Punkte fuer einen Stern
79 void CGTessellator::defineStar() {
80 // 5 Punkte insgesamt
81 pos_ = 5;
82 // 1 Kontur
83 contours_ = 1;
84 // diese Kontur enthält alle bisher definierten Punkte
85 contourSize_[0] = 5;
86 pts_[0] = Point(150.0, 150.0);
87 pts_[1] = Point(225.0, 300.0);
88 pts_[2] = Point(300.0, 150.0);
89 pts_[3] = Point(150.0, 250.0);
90 pts_[4] = Point(300.0, 250.0);
91
92 // Stern zeichnen
93 glutPostRedisplay();
94 }
95
96 void CGTessellator::onInit() {
97 glClearColor(1, 1, 1, 1);
98
99 // festlegen der Vertex, Begin, End und Error Callback
100 // Beispiel: Combine Callback, Achtung: FUNC-Cast!
101 gluTessCallback(tobj_, GLU_TESS_COMBINE, (FUNC) &combineCallback);
102 gluTessCallback(tobj_, GLU_TESS_VERTEX, (FUNC) &vertexCallback);
103
104
105 gluTessCallback(tobj_, GLU_TESS_BEGIN, (FUNC) &beginCallback);
106 gluTessCallback(tobj_, GLU_TESS_END, (FUNC) &endCallback);
107
108 gluTessCallback(tobj_, GLU_TESS_ERROR, (FUNC) &error);
109 }
110
111 void CGTessellator::drawPolygon() {
112 gluTessBeginPolygon(tobj_, NULL);
113
114 // alle Punkte durchlaufen
115 int nVertexPtr = 0;
116
117 // alle Polygone
118 for (int nContour = 0; nContour < contours_; nContour++)
119 {
120 gluTessBeginContour(tobj_);
121
122 // alle Eckpunkte eines Polygons
123 for (int nVertex=0; nVertex<contourSize_[nContour]; nVertex++)
124 {
125 gluTessVertex(tobj_, pts_[nVertexPtr].dta_, pts_[nVertexPtr].dta_);
126 nVertexPtr++;
127 }
128
129 gluTessEndContour(tobj_);
130 }
131 gluTessEndPolygon(tobj_);
132 // Tessellation des Polygons mit GLU-Routinen
133 }
134
135 void CGTessellator::onDraw() {
136 glClear(GL_COLOR_BUFFER_BIT);
137
138 // Zeichnen des Polygons (blau)
139 glColor3f(0.5,0.5,1);
140 drawPolygon();
141
142 // Zeichnen des Polygon-Randes (schwarz), benutzt erneut Tessellator
143 glColor3f(0,0,0);
144 gluTessProperty(tobj_, GLU_TESS_BOUNDARY_ONLY, GL_TRUE);
145 drawPolygon();
146 gluTessProperty(tobj_, GLU_TESS_BOUNDARY_ONLY, GL_FALSE);
147
148 // Zeichnen der Eckpunkte (rot)
149 glPointSize(4);
150 glColor3d(1,0,0);
151
152 glBegin(GL_POINTS);
153 for (int i = 0; i < pos_; i++)
154 glVertex2dv(pts_[i].dta_);
155 glEnd();
156
157 // tauschen wie im Swingerclub
158 swapBuffers();
159 }
160
161 void CGTessellator::onSize(unsigned int newWidth, unsigned int newHeight) {
162 glClear(GL_COLOR_BUFFER_BIT);
163 glViewport(0, 0, newWidth - 1, newHeight - 1);
164
165 glMatrixMode(GL_PROJECTION_MATRIX);
166 glLoadIdentity();
167 gluOrtho2D(0, newWidth-1, 0, newHeight-1);
168 glMatrixMode(GL_MODELVIEW_MATRIX);
169
170 }
171
172 void CGTessellator::onKey(unsigned char key) {
173 // Key Belegung
174 switch (key) {
175 // beenden
176 case 'q': exit(0); break;
177
178 // Stern zeichnen
179 case 's': defineStar(); break;
180
181 // neue Kontur beginnen
182 case 'k': contourSize_[contours_++] = 0; break;
183
184 // alle Punkte/Bildschirm löschen
185 case 'c': contours_ = 1;
186 contourSize_[0] = 0;
187 pos_ = 0;
188 break;
189
190 // Tessellationsalgorithmen
191 case '1': gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ODD); break;
192 case '2': gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO); break;
193 case '3': gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE); break;
194 case '4': gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NEGATIVE); break;
195 case '5': gluTessProperty(tobj_, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_ABS_GEQ_TWO); break;
196 }
197
198 // und neu zeichnen
199 glutPostRedisplay();
200 }
201
202 void CGTessellator::onButton(MouseButton button, MouseButtonEvent event,
203 int x, int y) {
204 // Punkt speichern
205 pts_[pos_] = Point(x, y);
206 contourSize_[contours_-1]++;
207 pos_++;
208
209 // und neu zeichnen
210 glutPostRedisplay();
211 }
212
213 int main(int argc, char* argv[]) {
214 CGTessellator tess;
215 tess.start(argc, argv, "CGTessellator, Stephan Brumme, 702544",
216 CGTessellator::ColorBuffer| CGTessellator::DoubleBuffer | CGTessellator::StencilBuffer,
217 200, 400, 400);
218 return(0);
219 }
220