Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Extras / sph / common / mesh.cpp
1 /*
2   FLUIDS v.1 - SPH Fluid Simulator for CPU and GPU
3   Copyright (C) 2009. Rama Hoetzlein, http://www.rchoetzlein.com
4
5   ZLib license
6   This software is provided 'as-is', without any express or implied
7   warranty.  In no event will the authors be held liable for any damages
8   arising from the use of this software.
9
10   Permission is granted to anyone to use this software for any purpose,
11   including commercial applications, and to alter it and redistribute it
12   freely, subject to the following restrictions:
13
14   1. The origin of this software must not be misrepresented; you must not
15      claim that you wrote the original software. If you use this software
16      in a product, an acknowledgment in the product documentation would be
17      appreciated but is not required.
18   2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20   3. This notice may not be removed or altered from any source distribution.
21 */
22
23 #include <conio.h>
24 #include <vector.h>
25 #include "mesh.h"
26 #include "mdebug.h"
27 //#include "mfile.h"
28
29 //#include "event.h"
30
31 #include <gl/glut.h>
32
33 #define DEGtoRAD        (3.141592/180.0)
34
35 bool Mesh::mbInitStatic = false;
36 int Mesh::miBufSize[MAX_MFORMAT][MAX_BFORMAT];
37
38 Mesh::Mesh ()
39 {
40         debug.SendToConsole ( true );
41
42         m_Mform = MFormat::UDef;
43         m_CurrF = 0;
44         m_Vbuf = BUF_UNDEF;
45         m_Ebuf = BUF_UNDEF;
46         m_Fbuf = BUF_UNDEF;
47 }
48
49 Mesh& Mesh::operator= ( Mesh& src )
50 {
51         CopyBuffers ( src );
52         CopyAttributes ( src );
53         m_Mform = src.GetMeshBufs ( m_Vbuf, m_Ebuf, m_Fbuf );
54         return *this;
55 }
56
57 void Mesh::InitStatic ()
58 {
59         mbInitStatic = true;
60         miBufSize[ (int) FVF ][ (int) BVert ] = sizeof ( VertFVF );
61         miBufSize[ (int) FVF ][ (int) BFace ] = sizeof ( FaceFVF );
62         miBufSize[ (int) FVF ][ (int) BEdge ] = 0;
63         miBufSize[ (int) CM  ][ (int) BVert ] = sizeof ( VertCM );
64         miBufSize[ (int) CM  ][ (int) BEdge ] = sizeof ( EdgeCM );
65         miBufSize[ (int) CM  ][ (int) BFace ] = sizeof ( FaceCM );
66
67 }
68
69 /*void Mesh::onUpdate ( objData dat, mint::Event* e )
70 {
71         uchar           dtype;
72         hval            num;
73         hval            max;
74         long            size;
75         ushort          stride;
76         int                     num_buf;
77
78         switch ( dat ) {
79         case 'full':
80                 ClearBuffers ();
81                 ClearAttributes ();
82                                 
83                 m_Mform = (MFormat) e->getUChar ();
84                 m_Vbuf = e->getUChar ();
85                 m_Ebuf = e->getUChar ();
86                 m_Fbuf = e->getUChar ();
87                 num_buf = e->getInt ();
88                 for (int b=0; b < num_buf; b++) {
89                         dtype = e->getUChar ();
90                         stride = e->getUShort ();
91                         num = e->getInt ();
92                         max = e->getInt ();
93                         AddBuffer ( dtype, stride, max );
94                         e->getMem ( mBuf[b].data, num * mBuf[b].stride );
95                         mBuf[b].num = num;
96                 }
97
98                 mHeapNum = e->getInt ();
99                 mHeapMax = e->getInt ();
100                 mHeapFree = e->getInt ();
101                 mHeap = new hval[mHeapMax];
102                 e->getMem ( (char*) mHeap, mHeapNum * sizeof(hval) );
103                 break;
104         };
105 }
106
107 void Mesh::UpdateMesh ()
108 {
109         int s = GetSize () + (mBuf.size()+1)*4*sizeof(int);
110         mint::Event* e = updateStart ( 'full', s );     
111
112         e->attachUChar ( (char) m_Mform ) ;
113         e->attachUChar ( (char) m_Vbuf );
114         e->attachUChar ( (char) m_Ebuf );
115         e->attachUChar ( (char) m_Fbuf );
116         e->attachInt ( mBuf.size() );
117         for (int b=0; b < mBuf.size(); b++) {
118                 e->attachUChar ( mBuf[b].dtype );
119                 e->attachUShort ( mBuf[b].stride );
120                 e->attachInt ( mBuf[b].num );
121                 e->attachInt ( mBuf[b].max );           
122                 e->attachMem ( mBuf[b].data, mBuf[b].num * mBuf[b].stride );
123         }
124         e->attachInt ( mHeapNum );
125         e->attachInt ( mHeapMax );
126         e->attachInt ( mHeapFree );
127         e->attachMem ( (char*) mHeap, mHeapNum * sizeof(hval) );
128
129         updateEnd ( e );
130 }
131 */
132
133 //------------------------------------------------------------------ FVF - Face-vertex-face Mesh
134 void Mesh::CreateFVF () 
135 {
136         if ( !mbInitStatic ) InitStatic ();
137         SetFuncFVF ();
138
139         m_Mform = FVF;
140         m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( FVF, BVert ), 64 );
141         m_Fbuf = AddBuffer ( (uchar) BFace, BufSize( FVF, BFace ), 64 );
142         AddAttribute ( m_Vbuf, "pos", sizeof ( AttrPos ), false );
143         AddAttribute ( m_Vbuf, "norm", sizeof ( AttrNorm ) );
144
145         AddHeap ( 128 );
146 }
147
148 void Mesh::ClearFVF ()
149 {
150         ResetBuffer ( 0, mBuf[0].max );
151         ResetBuffer ( 1, mBuf[0].max );
152
153         ResetHeap ();
154 }
155
156 void Mesh::SmoothFVF ( int iter )
157 {
158         Vector3DF norm, side;
159         int cnt;
160         FaceFVF* f;
161         VertFVF *v1, *v2, *v3;
162         AttrPos* face_pos;
163         face_pos = new AttrPos[ NumFace() ];
164
165         for (int j=0; j < iter; j++) {
166                 // Compute centroid of all faces
167                 for (int n=0; n < NumFace(); n++) {
168                         f = GetFaceFVF ( n );
169                         v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3);
170                         face_pos[n].x = ( v1->x + v2->x + v3->x ) / 3.0;
171                         face_pos[n].y = ( v1->y + v2->y + v3->y ) / 3.0;
172                         face_pos[n].z = ( v1->z + v2->z + v3->z ) / 3.0;
173                 }
174                 // Compute new vertex positions
175                 int cnt;
176                 Vector3DF vec;
177                 for (int n=0; n < NumVert(); n++) {
178                         v1 = GetVertFVF ( n );
179                         vec.Set (0,0,0);
180                         hval* fptr = mHeap + v1->flist.pos;     
181                         for (int j=0; j < v1->flist.cnt; j++) {
182                                 vec.x += face_pos[ (*fptr) ].x;
183                                 vec.y += face_pos[ (*fptr) ].y;
184                                 vec.z += face_pos[ (*fptr) ].z;
185                                 fptr++;
186                         }
187                         v1->x = vec.x / (float) v1->flist.cnt;
188                         v1->y = vec.y / (float) v1->flist.cnt;
189                         v1->z = vec.z / (float) v1->flist.cnt;
190                 }
191         }
192         delete face_pos;
193 }
194
195 void Mesh::SetNormalFVF ( int n, Vector3DF norm )
196 {
197         VertFVF* v1;
198         AttrNorm* vn;
199         int noff = GetAttrOffset ( "norm" );
200         v1 = GetVertFVF ( n );
201         vn = (AttrNorm* ) ((char*) v1 + noff );
202         vn->nx = norm.x;
203         vn->ny = norm.y;
204         vn->nz = norm.z;
205 }
206
207
208 void Mesh::SetColorFVF ( int n, DWORD clr )
209 {
210         VertFVF* v1;
211         AttrClr* vc;
212         int coff = GetAttrOffset ( "color" );
213         if ( coff == -1 ) return;
214         v1 = GetVertFVF ( n );
215         vc = (AttrClr* ) ((char*) v1 + coff );
216         vc->clr = clr;
217 }
218 void Mesh::ComputeNormalsFVF ()
219 {
220         Vector3DF norm, side;
221         FaceFVF* f;
222         VertFVF *v1, *v2, *v3, *v4;
223         AttrNorm* vn;
224         AttrNorm* face_norms;
225         face_norms = new AttrNorm[ NumFace() ];
226
227         // Clear vertex normals
228         int noff = GetAttrOffset ( "norm" );
229         for (int n=0; n < NumVert(); n++) {
230                 v1 = GetVertFVF ( n );
231                 vn = (AttrNorm*) ((char*) v1 + noff);
232                 vn->nx = 0;
233                 vn->ny = 0;
234                 vn->nz = 0;
235         }
236
237         // Compute normals of all faces
238         for (int n=0; n < NumFace(); n++) {
239                 f = GetFaceFVF ( n );
240                 v1 = GetVertFVF(f->v1); v2 = GetVertFVF(f->v2); v3 = GetVertFVF(f->v3);
241                 side = Vector3DF ( v2->x, v2->y, v2->z );
242                 side -= Vector3DF ( v1->x, v1->y, v1->z );
243                 side.Normalize ();
244                 norm = Vector3DF ( v3->x, v3->y, v3->z );
245                 norm -= Vector3DF ( v1->x, v1->y, v1->z );
246                 norm.Normalize ();
247                 norm.Cross ( side );
248                 face_norms[n].nx = norm.x;
249                 face_norms[n].ny = norm.y;
250                 face_norms[n].nz = norm.z;
251                 vn = (AttrNorm*) ((char*) v1 + noff);   vn->nx += norm.x; vn->ny += norm.y;     vn->nz += norm.z;
252                 vn = (AttrNorm*) ((char*) v2 + noff);   vn->nx += norm.x; vn->ny += norm.y;     vn->nz += norm.z;
253                 vn = (AttrNorm*) ((char*) v3 + noff);   vn->nx += norm.x; vn->ny += norm.y;     vn->nz += norm.z;
254                 if ( f->v4 != -1 ) {
255                         v4 = GetVertFVF(f->v4);
256                         vn = (AttrNorm*) ((char*) v4 + noff);   vn->nx += norm.x; vn->ny += norm.y;     vn->nz += norm.z;
257                 }
258         }
259
260         // Normalize vertex normals
261         Vector3DF vec;
262         for (int n=0; n < NumVert(); n++) {
263                 v1 = GetVertFVF ( n );
264                 vn = (AttrNorm*) ((char*) v1 + noff);
265                 vec.Set ( vn->nx, vn->ny, vn->nz );
266                 vec.Normalize ();
267                 vn->nx = vec.x;
268                 vn->ny = vec.y;
269                 vn->nz = vec.z;
270         }
271         
272         // Compute normal of a vertex from surrounding faces (slow method)
273         /*int cnt;
274         for (int n=0; n < NumVert(); n++) {
275                 v1 = GetVertFVF ( n );
276                 vn = (VertNorm*) GetExtraFVF ( v1 );
277                 cnt = 0;
278                 vn->nx = 0; vn->ny = 0; vn->nz = 0;
279                 hval* fptr = mHeap + v1->flist.pos;     
280                 for (int j=0; j < v1->flist.cnt; j++) {
281                         vn->nx += face_norms[ (*fptr) ].nx;
282                         vn->ny += face_norms[ (*fptr) ].ny;
283                         vn->nz += face_norms[ (*fptr) ].nz;
284                         cnt++;
285                         fptr++;
286                 }
287                 vn->nx /= (float) cnt;
288                 vn->ny /= (float) cnt;
289                 vn->nz /= (float) cnt;
290         }*/
291
292         delete face_norms;
293 }
294
295 void Mesh::SetFuncFVF ()
296 {
297         m_AddVertFunc = &Mesh::AddVertFVF;
298         m_AddFaceFast3Func = &Mesh::AddFaceFast3FVF;
299         m_AddFaceFast4Func = &Mesh::AddFaceFast4FVF;
300 }
301
302 xref Mesh::AddFaceFast3FVF ( xref v1, xref v2, xref v3 )
303 {
304         xref fNdx;      
305         FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx );
306         f->v1 = v1;     f->v2 = v2;     f->v3 = v3; f->v4 = -1;
307         AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA );     
308         AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA );
309         AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA );
310         return fNdx;
311 }
312 xref Mesh::AddFaceFast4FVF ( xref v1, xref v2, xref v3, xref v4 )
313 {
314         xref fNdx;      
315         FaceFVF* f = (FaceFVF*) AddElem ( m_Fbuf, fNdx );
316         f->v1 = v1;     f->v2 = v2;     f->v3 = v3; f->v4 = v4;
317         AddRef ( fNdx, GetVertFVF(v1)->flist, FACE_DELTA );     
318         AddRef ( fNdx, GetVertFVF(v2)->flist, FACE_DELTA );
319         AddRef ( fNdx, GetVertFVF(v3)->flist, FACE_DELTA );
320         AddRef ( fNdx, GetVertFVF(v4)->flist, FACE_DELTA );
321         return fNdx;
322 }
323 xref Mesh::AddVertFVF ( float x, float y, float z )
324 {
325         xref ndx;
326         VertFVF* v = (VertFVF*) AddElem ( m_Vbuf, ndx );
327         v->x = x; v->y = y; v->z = z;
328         ClearRefs ( v->flist );
329         return ndx;
330 }
331
332 void Mesh::DebugFVF ()
333 {
334         int n;
335         int j;  
336         VertFVF* v;
337         FaceFVF* f;
338         debug.Printf ( "-- MESH --\n");
339         
340         debug.Printf ( "-- verts\n" );
341         for (n=0; n < NumVert(); n++) {
342                 v = GetVertFVF(n);
343                 debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) f:%d %d{", n, v->x, v->y, v->z, v->flist.cnt, v->flist.pos);
344                 if ( v->flist.cnt > 0 ) {
345                         for (j=0; j < v->flist.cnt; j++) 
346                                 debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA );
347                 }
348                 debug.Printf ( "}\n" ); 
349         }
350         debug.Printf ( "-- faces\n" );  
351         for (n=0; n < NumFace(); n++) {
352                 f = GetFaceFVF(n);
353                 debug.Printf ( "%d: v:%d %d %d\n", n, f->v1, f->v2, f->v3);
354         }
355
356         DebugHeap ();
357         
358         debug.Printf ("\n\n");
359         //_getch();
360 }
361
362
363 //------------------------------------------------------------------ CM - Connected Mesh
364 // Create Connected Mesh (CM)
365 void Mesh::CreateCM () 
366 {
367         if ( !mbInitStatic ) InitStatic ();
368         SetFuncCM ();
369
370         m_Mform = CM;
371         m_Vbuf = AddBuffer ( (uchar) BVert, BufSize( CM, BVert ), 64 );
372         m_Ebuf = AddBuffer ( (uchar) BEdge, BufSize ( CM, BEdge), 64 );
373         m_Fbuf = AddBuffer ( (uchar) BFace, BufSize ( CM, BFace), 64 );
374         AddAttribute ( m_Vbuf, "pos", sizeof(AttrPos), false );
375         AddAttribute ( m_Vbuf, "norm", sizeof(AttrNorm) );
376
377         AddHeap ( 128 );
378 }
379
380 void Mesh::SetFuncCM ()
381 {
382         m_AddVertFunc = &Mesh::AddVertCM;
383         m_AddFaceFast3Func = &Mesh::AddFaceFast3CM;
384         m_AddFaceFast4Func = &Mesh::AddFaceFast4CM;
385 }
386
387
388 xref Mesh::AddVertCM ( float x, float y, float z )
389 {
390         xref ndx;
391         VertCM* v = (VertCM*) AddElem ( m_Vbuf, ndx );
392         v->x = x; v->y = y; v->z = z;
393         ClearRefs ( v->elist );
394         ClearRefs ( v->flist );
395         return ndx;
396 }
397
398 xref Mesh::AddFaceFast3CM ( xref v1, xref v2, xref v3 )
399 {
400         xref fNdx;      
401         FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx );
402         f->v1 = v1;     f->v2 = v2;     f->v3 = v3; f->v4 = -1;
403         xref eNdx;
404         eNdx = AddEdgeCM ( f->v1, f->v2 );              f->e1 = eNdx;
405         eNdx = AddEdgeCM ( f->v2, f->v3 );              f->e2 = eNdx;
406         eNdx = AddEdgeCM ( f->v3, f->v1 );              f->e3 = eNdx;
407         AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA );      
408         AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA );
409         AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA );
410         return fNdx;
411 }
412 xref Mesh::AddFaceFast4CM ( xref v1, xref v2, xref v3, xref v4 )
413 {
414         xref fNdx;      
415         FaceCM* f = (FaceCM*) AddElem ( m_Fbuf, fNdx );
416         f->v1 = v1;     f->v2 = v2;     f->v3 = v3; f->v4 = v4;
417         xref eNdx;
418         eNdx = AddEdgeCM ( f->v1, f->v2 );              f->e1 = eNdx;
419         eNdx = AddEdgeCM ( f->v2, f->v3 );              f->e2 = eNdx;
420         eNdx = AddEdgeCM ( f->v3, f->v4 );              f->e3 = eNdx;
421         eNdx = AddEdgeCM ( f->v4, f->v1 );              f->e4 = eNdx;
422         AddRef ( fNdx, GetVertCM(v1)->flist, FACE_DELTA );      
423         AddRef ( fNdx, GetVertCM(v2)->flist, FACE_DELTA );
424         AddRef ( fNdx, GetVertCM(v3)->flist, FACE_DELTA );
425         AddRef ( fNdx, GetVertCM(v4)->flist, FACE_DELTA );
426         return fNdx;
427 }
428
429 xref Mesh::FindEdgeCM ( xref v1, xref v2 )
430 {       
431         EdgeCM *pE;
432         VertCM *pV1;
433         pV1 = GetVertCM(v1);    
434         if ( pV1->elist.cnt == 0 ) return -1;
435         hval* e = mHeap + pV1->elist.pos;
436         #ifdef MESH_DEBUG
437                 for (int n=0; n < pV1->elist.cnt; n++) {
438                         pE = GetEdgeCM( (*e)-EDGE_DELTA );
439                         if ( pE->v1 == v2 || pE->v2 == v2 ) return (*e)-EDGE_DELTA;
440                         e++;
441                 }
442         #else   
443                 for (int n=0; n < pV1->elist.cnt; n++) {
444                         pE = GetEdgeCM( *e );
445                         if ( pE->v1 == v2 || pE->v2 == v2 ) return *e;
446                         e++;
447                 }
448         #endif
449         return -1;
450 }
451
452 xref Mesh::AddEdgeCM ( xref v1, xref v2 )
453 {       
454         xref eNdx = FindEdgeCM ( v1, v2 );
455         EdgeCM* e = GetEdgeCM(eNdx);
456         if ( eNdx == -1 ) {
457                 e = (EdgeCM*) AddElem ( m_Ebuf, eNdx );
458                 e->f1 = 0;
459                 e->f2 = 0;
460                 e->v1 = v1;
461                 e->v2 = v2;             
462                 AddRef ( eNdx, GetVertCM(v1)->elist, EDGE_DELTA );
463                 AddRef ( eNdx, GetVertCM(v2)->elist, EDGE_DELTA );              
464         }
465         return eNdx;
466 }
467
468 void Mesh::DebugCM ()
469 {
470         int n;
471         int j;  
472         VertCM* v;
473         EdgeCM* e;
474         FaceCM* f;
475         debug.Printf ( "-- MESH --\n");
476         
477         debug.Printf ( "-- verts\n" );
478         for (n=0; n < NumVert(); n++) {
479                 v = GetVertCM(n);
480                 debug.Printf ( "%d: (%2.1f,%2.1f,%2.1f) e:%d %d{", n, v->x, v->y, v->z, v->elist.cnt, v->elist.pos);
481                 if ( v->elist.cnt > 0 ) { 
482                         for (j=0; j < v->elist.cnt; j++) 
483                                 debug.Printf ( "%d ", *(mHeap+v->elist.pos+j) - EDGE_DELTA );
484                 }
485                 debug.Printf ( "}, f:%d %d{", v->flist.cnt, v->flist.pos);
486                 if ( v->flist.cnt > 0 ) {
487                         for (j=0; j < v->flist.cnt; j++) 
488                                 debug.Printf ( "%d ", *(mHeap+v->flist.pos+j) - FACE_DELTA );
489                 }
490                 debug.Printf ( "}\n" ); 
491         }
492
493         debug.Printf ( "-- edges\n" );  
494         for (n=0; n < NumEdge(); n++) {
495                 e = GetEdgeCM (n);
496                 debug.Printf ( "%d: v:%d %d, f:%d %d\n", n, e->v1, e->v2, e->f1, e->f2 );               
497         }
498
499         debug.Printf ( "-- faces\n" );  
500         for (n=0; n < NumFace(); n++) {
501                 f = GetFaceCM(n);
502                 debug.Printf ( "%d: v:%d %d %d, e:%d %d %d\n", n, f->v1, f->v2, f->v3, f->e1, f->e2, f->e3 );           
503         }
504
505
506         hval* pVal = mHeap;
507         debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree );
508         for (n=0; n < mHeapNum; n++) {
509                 if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n );
510                 #ifdef MESH_DEBUG
511                         if ( *pVal == 0 ) {
512                                 debug.Printf ( "00000 ");
513                         } else if (  *pVal == (hval) 0xFFFF ) {
514                                 debug.Printf ( "----- ");               
515                         } else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) {
516                                 debug.Printf ( "v%04d ", *pVal - VERT_DELTA );
517                         } else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) {
518                                 debug.Printf ( "e%04d ", *pVal - EDGE_DELTA );
519                         } else if ( *pVal >= FACE_DELTA ) {
520                                 debug.Printf ( "f%04d ", *pVal - FACE_DELTA );
521                         } else {
522                                 debug.Printf ( "H%04d ", (int) *pVal );
523                         }                       
524                 #else
525                         debug.Printf ( "%05d ", (int) *pVal );
526                 #endif
527                 pVal++;
528         }
529         
530         debug.Printf ("\n\n");
531         //_getch();
532 }
533
534 void Mesh::DebugHeap ()
535 {
536         hval* pVal = mHeap;
537         debug.Printf ( "-- heap (size: %d, max: %d, free: %04d)\n", mHeapNum, mHeapMax, mHeapFree );
538         for (int n=0; n < mHeapNum; n++) {
539                 if ( (n % 8) == 0 ) debug.Printf ( "\n[%04d] ", n );
540                 #ifdef MESH_DEBUG
541                         if ( *pVal == 0 ) {
542                                 debug.Printf ( "00000 ");
543                         } else if (  *pVal == (hval) 0xFFFF ) {
544                                 debug.Printf ( "----- ");               
545                         } else if ( *pVal >= VERT_DELTA && *pVal < EDGE_DELTA ) {
546                                 debug.Printf ( "v%04d ", *pVal - VERT_DELTA );
547                         } else if ( *pVal >= EDGE_DELTA && *pVal < FACE_DELTA ) {
548                                 debug.Printf ( "e%04d ", *pVal - EDGE_DELTA );
549                         } else if ( *pVal >= FACE_DELTA ) {
550                                 debug.Printf ( "f%04d ", *pVal - FACE_DELTA );
551                         } else {
552                                 debug.Printf ( "H%04d ", (int) *pVal );
553                         }                       
554                 #else
555                         debug.Printf ( "%05d ", (int) *pVal );
556                 #endif
557                 pVal++;
558         }
559 }
560
561 void Mesh::DrawVertsCM ( float* viewmat, int a, int b )
562 {
563         VertCM* v;
564
565         glColor3f (1,0,0);
566         glLoadMatrixf ( viewmat );
567         glTranslatef ( mT.x, mT.y, mT.z );
568         glBegin ( GL_POINTS );
569         for (int n = a; n <= b; n++) {  
570                 v = GetVertCM (n);
571                 glVertex3f ( v->x, v->y, v->z );
572                 //glCallList ( m_GLObj );               
573         }
574         glEnd ();
575 }
576
577 void Mesh::DrawVertsFVF ( float* viewmat, int a, int b )
578 {
579         VertFVF* v;
580         glColor3f (1,0,0);
581         glLoadMatrixf ( viewmat );
582         glTranslatef ( mT.x, mT.y, mT.z );
583         glBegin ( GL_POINTS );
584         for (int n = a; n <= b; n++) {  
585                 v = GetVertFVF (n);
586                 glVertex3f ( v->x, v->y, v->z );
587                 //glCallList ( m_GLObj );               
588         }
589         glEnd ();
590 }
591
592 void Mesh::DrawFacesCM ( float* viewmat, int a, int b )
593 {
594         FaceCM* f;
595         VertCM* v;
596         AttrNorm* vn;
597         int noff = GetAttrOffset ( "norm" );
598         glLoadMatrixf ( viewmat );
599         glTranslatef ( mT.x, mT.y, mT.z );
600         GLenum dm = GL_TRIANGLES;
601         glBegin ( dm );
602         f = GetFaceCM ( a );
603         for (int n = a; n <= b; n++) {
604                 if ( f->v4 == -1 ) {
605                         if ( dm != GL_TRIANGLES ) {     glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; }
606                         v = GetVertCM(f->v1);   vn = (AttrNorm*) ((char*) v + noff);
607                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
608                         v = GetVertCM(f->v2);   vn = (AttrNorm*) ((char*) v + noff);
609                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
610                         v = GetVertCM(f->v3);   vn = (AttrNorm*) ((char*) v + noff);
611                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
612                 } else {
613                         if ( dm != GL_QUADS )   { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; }
614                         v = GetVertCM(f->v1);   vn = (AttrNorm*) ((char*) v + noff);
615                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
616                         v = GetVertCM(f->v2);   vn = (AttrNorm*) ((char*) v + noff);
617                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
618                         v = GetVertCM(f->v3);   vn = (AttrNorm*) ((char*) v + noff);
619                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
620                         v = GetVertCM(f->v4);   vn = (AttrNorm*) ((char*) v + noff);
621                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
622                 }
623                 f++;
624         }       
625         glEnd ();
626 }
627
628 void Mesh::DrawFacesFVF ( float* viewmat, int a, int b )
629 {
630         FaceFVF* f;
631         VertFVF* v;
632         AttrNorm* vn;
633         AttrClr* vc;
634         int noff = GetAttrOffset ( "norm" );
635         int coff = GetAttrOffset ( "color" );
636         coff = -1;
637
638         //glLoadMatrixf ( viewmat );
639         //glTranslatef ( mT.x, mT.y, mT.z );
640         GLenum dm = GL_TRIANGLES;
641         glBegin ( dm );
642         f = GetFaceFVF ( a );
643         for (int n = a; n <= b; n++) {
644                 if ( f->v4 == -1 ) {
645                         if ( dm != GL_TRIANGLES ) {     glEnd (); glBegin ( GL_TRIANGLES ); dm = GL_TRIANGLES; }
646                         v = GetVertFVF(f->v1);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
647                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
648                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
649                         
650                         v = GetVertFVF(f->v2);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
651                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
652                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
653                         
654                         v = GetVertFVF(f->v3);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
655                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
656                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
657                 } else {
658                         if ( dm != GL_QUADS )   { glEnd (); glBegin ( GL_QUADS ); dm = GL_QUADS; }
659                         v = GetVertFVF(f->v1);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
660                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
661                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
662                         
663                         v = GetVertFVF(f->v2);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
664                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
665                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
666                         
667                         v = GetVertFVF(f->v3);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
668                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
669                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
670                         
671                         v = GetVertFVF(f->v4);  vn = (AttrNorm*) ((char*) v + noff);    vc = (AttrClr*) ((char*) v +coff);
672                         if ( coff != -1 ) glColor4f ( RED(vc->clr), GRN(vc->clr), BLUE(vc->clr), ALPH(vc->clr) );
673                         glNormal3f ( vn->nx, vn->ny, vn->nz );  glVertex3f ( v->x, v->y, v->z );
674                 }
675                 f++;
676         }       
677         glEnd ();
678 }
679
680 void Mesh::DrawEdgesCM ( float* viewmat, int a, int b )
681 {
682         EdgeCM* e;
683         
684         glLoadMatrixf ( viewmat );
685         glTranslatef ( mT.x, mT.y, mT.z );
686         glBegin ( GL_LINES );
687         e = GetEdgeCM ( a );
688         for (int n = a; n <= b; n++) {
689                 glVertex3f ( GetVertCM(e->v1)->x, GetVertCM(e->v1)->y, GetVertCM(e->v1)->z );
690                 glVertex3f ( GetVertCM(e->v2)->x, GetVertCM(e->v2)->y, GetVertCM(e->v2)->z );
691                 e++;
692         }
693         glEnd ();
694 }
695
696 void Mesh::DrawGL ( float* viewmat )
697 {
698         mT.Set(0,0,0);
699         
700         switch ( m_Mform ) {
701         case CM: {
702                 glDepthRange (0.001, 1.001);
703                 //glColor3f ( 1, 0, 0 );                DrawVertsCM ( viewmat, 0, NumVert()-1 );
704                 glColor3f ( .6, .6, .6 );       DrawFacesCM ( viewmat, 0, NumFace()-1 );
705                 //glDepthRange (0.0005, 1.0005);
706                 //glColor3f ( 1, 1, 1);         DrawEdgesCM ( viewmat, 0, NumEdge()-1 );        
707                 } break;
708         case FVF: { 
709                 //glColor3f (1,0,0);                    DrawVertsFVF ( viewmat, 0, NumVert()-1 );
710                 //glEnable (GL_LIGHTING);
711                 
712                 glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );
713                 glColor4f ( .9, .9, .9, 0.75 ); DrawFacesFVF ( viewmat, 0, NumFace()-1 );
714
715                 /*glDisable (GL_LIGHTING );
716                 glDepthRange (0.000, 1.00);
717                 glPolygonMode ( GL_FRONT_AND_BACK, GL_LINE );
718                 glLineWidth ( 3 );
719                 glColor4f ( 0, 0, 0, 1.0 );     DrawFacesFVF ( viewmat, 0, NumFace()-1 );               
720                 glEnable ( GL_LIGHTING );
721
722                 glLineWidth ( 1);
723
724                 glDepthRange (0.0, 1.0);
725                 glPolygonMode ( GL_FRONT_AND_BACK, GL_FILL );*/
726
727                 } break;
728         }
729 }
730
731 void Mesh::DrawFaceGL ( float* viewmat )
732 {
733         mT.Set (0,0,0);
734         if ( m_CurrF < 0 ) m_CurrF = NumFace()-1;
735         if ( m_CurrF >= NumFace() ) m_CurrF = 0;
736         
737         switch ( m_Mform ) {
738         case FVF: 
739                 glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 );    
740                 DrawFacesFVF ( viewmat, m_CurrF, m_CurrF );
741                 break;
742         case CM:
743                 glDepthRange (0.0, 1.0); glColor3f (1.0, 1.0, 1.0 );    
744                 DrawFacesCM ( viewmat, m_CurrF, m_CurrF );
745                 break;
746         };
747 }
748
749 void Mesh::Measure ()
750 {
751         hval* pCurr = mHeap + mHeapFree;        
752         int vs, es, fs, hs, hm, as, frees = 0;
753         vs = NumVert(); if ( vs !=0 ) vs *= GetStride(m_Vbuf);
754         es = NumEdge(); if ( es !=0 ) es *= GetStride(m_Ebuf);
755         fs = NumFace(); if ( fs !=0 ) fs *= GetStride(m_Fbuf);
756         hs = mHeapNum*sizeof(hval);
757         hm = mHeapMax*sizeof(hval);
758         
759         while ( pCurr != mHeap-1 ) {
760                 frees += *(pCurr);
761                 pCurr = mHeap + * (hpos*) (pCurr + FPOS);
762         }
763         frees *= sizeof(hval);
764         as = 0;
765         if ( m_Vbuf!=-1 ) as += mBuf[m_Vbuf].max * GetStride(m_Vbuf);
766         if ( m_Fbuf!=-1 ) as += mBuf[m_Fbuf].max * GetStride(m_Fbuf);
767         if ( m_Ebuf!=-1 ) as += mBuf[m_Ebuf].max * GetStride(m_Ebuf);
768         as += hm;
769
770         debug.Printf ( "NumVert:     %07.1fk (%d)\n", vs/1000.0, NumVert() );
771         debug.Printf ( "NumFace:     %07.1fk (%d)\n", fs/1000.0, NumFace() );
772         debug.Printf ( "NumEdge:     %07.1fk (%d)\n", es/1000.0, NumEdge() );
773         debug.Printf ( "Heap Size:   %07.1fk (%d)\n", hs/1000.0, mHeapNum );
774         debug.Printf ( "Free Size:   %07.1fk\n", frees/1000.0 );
775         debug.Printf ( "Heap Used:   %07.1fk (%5.1f%%)\n", (hs-frees)/1000.0, (hs-frees)*100.0/(vs+es+fs+hs-frees) );
776         debug.Printf ( "Heap Max:    %07.1fk\n", hm/1000.0 );   
777         debug.Printf ( "Total Used:  %07.1fk\n", (vs+es+fs+hs-frees)/1000.0 );
778         debug.Printf ( "Total Alloc: %07.1fk\n", as/1000.0 );
779         debug.Printf ( "Fragmentation: %f%%\n", (hm-(hs-frees))*100.0 / hm );
780 }
781
782
783 /*int Mesh::GetIndex ( int b, void* v )
784 {
785         if ( v == 0x0 ) return -1;
786         return ((char*) v - (char*) mBuf[b].data) / mBuf[b].stride;
787 }*/
788
789 int Mesh::FindPlyElem ( char typ )
790 {
791         for (int n=0; n < m_Ply.size(); n++) {
792                 if ( m_Ply[n]->type == typ ) return n;
793         }
794         return -1;
795 }
796
797 int Mesh::FindPlyProp ( int elem, std::string name )
798 {
799         for (int n=0; n < m_Ply[elem]->prop_list.size(); n++) {
800                 if ( m_Ply[elem]->prop_list[n].name.compare ( name)==0 )
801                         return n;
802         }
803         return -1;
804 }
805
806 void Mesh::LoadPly ( char* fname, float s  )
807 {
808 /*      int m_PlyCnt;
809         float m_PlyData[40];
810         char buf[1000];
811         char bword[1000];
812         std::string word;
813         Buffer b(1000);
814         int vnum, fnum, elem, cnt;
815         char typ;
816
817         if ( m_Mform == MFormat::UDef )
818                 CreateFVF ();
819
820         m_File.Open ( fname, FILE_READ | FILE_SEQUENTIAL );     
821         if ( !m_File.Valid() ) {
822                 error.PrintF ( "mesh", "Could not find file: %s\n", fname );
823                 error.Exit ();
824         }
825         
826         // Read header
827         m_File.ReadLine ( buf, 1000 );
828         b.ReadWord ( buf, bword ); word = bword;
829         if ( word.compare("ply" )!=0 ) {
830                 error.PrintF ( "Not a ply file. %s\n", fname );
831                 error.Exit ();
832         }
833
834         debug.Printf ( "Reading PLY.\n" ); 
835         while ( m_File.ReadLine ( buf, 1000 ) == FILE_STATUS_OK ) {
836                 b.ReadWord ( buf, bword );
837                 word = bword;
838                 if ( word.compare("comment" )!=0 ) {
839                         if ( word.compare("end_header")==0 ) break;
840                         if ( word.compare("property")==0 ) {
841                                 b.ReadWord ( buf, bword );
842                                 word = bword;
843                                 if ( word.compare("float")==0 ) typ = PLY_FLOAT;
844                                 if ( word.compare("float16")==0 ) typ = PLY_FLOAT;
845                                 if ( word.compare("float32")==0 ) typ = PLY_FLOAT;
846                                 if ( word.compare("int8")==0 ) typ = PLY_INT;
847                                 if ( word.compare("uint8")==0 ) typ = PLY_UINT;
848                                 if ( word.compare("list")==0) {
849                                         typ = PLY_LIST;
850                                         b.ReadWord ( buf, bword );
851                                         b.ReadWord ( buf, bword );
852                                 }
853                                 b.ReadWord ( buf, bword );
854                                 word = bword;
855                                 AddPlyProperty ( typ, word );
856                         }
857                         if ( word.compare("element" )==0 ) {
858                                 b.ReadWord ( buf, bword);       word = bword;
859                                 if ( word.compare("vertex")==0 ) {
860                                         b.ReadWord ( buf, bword);
861                                         vnum = atoi ( bword );
862                                         debug.Printf ( "  Verts: %d\n", vnum );
863                                         AddPlyElement ( PLY_VERTS, vnum );
864                                 }
865                                 if ( word.compare("face")==0 ) {
866                                         b.ReadWord ( buf, bword);
867                                         fnum = atoi ( bword );
868                                         debug.Printf ( "  Faces: %d\n", fnum );
869                                         AddPlyElement ( PLY_FACES, fnum );
870                                 }
871                         }
872                 }               
873         }
874
875         // Read data
876         int xi, yi, zi;
877         debug.Printf ( "  Reading verts..\n" ); 
878         elem = FindPlyElem ( PLY_VERTS );
879         xi = FindPlyProp ( elem, "x" );
880         yi = FindPlyProp ( elem, "y" );
881         zi = FindPlyProp ( elem, "z" );
882         if ( elem == -1 || xi == -1 || yi == -1 || zi == -1 ) {
883                 debug.Printf ( "ERROR: Vertex data not found.\n" );
884                 exit(-1);
885         }
886         for (int n=0; n < m_Ply[elem]->num; n++) {
887                 m_File.ReadLine ( buf, 1000 );
888                 for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) {
889                         b.ReadWord ( buf, bword );
890                         m_PlyData[ j ] = atof ( bword );
891                 }
892                 AddVert ( m_PlyData[xi]*s, m_PlyData[zi]*s, m_PlyData[yi]*s );
893         }
894
895         debug.Printf ( "  Reading faces..\n" );
896         elem = FindPlyElem ( PLY_FACES );
897         xi = FindPlyProp ( elem, "vertex_indices" );
898         if ( elem == -1 || xi == -1 ) {
899                 debug.Printf ( "ERROR: Face data not found.\n" );
900                 exit(-1);
901         }
902         for (int n=0; n < m_Ply[elem]->num; n++) {
903                 m_File.ReadLine ( buf, 1000 );
904                 m_PlyCnt = 0;
905                 for (int j=0; j < m_Ply[elem]->prop_list.size(); j++) {
906                         if ( m_Ply[elem]->prop_list[j].type == PLY_LIST ) {
907                                 b.ReadWord ( buf, bword );
908                                 cnt = atoi ( bword );   
909                                 m_PlyData[ m_PlyCnt++ ] = cnt;
910                                 for (int c =0; c < cnt; c++) {
911                                         b.ReadWord ( buf, bword );
912                                         m_PlyData[ m_PlyCnt++ ] = atof ( bword );
913                                 }
914                         } else {
915                                 b.ReadWord ( buf, bword );
916                                 m_PlyData[ m_PlyCnt++ ] = atof ( bword );
917                         }
918                 }
919                 if ( m_PlyData[xi] == 3 ) {
920                         //debug.Printf ( "    Face: %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] );
921                         AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3] );
922                 }
923                 
924                 if ( m_PlyData[xi] == 4 ) {
925                         //debug.Printf ( "    Face: %d, %d, %d, %d\n", (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4]);
926                         AddFaceFast ( (int) m_PlyData[xi+1], (int) m_PlyData[xi+2], (int) m_PlyData[xi+3], (int) m_PlyData[xi+4] );
927                 }
928         }
929
930         Measure ();
931         ComputeNormalsFVF ();           // !-- should be abstracted
932 */
933
934         //      UpdateMesh ();
935 }
936
937 void Mesh::AddPlyElement ( char typ, int n )
938 {
939         debug.Printf ( "  Element: %d, %d\n", typ, n );
940         PlyElement* p = new PlyElement;
941         p->num = n;
942         p->type = typ;
943         p->prop_list.clear ();
944         m_PlyCurrElem = m_Ply.size();
945         m_Ply.push_back ( p );
946 }
947
948 void Mesh::AddPlyProperty ( char typ, std::string name )
949 {
950         debug.Printf ( "  Property: %d, %s\n", typ, name.c_str() );
951         PlyProperty p;
952         p.name = name;
953         p.type = typ;
954         m_Ply [ m_PlyCurrElem ]->prop_list.push_back ( p );
955 }