ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/libgender/entity.C
Revision: 1.62
Committed: Thu Nov 4 15:43:53 2004 UTC (19 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.61: +2 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include <cassert>
2 #include <cstdlib>
3 #include <algorithm>
4
5 using namespace std;
6
7 #include "opengl.h"
8
9 #include "util.h"
10 #include "entity.h"
11 #include "oct.h"
12 #include "view.h"
13
14 /////////////////////////////////////////////////////////////////////////////
15
16 geometry::~geometry ()
17 {
18 }
19
20 template class geometry_opengl1d<GL_POINTS>;
21 template class geometry_opengl1d<GL_LINES>;
22 template class geometry_opengl1d<GL_LINE_STRIP>;
23 template class geometry_opengl1d<GL_LINE_LOOP>;
24 template class geometry_opengl2d<GL_TRIANGLES>;
25 template class geometry_opengl2d<GL_TRIANGLE_STRIP>;
26 template class geometry_opengl2d<GL_TRIANGLE_FAN>;
27 template class geometry_opengl2d<GL_QUADS>;
28 template class geometry_opengl2d<GL_QUAD_STRIP>;
29 template class geometry_opengl2d<GL_POLYGON>;
30
31 geometry_opengl::geometry_opengl ()
32 {
33 list = glGenLists (1);
34 }
35
36 geometry_opengl::~geometry_opengl ()
37 {
38 glDeleteLists (list, 1);
39 }
40
41 template<GLenum type>
42 void geometry_opengl1d<type>::set (const vector<vertex_v3f> &v)
43 {
44 clear ();
45 insert (end (), v.begin (), v.end ());
46
47 bbox.reset ();
48
49 for (const_iterator i = end (); i-- != begin (); )
50 bbox.add (i->v);
51
52 update ();
53 }
54
55 template<GLenum type>
56 void geometry_opengl1d<type>::draw (view &ctx)
57 {
58 glBegin (type);
59
60 for (iterator i = begin (); i < end (); ++i)
61 glVertex3fv ((GLfloat *)&i->v);
62
63 glEnd ();
64 }
65
66 template<GLenum type>
67 void geometry_opengl2d<type>::set (const vector<vertex_t2f_n3f_v3f> &v)
68 {
69 bbox.reset ();
70
71 for (vector<vertex_t2f_n3f_v3f>::const_iterator i = v.end (); i-- != v.begin (); )
72 bbox.add (i->v);
73
74 update ();
75
76 glNewList (list, GL_COMPILE);
77
78 #if 0
79 glBegin (type);
80
81 for (vector<vertex_t2f_n3f_v3f>::const_iterator i = v.begin (); i < v.end (); ++i)
82 {
83 glTexCoord2fv ((GLfloat *)&i->t);
84 glNormal3fv ((GLfloat *)&i->n);
85 glVertex3fv ((GLfloat *)&i->v);
86 }
87
88 glEnd ();
89 #else
90 glEnableClientState (GL_VERTEX_ARRAY);
91 glEnableClientState (GL_NORMAL_ARRAY);
92 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
93 glVertexPointer (3, GL_FLOAT, sizeof (vertex_t2f_n3f_v3f), (void *)&v.begin ()->v);
94 glNormalPointer (GL_FLOAT, sizeof (vertex_t2f_n3f_v3f), (void *)&v.begin ()->n);
95 glTexCoordPointer (2, GL_FLOAT, sizeof (vertex_t2f_n3f_v3f), (void *)&v.begin ()->t);
96
97 glDrawArrays (type, 0, v.size ());
98
99 glDisableClientState (GL_VERTEX_ARRAY);
100 glDisableClientState (GL_NORMAL_ARRAY);
101 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
102 #endif
103
104 glEndList ();
105 }
106
107 template<GLenum type>
108 void geometry_opengl2d<type>::draw (view &ctx)
109 {
110 m->enable (ctx);
111 glCallList (list);
112 m->disable (ctx);
113 }
114
115 void geometry_sphere::update ()
116 {
117 bbox.reset ();
118 bbox.add (-point (radius, radius, radius));
119 bbox.add ( point (radius, radius, radius));
120
121 geometry::update ();
122 }
123
124 void geometry_sphere::draw (view &ctx)
125 {
126 int n = min (100, max (15, (int)(ctx.pixfact * radius) / 10));
127
128 m->enable (ctx);
129 GLUquadric *quad = gluNewQuadric ();
130 gluQuadricTexture (quad, true);
131 gluSphere (quad, radius, n, n);
132 gluDeleteQuadric (quad);
133 m->disable (ctx);
134 }
135
136 /////////////////////////////////////////////////////////////////////////////
137
138 void geometry_transform::update ()
139 {
140 const box &sub = g->bbox;
141
142 bbox.reset ();
143 bbox.add (m * vec3 (sub.a.x, sub.a.y, sub.a.z));
144 bbox.add (m * vec3 (sub.b.x, sub.a.y, sub.a.z));
145 bbox.add (m * vec3 (sub.a.x, sub.b.y, sub.a.z));
146 bbox.add (m * vec3 (sub.b.x, sub.b.y, sub.a.z));
147 bbox.add (m * vec3 (sub.a.x, sub.a.y, sub.b.z));
148 bbox.add (m * vec3 (sub.b.x, sub.a.y, sub.b.z));
149 bbox.add (m * vec3 (sub.a.x, sub.b.y, sub.b.z));
150 bbox.add (m * vec3 (sub.b.x, sub.b.y, sub.b.z));
151
152 geometry::update ();
153 }
154
155 #if 0
156 void geometry_transform::renormalize ()
157 {
158 point trans(m(0,3), m(1,3), m(2,3));
159 ::renormalize (e->orig, trans);
160 m(0,3) = trans.x; m(1,3) = trans.y; m(2,3) = trans.z;
161 }
162 #endif
163
164 void geometry_transform::update (const matrix &xfrm)
165 {
166 m = m * xfrm;
167
168 update ();
169 }
170
171 void geometry_transform::set_matrix (const matrix &xfrm)
172 {
173 m = xfrm;
174
175 update ();
176 }
177
178 void geometry_transform::draw (view &ctx)
179 {
180 glPushMatrix ();
181 glMultMatrixf ((GLfloat *)&m);
182 g->draw (ctx);
183 glPopMatrix ();
184 }
185
186 void geometry_anim::draw (view &ctx)
187 {
188 matrix save_m = m;
189
190 update (matrix::rotation (vx * timer.now, vec3 (1, 0, 0))
191 * matrix::rotation (vy * timer.now, vec3 (0, 1, 0))
192 * matrix::rotation (vz * timer.now, vec3 (0, 0, 1)));
193
194 geometry_transform::draw (ctx);
195
196 m = save_m;
197 }
198
199 /////////////////////////////////////////////////////////////////////////////
200
201 void geometry_filter::set (geometry *g)
202 {
203 this->g = g;
204
205 if (g)
206 g->parent = this;
207
208 update ();
209 }
210
211 void geometry_filter::update ()
212 {
213 if (g)
214 {
215 bbox = g->bbox;
216 geometry::update ();
217 }
218 }
219
220 void geometry_filter::draw (view &ctx)
221 {
222 g->draw (ctx);
223 }
224
225 geometry_filter::~geometry_filter ()
226 {
227 delete g;
228 }
229
230 /////////////////////////////////////////////////////////////////////////////
231
232 void geometry_container::update ()
233 {
234 bbox.reset ();
235
236 for (iterator i = end (); i-- != begin (); )
237 bbox.add ((*i)->bbox);
238
239 geometry::update ();
240 }
241
242 void geometry_container::add (geometry *g)
243 {
244 push_back (g);
245 g->parent = this;
246
247 update ();
248 }
249
250 void geometry_container::draw (view &ctx)
251 {
252 for (iterator i = end (); i-- != begin (); )
253 (*i)->draw (ctx);
254 }
255
256 geometry_container::~geometry_container ()
257 {
258 for (iterator i = end (); i-- != begin (); )
259 delete *i;
260
261 clear ();
262 }
263
264 ///////////////////////////////////////////////////////////////////////////
265
266 static void nurbs_error (GLenum errorCode)
267 {
268 const GLubyte *estring;
269 estring = gluErrorString(errorCode);
270 fprintf (stderr, "Nurbs error: %s\n", estring);
271 }
272
273 void errorCallback(GLenum errorCode)
274 {
275 const GLubyte *estring;
276
277 estring = gluErrorString(errorCode);
278 fprintf (stderr, "Tessellation Error: %s\n", estring);
279 exit (0);
280 }
281
282 void tcbBegin (GLenum prim)
283 {
284 glBegin (prim);
285 }
286
287 void tcbVertex (void *data)
288 {
289 glVertex3fv ((GLfloat *)data);
290 }
291
292 void tcbEnd ()
293 {
294 glEnd ();
295 }
296
297 void geometry_nurbs::set ()
298 {
299 // < XXX >: Testing CODE
300 int u, v;
301 for (u = 0; u < 4; u++) {
302 for (v = 0; v < 4; v++) {
303 ctlpoints[u][v][0] = 2.0*((GLfloat)u - 1.5);
304 ctlpoints[u][v][1] = 2.0*((GLfloat)v - 1.5);
305
306 if ( (u == 1 || u == 2) && (v == 1 || v == 2))
307 ctlpoints[u][v][2] = 3.0;
308 else
309 ctlpoints[u][v][2] = -3.0;
310 }
311 }
312 tess = gluNewTess();
313 // </ XXX >
314
315 glEnable(GL_AUTO_NORMAL);
316 nurb = gluNewNurbsRenderer ();
317 gluNurbsProperty (nurb, GLU_AUTO_LOAD_MATRIX, GL_FALSE);
318 gluNurbsProperty (nurb, GLU_DISPLAY_MODE, GLU_FILL);
319 gluNurbsProperty (nurb, GLU_NURBS_MODE, GLU_NURBS_TESSELLATOR);
320 gluNurbsProperty (nurb, GLU_SAMPLING_METHOD, GLU_OBJECT_PATH_LENGTH);
321 gluNurbsProperty (nurb, GLU_SAMPLING_TOLERANCE, 1.0);
322 gluNurbsCallback (nurb, GLU_ERROR, (GLvoid (*)()) nurbs_error);
323 gluNurbsCallback (nurb, GLU_NURBS_BEGIN, (GLvoid(*)()) tcbBegin);
324 gluNurbsCallback (nurb, GLU_NURBS_VERTEX,(GLvoid(*)()) tcbVertex);
325 gluNurbsCallback (nurb, GLU_NURBS_END, tcbEnd);
326 glDisable(GL_AUTO_NORMAL);
327
328 }
329
330 void geometry_nurbs::draw (view &ctx)
331 {
332 GLfloat knots[8] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0};
333
334 GLfloat mat_diffuse[] = { 0.7, 0.7, 0.7, 1.0 };
335 GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
336 GLfloat mat_shininess[] = { 100.0 };
337
338 glClearColor (0.0, 0.0, 0.0, 0.0);
339 glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
340 glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
341 glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
342
343
344 glEnable(GL_AUTO_NORMAL);
345 gluBeginSurface (nurb);
346 gluNurbsSurface (nurb, 8, knots, 8, knots, 4 * 3, 3, &ctlpoints[0][0][0], 4, 4, GL_MAP2_VERTEX_3);
347 gluEndSurface (nurb);
348 /*
349 glEnable(GL_AUTO_NORMAL);
350 glPushMatrix();
351 GL_LG_DEBUG;
352 =======
353
354 gluEndSurface (nurb);
355 >>>>>>> 1.40
356 glDisable(GL_AUTO_NORMAL);
357 glPopMatrix();
358 glFlush();
359 */
360 }
361
362 /////////////////////////////////////////////////////////////////////////////
363
364 entity::entity (geometry *g)
365 : geometry_filter(g)
366 , p(0,0,0)
367 {
368 update ();
369 }
370
371 entity::~entity ()
372 {
373 hide ();
374 }
375
376 void entity::move (const vec3 &v)
377 {
378 p = p + v;
379
380 renormalize (orig, p);
381
382 update ();
383 }
384
385 void entity::show ()
386 {
387 if (!o.size ())
388 world.add (this);
389 }
390
391 void entity::hide ()
392 {
393 for (vector<octant *>::iterator i = o.end (); i-- != o.begin (); )
394 (*i)->remove (this);
395
396 o.clear ();
397 }
398
399 void entity::update ()
400 {
401 if (!g)
402 return;
403
404 bbox = g->bbox;
405
406 a.x = orig.x + (soffs)floorf (bbox.a.x + p.x);
407 a.y = orig.y + (soffs)floorf (bbox.a.y + p.y);
408 a.z = orig.z + (soffs)floorf (bbox.a.z + p.z);
409 b.x = orig.x + (soffs)ceilf (bbox.b.x + p.x);
410 b.y = orig.y + (soffs)ceilf (bbox.b.y + p.y);
411 b.z = orig.z + (soffs)ceilf (bbox.b.z + p.z);
412
413 if (o.size ())
414 {
415 hide ();
416 show ();
417 }
418 }
419
420 void entity::draw (view &ctx)
421 {
422 ctx.eorig = orig - ctx.orig;
423
424 glPushMatrix ();
425 glTranslatef (p.x + ctx.eorig.x, p.y + ctx.eorig.y, p.z + ctx.eorig.z);
426 g->draw (ctx);
427 glPopMatrix ();
428 }
429
430 /////////////////////////////////////////////////////////////////////////////
431 //
432
433 #define SIZE 33
434
435 struct geometry_heightfield::node
436 {
437 vertex_t2f_n3f_v3f vd[SIZE][SIZE];
438 gl::vertex_buffer vb;
439 GLushort *ibp;
440 GLfloat hvar;
441 GLfloat x, y, z, e;
442
443 // 23
444 // 01
445 struct geometry_heightfield::node *sub[4];
446
447 void update_normals ();
448 void draw (view &ctx);
449
450 node ();
451 };
452
453 geometry_heightfield::node::node ()
454 {
455 sub[0] = sub[1] = sub[2] = sub[3] = 0;
456 //vb.set (vd);
457 }
458
459 static index_buffer ib;
460 static GLushort *ibp;
461 static int icnt;
462
463 geometry_heightfield::geometry_heightfield (GLfloat sx, GLfloat sy)
464 : sx(sx), sy(sy)
465 , sm (max (sx, sy))
466 {
467 if (!ib)
468 {
469 ib.set<GLushort> (SIZE * SIZE * 6, GL_STATIC_DRAW);
470 ibp = (GLushort *)ib.map ();
471
472 GLushort *p = ibp;
473
474 for (int x = 0; x < SIZE - 1; x++)
475 for (int y = 0; y < SIZE - 1; y++)
476 {
477 unsigned short a = (y + 0) * SIZE + (x + 0);
478 unsigned short b = (y + 0) * SIZE + (x + 1);
479 unsigned short c = (y + 1) * SIZE + (x + 1);
480 unsigned short d = (y + 1) * SIZE + (x + 0);
481
482 *p++ = c; *p++ = b; *p++ = a;
483 *p++ = d; *p++ = c; *p++ = a;
484 }
485
486 icnt = p - ibp;
487
488 ib.unmap ();
489 }
490
491 update ();
492
493 tree = new node;
494 tree->hvar = 0.01F * sx;
495 tree->x = tree->y = 0.F;
496 tree->e = sm;
497
498 for (int x = 0; x < SIZE; x++)
499 for (int y = 0; y < SIZE; y++)
500 {
501 vertex_t2f_n3f_v3f &v = tree->vd[y][x];
502
503 v.t = tex2 ((GLfloat)x / (SIZE - 1), (GLfloat)y / (SIZE - 1));
504 v.v = vec3 (sx * x / (SIZE - 1), tree->hvar * rand () / RAND_MAX, sy * y / (SIZE - 1));
505 v.n = vec3 (0, 1, 0);
506 }
507
508 tree->update_normals ();
509
510 tree->vb.set (&tree->vd[0][0], SIZE * SIZE);
511
512 bbox.reset ();
513 bbox.add (vec3 (0, 0, 0));
514 bbox.add (vec3 (sx, tree->hvar, sy));
515 }
516
517 void geometry_heightfield::update ()
518 {
519 geometry::update ();
520 }
521
522 static int maxcnt, thiscnt;
523 static GLfloat mine;
524
525 void geometry_heightfield::draw (view &ctx)
526 {
527 testmat->enable (ctx);
528 maxcnt = 10;
529 thiscnt = 0;
530 mine = 1e38;
531 tree->draw (ctx);
532 testmat->disable (ctx);
533 //printf (" TC %d mine %f\n", thiscnt, mine);
534 }
535
536 void geometry_heightfield::node::update_normals ()
537 {
538 GLfloat az = 0.F;
539
540 for (int x = 0; x < SIZE; x++)
541 for (int y = 0; y < SIZE; y++)
542 {
543 vertex_t2f_n3f_v3f &v = vd[y][x];
544
545 if (x && y)
546 v.n = normalize (cross (vd[y-1][x].v - v.v, vd[y][x-1].v - v.v));
547
548 az += v.v.y;
549 }
550
551 z = az / (SIZE * SIZE);
552 }
553
554 void geometry_heightfield::node::draw (view &ctx)
555 {
556 vec3 center = vec3 (ctx.eorig) + vec3 (x + e * .5F, z, y + e * .5F);
557 GLfloat d = length (center);
558
559 if (!overlap (ctx.frustum.c, sphere (center, e * 2)))
560 return;
561
562 if (d > e * 2.F)
563 {
564 if (mine > e) mine = e; thiscnt++;
565 vb.bind ();
566 ib.draw (GL_TRIANGLES, 0, icnt);
567 }
568 else
569 {
570 for (int i = 0; i < 4; i++)
571 {
572 if (!sub[i])
573 {
574 if (!--maxcnt)
575 {
576 vb.bind ();
577 ib.draw (GL_TRIANGLES, 0, icnt);
578 }
579
580 node *n = sub[i] = new node;
581
582 n->hvar = hvar * 0.5;
583 n->x = x + (i & 1 ? e * .5F : 0.F);
584 n->y = y + (i & 2 ? e * .5F : 0.F);
585 n->e = e * .5F;
586
587 for (int x = 0; x < SIZE; x++)
588 for (int y = 0; y < SIZE; y++)
589 n->vd[y][x] = vd[(y >> 1) + (i & 2 ? SIZE / 2 : 0)][(x >> 1) + (i & 1 ? SIZE / 2 : 0)];
590
591 for (int x = 1; x < SIZE; x += 2)
592 for (int y = 0; y < SIZE; y += 2)
593 {
594 n->vd[y][x].t = (n->vd[y][x-1].t + n->vd[y][x+1].t) * 0.5F;
595 n->vd[y][x].v = (n->vd[y][x-1].v + n->vd[y][x+1].v) * 0.5F;
596 if (y && y < SIZE - 1)
597 n->vd[y][x].v.y += n->hvar * (GLfloat)rand () / RAND_MAX - n->hvar * .5F;
598 }
599
600 for (int x = 0; x < SIZE; x++)
601 for (int y = 1; y < SIZE; y += 2)
602 {
603 n->vd[y][x].t = (n->vd[y-1][x].t + n->vd[y+1][x].t) * 0.5F;
604 n->vd[y][x].v = (n->vd[y-1][x].v + n->vd[y+1][x].v) * 0.5F;
605 if (x && x < SIZE - 1)
606 n->vd[y][x].v.y += n->hvar * (GLfloat)rand () / RAND_MAX - n->hvar * .5F;
607 }
608
609 n->update_normals ();
610
611 n->vb.set (&n->vd[0][0], SIZE * SIZE);
612 }
613
614 sub[i]->draw (ctx);
615 }
616 }
617 }
618