View difference between Paste ID: eWDtdgvm and
SHOW: | | - or go back to the newest paste.
1-
1+
#include <math.h>
2
#include <stdio.h>
3
#include <GL/glut.h>
4
#include "GluCylinders.h"
5
6
// There's no real need to comment includes.
7
// What a include supplies normally is obvious from the file name
8
9
10
void animate(float t, float&, float&, float&);
11
12
void renderCylinder(float x1, float y1, float z1,
13
                    float x2,float y2, float z2,
14
                    float radius, int subdivisions,
15
                    GLUquadricObj *quadric);
16
17
void renderCylinder_convenient(float x1, float y1, float z1,
18
                               float x2,float y2, float z2,
19
                               float radius,int subdivisions);
20
21
// The next global variable controls the animation's state and speed.
22
float RotateAngle = 0.0f;		// Angle in degrees of rotation around y-axis
23
float Azimuth = 0.0;			// Rotated up or down by this amount
24
float AngleStepSize = 3.0f;		// Step three degrees at a time
25
const float AngleStepMax = 10.0f;
26
const float AngleStepMin = 0.1f;
27
28
int WireFrameOn = 1;			// == 1 for wire frame mode
29
30
//points
31
// I would not call this geometry but control points...
32
float Geometry[9][3] = {
33
	{ 4,2.0,0},
34
	{ 4,2.0,0},	// Point1
35
	{-1.5,0.2,0},                            
36
37
	{-2,0.3,0},                               
38
	{-2.5,0.6,0},
39
40
	{-3,0.8,0},                              
41
   
42
	{-3.5,1.0,0},
43
	{ -5.5,1.8,0}, //point 2
44
	{ -5.5,1.8,0}
45
	
46
};
47
48
int x2[5],y2[5],z2[5];
49
50
// LOD? Level of Detail? Length of Delay?
51
// This is a case where a comment makes sense: Explaining abbreviations.
52
// unsigned int LOD=20; 
53
54
void myKeyboardFunc( unsigned char key, int x, int y )
55
{
56
	switch ( key ) {
57
	case 'w':
58
		WireFrameOn = 1-WireFrameOn;
59
		glutPostRedisplay();
60
		break;
61
	case 'R':
62
		AngleStepSize *= 1.5;
63
		if (AngleStepSize>AngleStepMax ) {
64
			AngleStepSize = AngleStepMax;
65
		}
66
		break;
67
	case 'r':
68
		AngleStepSize /= 1.5;
69
		if (AngleStepSize<AngleStepMin ) {
70
			AngleStepSize = AngleStepMin;
71
		}
72
		break;
73
	case 27:	// Escape key
74
		exit(1);
75
	}
76
}
77
78
// glutSpecialFunc is called below to set this function to handle
79
//		all "special" key presses.  See glut.h for the names of
80
//		special keys.
81
void mySpecialKeyFunc( int key, int x, int y )
82
{
83
	switch ( key ) {
84
	case GLUT_KEY_UP:		
85
		Azimuth += AngleStepSize;
86
		if ( Azimuth>80.0f ) {
87
			Azimuth = 80.0f;
88
		}
89
		break;
90
	case GLUT_KEY_DOWN:
91
		Azimuth -= AngleStepSize;
92
		if ( Azimuth < -80.0f ) {
93
			Azimuth = -80.0f;
94
		}
95
		break;
96
	case GLUT_KEY_LEFT:
97
		RotateAngle += AngleStepSize;
98
		if ( RotateAngle > 180.0f ) {
99
			RotateAngle -= 360.0f;
100
		}
101
		break;
102
	case GLUT_KEY_RIGHT:
103
		
104
		RotateAngle -= AngleStepSize;
105
		if ( RotateAngle < -180.0f ) {
106
			RotateAngle += 360.0f;
107
			
108
		}
109
		break;
110
	}
111
	glutPostRedisplay();
112
113
}
114
/*
115
 * drawScene() handles the animation and the redrawing of the
116
 *		graphics window contents.
117
 */
118
void drawScene(void)
119
{
120
	// Those should not be a drawScene static, but part of
121
	// a scene management structure. Which your code lacks,
122
	// unfortunately, and I'm not gonna introduce one.
123
	static float animation_time = 0.;
124
	static int j = 1; // why 1 indexed? This is not Lua
125
126
	if ( WireFrameOn ) {
127
		glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE ); // Just show wireframes
128
	} else {
129
		glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL ); // Show solid polygons
130
	}
131
132
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
133
	glEnable(GL_DEPTH_TEST);
134
135
	
136
	glMatrixMode( GL_MODELVIEW );
137
	glLoadIdentity();
138
139
	glTranslatef( -0.5, 0.0, -35.0 );
140
	glRotatef( RotateAngle, 0.0, 1.0, 0.0 );
141
	glRotatef( Azimuth, 1.0, 0.0, 0.0 );
142
143
// Please, don't /code/ your geometry, it's ugly and unmaintainable. I omit that code here
144
// (...)
145
146
147
	// Okay, I can just guess here, but it looks like you're intending to draw 
148
	// a trace of the sphere as it moves around. I have no idea what that j
149
	// loop is meant for, though. But I guess you want to show the control points,
150
	// one after another. This another case _FOR_ comments: Explaining the idea of
151
	// the overall scheme. Don't write in a comment what a single statement does. I
152
	// can see that from the statement.
153
154
	// use the parametric time value 0 to current animation time.
155
	float x3, y3, z3;
156
157
	// first draw the trace
158
	glBegin(GL_LINE_STRIP);
159
	for(float t = 0; t < animation_time; t+=0.05) {
160
		animate(t, x3, y3, z3);
161
		glVertex3f( x3,y3,z3 );
162
	}
163
	glEnd();
164
165
	// Then draw the control point markers
166
	glColor3f(1,1,0);
167
	for(float t = 0; t < animation_time; t+=0.05) {
168
		animate(t, x3, y3, z3);
169
		renderCylinder_convenient(
170
			Geometry[j][0],Geometry[j][1],Geometry[j][2],
171
			x3,y3,z3,
172
			0.3, 32); 
173
	}
174
175
	// Last but not least draw sphere at the position for animation_time.
176
	animate(animation_time, x3, y3, z3);
177
	glutDrawSphere(...);
178
179
	// now, we want to play that animation a few times in 
180
	// succession, but with different control points visible
181
	// or so I presume so after each animation time has reached 1
182
	// we increment the control point counter. And after that hit
183
	// its maximum we stop advancing the animation
184
185
	if(j<3) {
186
		if(animation_time < 1.0) {
187
			// Animation step should be a measured
188
			// value. However in case of your simple
189
			// graphics and in the case of v-synced
190
			// buffer swap, and the prevalence of LCD
191
			// screens updating at 60Hz we can make this
192
			// a constant:
193
			// One frame is 1/60th of a second and we
194
			// want to take the animation 5 seconds to
195
			// play:
196
			float animation_step = (1./60.) / (5.);
197
198
			animation_time += animation_step;
199
		} else {
200
			animation_time = 0.;
201
			j++;
202
		}
203
	}
204
205
	glutSwapBuffers();
206
}
207
208
209
// Called when the window is resized
210
//		w, h - width and height of the window in pixels.
211
void resizeWindow(int w, int h)
212
{
213
	double aspectRatio;
214
215
	// Technically all this should be done in the display function!
216
217
	// Define the portion of the window used for OpenGL rendering.
218
	glViewport( 0, 0, w, h );	// View port uses whole window
219
220
	// Set up the projection view matrix: perspective projection
221
	// Determine the min and max values for x and y that should appear in the window.
222
	// The complication is that the aspect ratio of the window may not match the
223
	//		aspect ratio of the scene we want to view.
224
	w = (w==0) ? 1 : w;
225
	h = (h==0) ? 1 : h;
226
	aspectRatio = (double)w / (double)h;
227
228
	glMatrixMode( GL_PROJECTION );
229
	glLoadIdentity();
230
	gluPerspective( 15.0, aspectRatio, 25.0, 45.0 );
231
232
}
233
234
235
// Main routine
236
// Set up OpenGL, define the callbacks and start the main loop
237
int main( int argc, char** argv )
238
{
239
	glutInit(&argc, argv);
240
241
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
242
243
	glutInitWindowPosition( 10, 60 );
244
	glutInitWindowSize( 360, 360 );
245
	glutCreateWindow( "GluCylinders" );
246
247
	glutKeyboardFunc( myKeyboardFunc );
248
	glutSpecialFunc( mySpecialKeyFunc );
249
250
	glutReshapeFunc( resizeWindow );
251
252
	glutIdleFunc( glutPostRedisplay ); // when idle -> redraw
253
254
	glutDisplayFunc( drawScene );
255
256
	fprintf(stdout, "Arrow keys control viewpoint.\n");
257
	fprintf(stdout, "Press \"w\" to toggle wireframe mode.\n");
258
	fprintf(stdout, "Press \"R\" or \"r\" to increase or decrease rate of movement (respectively).\n");
259
	
260
	// Start the main loop.  glutMainLoop never returns.
261
	glutMainLoop(  );
262
263
	return 0;
264
}
265
266
GLUquadricObj* myReusableQuadric = 0;
267
268
void drawGluCylinder( double height, double radius, int slices, int stacks ) {
269
	drawGluSlantCylinder( height, radius, radius, slices, stacks );
270
}
271
272
void drawGluSlantCylinder( double height, double radiusBase, double radiusTop, int slices, int stacks )
273
{
274
	if ( ! myReusableQuadric ) {
275
		myReusableQuadric = gluNewQuadric();  
276
		// Should (but don't) check if pointer is still null --- to catch memory allocation errors.
277
		gluQuadricNormals( myReusableQuadric, GL_TRUE );
278
	}
279
	// Draw the cylinder.
280
	gluCylinder( myReusableQuadric, radiusBase, radiusTop, height, slices, stacks );
281
}
282
283
284
void drawGluCylinderWithCaps( double height, double radius, int slices, int stacks ) {
285
	drawGluSlantCylinderWithCaps( height, radius, radius, slices, stacks );
286
}
287
288
289
// animate shall calculate the new position for the next
290
// render iteration. Don't do delays, busy loops and drawing
291
// stuff here.
292
void animate(float t, float &x3, float &y3, float &z3)
293
{
294
	// I don't see it in this mess, but I
295
	// assume this is some kind of spline
296
	// interpolation, right?
297
298
	x3 = 0.5*((-Geometry[j-1][0] + 3*Geometry[j][0]  -3*Geometry[j+1][0] + Geometry[j+2][0])*t*t*t + (2*Geometry[j-1][0] -5*Geometry[j][0] +4*Geometry[j+1][0] -Geometry[j+2][0])*t*t + (-Geometry[j-1][0] + Geometry[j+1][0])*t + 2*Geometry[j][0]);
299
300
	y3 = 0.5*((-Geometry[j-1][1] + 3*Geometry[j][1]  -3*Geometry[j+1][1] + Geometry[j+2][1])*t*t*t+ (2*Geometry[j-1][1] -5*Geometry[j][1] +4*Geometry[j+1][1] -Geometry[j+2][1])*t*t +(-Geometry[j-1][1] + Geometry[j+1][1])*t + 2*Geometry[j][1]);
301
302
			
303
304
	z3 = 0.5*((-Geometry[j-1][2] + 3*Geometry[j][2]  -3*Geometry[j+1][2] + Geometry[j+2][2])*t*t*t + (2*Geometry[j-1][2] -5*Geometry[j][2] +4*Geometry[j+1][2] -Geometry[j+2][2])*t*t +(-Geometry[j-1][2] + Geometry[j+1][2])*t + 2*Geometry[j][2]);
305
306
}
307
308
void renderCylinder(float x1, float y1, float z1, float x2,float y2, float z2, float radius,int subdivisions,GLUquadricObj *quadric)
309
{
310
	float v,rx,ry,ax,vx = x2-x1;   
311
	float vy = y2-y1;   
312
	float vz = z2-z1;   //handle the degenerate case of z1 == z2 with an approximation   
313
314
	if(vz == 0)       
315
		vz =.00000001;   
316
317
	v = sqrt( vx*vx + vy*vy + vz*vz );  
318
	ax = 57.2957795*acos( vz/v );   
319
320
	if ( vz < 0.0 )       
321
		ax = -ax;   
322
	
323
	rx = -vy*vz;   
324
	ry = vx*vz;   
325
326
	glPushMatrix();   //draw the cylinder body   
327
	glTranslatef( x1,y1,z1 );   
328
	glRotatef(ax, rx, ry, 0.0);  
329
	gluQuadricOrientation(quadric,GLU_OUTSIDE);   
330
	gluCylinder(quadric, radius, radius, v, subdivisions, 1);   //draw the first cap   
331
	gluQuadricOrientation(quadric,GLU_INSIDE);  
332
	gluDisk( quadric, 0.0, radius, subdivisions, 1);   
333
	glTranslatef( 0,0,v );   //draw the second cap   
334
	gluQuadricOrientation(quadric,GLU_OUTSIDE);  
335
	gluDisk( quadric, 0.0, radius, subdivisions, 1);  
336
	glPopMatrix();
337
}
338
339
void renderCylinder_convenient(
340
	float x1, float y1, float z1,
341
	float x2,float y2, float z2,
342
	float radius,int subdivisions)
343
{   
344
	//the same quadric can be re-used for drawing many cylinders
345
346
	// Instead of quadrics and coding your geometry you should
347
	// just import a 3D model and render that. It's easier and 
348
	// allows for more artistic freedom. Yes, Yes, I know, your
349
	// teachers assigment; seriously, I'd tell a teacher demanding
350
	// this to f*** himself.
351
352
	GLUquadricObj *quadric=gluNewQuadric();  
353
	gluQuadricNormals(quadric, GLU_SMOOTH);   
354
	renderCylinder(x1,y1,z1,x2,y2,z2,radius,subdivisions,quadric);   
355
	gluDeleteQuadric(quadric);}
356
357
358
void drawGluSlantCylinderWithCaps(
359
	double height, double radiusBase, double radiusTop,
360
	int slices, int stacks )
361
{
362
	// First draw the cylinder
363
	drawGluSlantCylinder( height, radiusBase, radiusTop, slices, stacks );
364
365
	// Draw the top disk cap
366
	glPushMatrix();
367
	glTranslated(0.0, 0.0, height);
368
	gluDisk( myReusableQuadric, 0.0, radiusTop, slices, stacks );
369
	glPopMatrix();
370
371
	// Draw the bottom disk cap
372
	glPushMatrix();
373
	glRotated(180.0, 1.0, 0.0, 0.0);
374
	gluDisk( myReusableQuadric, 0.0, radiusBase, slices, stacks );
375
	glPopMatrix();
376
377
}