1 /* ************************
2    Copyright Terrain Experts Inc.
3    Terrain Experts Inc (TERREX) reserves all rights to this source code
4    unless otherwise specified in writing by the President of TERREX.
5    This copyright may be updated in the future, in which case that version
6    supercedes this one.
7    -------------------
8    Terrex Experts Inc.
9    4400 East Broadway #314
10    Tucson, AZ  85711
11    info@terrex.com
12    Tel: (520) 323-7990
13    ************************
14    */
15 
16 /* trpage_geom.cpp
17     Methods for the trpgGeometry class.
18     This includes read and write methods.
19     You should only need to change something in here if you want to modify
20      what trpgGeometry contains.
21     */
22 
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 
27 #include <trpage_geom.h>
28 #include <trpage_read.h>
29 
30 #if defined(_WIN32)
31 #define ALIGNMENT_WORKAROUND    false
32 #else
33 #define ALIGNMENT_WORKAROUND    true
34 #endif
35 
36 // Constructor
trpgGeometry()37 trpgGeometry::trpgGeometry()
38 {
39     primType = Polygons;
40     normBind = Overall;
41     numPrim = 0;
42 }
~trpgGeometry()43 trpgGeometry::~trpgGeometry()
44 {
45 }
46 
47 // Reset function
Reset()48 void trpgGeometry::Reset()
49 {
50     primType = Polygons;
51     numPrim = 0;
52     primLength.resize(0);
53     materials.resize(0);
54     vertDataFloat.resize(0);
55     vertDataDouble.resize(0);
56     normBind = Overall;
57     normDataFloat.resize(0);
58     normDataDouble.resize(0);
59     colors.resize(0);
60     texData.resize(0);
61     edgeFlags.resize(0);
62 }
63 
64 // Set functions
SetPrimType(PrimType type)65 void trpgGeometry::SetPrimType(PrimType type)
66 {
67     primType = type;
68 }
SetPrimLengths(int num,const int * len)69 void trpgGeometry::SetPrimLengths(int num,const int *len)
70 {
71     if (num < 0)
72         return;
73 
74     numPrim = num;
75     for (int i=0;i<num;i++)
76         primLength.push_back(len[i]);
77 }
AddPrimLength(int len)78 void trpgGeometry::AddPrimLength(int len)
79 {
80     if (len < 0)
81         return;
82 
83     numPrim++;
84     primLength.push_back(len);
85 }
AddPrim()86 void trpgGeometry::AddPrim()
87 {
88     numPrim++;
89 }
SetNumPrims(int num)90 void trpgGeometry::SetNumPrims(int num)
91 {
92     numPrim = num;
93 }
SetNumMaterial(int no)94 void trpgGeometry::SetNumMaterial(int no)
95 {
96     if (no < 0)
97         return;
98 
99     materials.resize(no,-1);
100 }
SetMaterial(int which,int mat,bool isLocal)101 void trpgGeometry::SetMaterial(int which,int mat,bool isLocal)
102 {
103     if (which < 0 || which >= (int)materials.size())
104         return;
105 
106     materials[which] = (isLocal ? -(mat+1) : mat);
107 }
SetMaterials(int32 num,const int32 * mat)108 void trpgGeometry::SetMaterials(int32 num,const int32 *mat)
109 {
110     materials.resize(num);
111     for (int i=0;i<num;i++)
112         materials[i] = mat[i];
113 }
AddMaterial(int mat)114 int trpgGeometry::AddMaterial(int mat)
115 {
116     materials.push_back(mat);
117 
118     return materials.size()-1;
119 }
120 
121 // Geometry/color/normal/etc... set functions
SetVertices(int num,const float32 * data)122 void trpgGeometry::SetVertices(int num,const float32 *data)
123 {
124     if (num < 0)
125         return;
126 
127     vertDataFloat.resize(0);
128     vertDataDouble.resize(0);
129     for (int i=0;i<3*num;i++)
130         vertDataFloat.push_back(data[i]);
131 }
SetVertices(int num,const float64 * data)132 void trpgGeometry::SetVertices(int num,const float64 *data)
133 {
134     if (num < 0)
135         return;
136 
137     vertDataFloat.resize(0);
138     vertDataDouble.resize(0);
139     for (int i=0;i<3*num;i++)
140         vertDataDouble.push_back(data[i]);
141 }
AddVertex(DataType type,trpg3dPoint & pt)142 void trpgGeometry::AddVertex(DataType type,trpg3dPoint &pt)
143 {
144     if (type == FloatData) {
145         vertDataFloat.push_back(static_cast<float>(pt.x));
146         vertDataFloat.push_back(static_cast<float>(pt.y));
147         vertDataFloat.push_back(static_cast<float>(pt.z));
148     } else {
149         vertDataDouble.push_back(pt.x);
150         vertDataDouble.push_back(pt.y);
151         vertDataDouble.push_back(pt.z);
152     }
153 }
SetNormals(int num,BindType bind,const float32 * data)154 void trpgGeometry::SetNormals(int num,BindType bind,const float32 *data)
155 {
156     if (num < 0)
157         return;
158 
159     normBind = bind;
160     normDataFloat.resize(0);
161     normDataDouble.resize(0);
162     for (int i=0;i<3*num;i++)
163         normDataFloat.push_back(data[i]);
164 }
SetNormals(int num,BindType bind,const float64 * data)165 void trpgGeometry::SetNormals(int num,BindType bind,const float64 *data)
166 {
167     if (num <0)
168         return;
169 
170     normBind = bind;
171     normDataFloat.resize(0);
172     normDataDouble.resize(0);
173     for (int i=0;i<3*num;i++)
174         normDataDouble.push_back(data[i]);
175 }
AddNormal(DataType type,trpg3dPoint & pt)176 void trpgGeometry::AddNormal(DataType type,trpg3dPoint &pt)
177 {
178     if (type == FloatData) {
179         normDataFloat.push_back(static_cast<float>(pt.x));
180         normDataFloat.push_back(static_cast<float>(pt.y));
181         normDataFloat.push_back(static_cast<float>(pt.z));
182     } else {
183         normDataDouble.push_back(pt.x);
184         normDataDouble.push_back(pt.y);
185         normDataDouble.push_back(pt.z);
186     }
187 }
188 // Constructor
trpgColorInfo()189 trpgColorInfo::trpgColorInfo()
190 {
191     Reset();
192 }
~trpgColorInfo()193 trpgColorInfo::~trpgColorInfo()
194 {
195 }
Reset()196 void trpgColorInfo::Reset()
197 {
198     bind = 0;
199     type = 0;
200     data.resize(0);
201 }
SetColors(int num,ColorType type,BindType bind,const trpgColor * data)202 void trpgGeometry::SetColors(int num,ColorType type,BindType bind,const trpgColor *data)
203 {
204     trpgColorInfo ci;
205 
206     if (num < 0)
207         return;
208 
209     // Set up color list
210     ci.type = type;
211     ci.bind = bind;
212     for (int i=0;i<num;i++)
213         ci.data.push_back(data[i]);
214 
215     colors.push_back(ci);
216 }
217 // Constructor
trpgTexData()218 trpgTexData::trpgTexData()
219 {
220     bind = 0;
221 }
~trpgTexData()222 trpgTexData::~trpgTexData()
223 {
224 }
set(int num,int in_bind,const float32 * data)225 void trpgTexData::set(int num,int in_bind,const float32 *data)
226 {
227     bind = in_bind;
228     floatData.resize(0);
229     doubleData.resize(0);
230     for (int i=0;i<2*num;i++)
231         floatData.push_back(data[i]);
232 }
set(int num,int in_bind,const float64 * data)233 void trpgTexData::set(int num,int in_bind,const float64 *data)
234 {
235     bind = in_bind;
236     floatData.resize(0);
237     doubleData.resize(0);
238     for (int i=0;i<2*num;i++)
239         doubleData.push_back(data[i]);
240 }
Reset()241 void trpgTexData::Reset()
242 {
243     bind = 0;
244     floatData.resize(0);
245     doubleData.resize(0);
246 }
247 
SetTexCoords(int num,BindType bind,const float32 * data)248 void trpgGeometry::SetTexCoords(int num,BindType bind,const float32 *data)
249 {
250     if (num < 0)
251         return;
252 
253     trpgTexData td;
254     td.set(num,bind,data);
255     texData.push_back(td);
256 }
SetTexCoords(int num,BindType bind,const float64 * data)257 void trpgGeometry::SetTexCoords(int num,BindType bind,const float64 *data)
258 {
259     if (num < 0)
260         return;
261 
262     trpgTexData td;
263     td.set(num,bind,data);
264     texData.push_back(td);
265 }
AddTexCoord(DataType type,trpg2dPoint & pt,int n)266 void trpgGeometry::AddTexCoord(DataType type,trpg2dPoint &pt, int n)
267 {
268     if ((n<0) || (n >= (int)texData.size()))
269         return;
270     trpgTexData *td = &texData[n];
271 
272     if (type == FloatData) {
273         td->floatData.push_back(static_cast<float>(pt.x));
274         td->floatData.push_back(static_cast<float>(pt.y));
275     } else {
276         td->doubleData.push_back(pt.x);
277         td->doubleData.push_back(pt.y);
278     }
279 }
AddTexCoord(DataType type,std::vector<trpg2dPoint> & pts)280 void trpgGeometry::AddTexCoord(DataType type,std::vector<trpg2dPoint> &pts)
281 {
282     if (texData.size() != pts.size())
283         return;
284 
285     for (unsigned int loop = 0; loop < pts.size(); loop++ ) {
286         trpgTexData *td = &texData[loop];
287 
288         if (type == FloatData) {
289             td->floatData.push_back(static_cast<float>(pts[loop].x));
290             td->floatData.push_back(static_cast<float>(pts[loop].y));
291         } else {
292             td->doubleData.push_back(pts[loop].x);
293             td->doubleData.push_back(pts[loop].y);
294         }
295     }
296 }
AddTexCoords(BindType bind)297 void trpgGeometry::AddTexCoords(BindType bind)
298 {
299     trpgTexData td;
300     td.bind = bind;
301     texData.push_back(td);
302 }
SetEdgeFlags(int num,const char * flags)303 void trpgGeometry::SetEdgeFlags(int num,const char *flags)
304 {
305     if (num < 0)
306         return;
307 
308     edgeFlags.resize(0);
309     for (int i=0;i<num;i++)
310         edgeFlags.push_back(flags[i]);
311 }
312 
313 // Get methods
GetPrimType(PrimType & t) const314 bool trpgGeometry::GetPrimType(PrimType &t) const
315 {
316     if (!isValid()) return false;
317     t = (PrimType)primType;
318     return true;
319 }
GetNumPrims(int & n) const320 bool trpgGeometry::GetNumPrims(int &n) const
321 {
322     if (!isValid()) return false;
323     n = numPrim;
324     return true;
325 }
GetPrimLengths(int * ret) const326 bool trpgGeometry::GetPrimLengths(int *ret) const
327 {
328     if (!isValid()) return false;
329     for (int i=0;i<numPrim;i++)
330         ret[i] = primLength[i];
331     return true;
332 }
GetNumMaterial(int & n) const333 bool trpgGeometry::GetNumMaterial(int &n) const
334 {
335     if (!isValid()) return false;
336     n = materials.size();
337     return true;
338 }
GetMaterial(int id,int32 & m,bool & isLocal) const339 bool trpgGeometry::GetMaterial(int id,int32 &m,bool &isLocal) const
340 {
341     isLocal = false;
342     if (!isValid() || id < 0 || id >= (int)materials.size()) return false;
343     m = materials[id];
344     if (m < 0) {
345         m = -m - 1;
346         isLocal = true;
347     }
348     return true;
349 }
GetNumVertex(int & v) const350 bool trpgGeometry::GetNumVertex(int &v) const
351 {
352     if (!isValid()) return false;
353     int nvf = vertDataFloat.size();
354     int nvd = vertDataDouble.size();
355     v = MAX(nvf,nvd);
356     v = v / 3;
357     return true;
358 }
GetVertices(float32 * v) const359 bool trpgGeometry::GetVertices(float32 *v) const
360 {
361     unsigned int i;
362 
363     if (!isValid()) return false;
364     if (vertDataFloat.size() != 0)
365         for (i=0;i<vertDataFloat.size();i++)
366             v[i] = vertDataFloat[i];
367     else
368         for (i=0;i<vertDataDouble.size();i++)
369             v[i] = static_cast<float32>(vertDataDouble[i]);
370     return true;
371 }
GetVertices(float64 * v) const372 bool trpgGeometry::GetVertices(float64 *v) const
373 {
374     unsigned int i;
375 
376     if (!isValid()) return false;
377     if (vertDataFloat.size() != 0)
378         for (i=0;i<vertDataFloat.size();i++)
379             v[i] = vertDataFloat[i];
380     else
381         for (i=0;i<vertDataDouble.size();i++)
382             v[i] = vertDataDouble[i];
383     return true;
384 }
GetVertex(int n,trpg3dPoint & pt) const385 bool trpgGeometry::GetVertex(int n,trpg3dPoint &pt) const
386 {
387     int id = 3*n;
388     int idMax = 3*n+2;
389     if (id < 0 || (idMax >= (int)vertDataFloat.size() && idMax >= (int)vertDataDouble.size()))
390         return false;
391     if (vertDataFloat.size() > vertDataDouble.size()) {
392         pt.x = vertDataFloat[id];
393         pt.y = vertDataFloat[id+1];
394         pt.z = vertDataFloat[id+2];
395     } else {
396         pt.x = vertDataDouble[id];
397         pt.y = vertDataDouble[id+1];
398         pt.z = vertDataDouble[id+2];
399     }
400     return true;
401 }
GetNumNormal(int32 & n) const402 bool trpgGeometry::GetNumNormal(int32 &n) const
403 {
404     if (!isValid()) return false;
405     if (normDataFloat.size() != 0)
406     {
407         n = normDataFloat.size() / 3;
408         return true;
409     }
410     if (normDataDouble.size() != 0)
411     {
412         n = normDataDouble.size() / 3;
413         return true;
414     }
415     n = 0;
416     return false;
417 }
GetNormals(float32 * v) const418 bool trpgGeometry::GetNormals(float32 *v) const
419 {
420     unsigned int i;
421 
422     if (!isValid()) return false;
423     if (normDataFloat.size() != 0)
424         for (i=0;i<normDataFloat.size();i++)
425             v[i] = normDataFloat[i];
426     else
427         for (i=0;i<normDataDouble.size();i++)
428             v[i] = static_cast<float32>(normDataDouble[i]);
429     return true;
430 }
GetNormals(float64 * v) const431 bool trpgGeometry::GetNormals(float64 *v) const
432 {
433     unsigned int i;
434 
435     if (!isValid()) return false;
436     if (normDataFloat.size() != 0)
437         for (i=0;i<normDataFloat.size();i++)
438             v[i] = normDataFloat[i];
439     else
440         for (i=0;i<normDataDouble.size();i++)
441             v[i] = normDataDouble[i];
442     return true;
443 }
GetNumColorSets(int & n) const444 bool trpgGeometry::GetNumColorSets(int &n) const
445 {
446     if (!isValid()) return false;
447     n = colors.size();
448     return true;
449 }
GetColorSet(int id,trpgColorInfo * ci) const450 bool trpgGeometry::GetColorSet(int id,trpgColorInfo *ci) const
451 {
452     if (!isValid() || id < 0 || id >= (int)colors.size()) return false;
453     *ci = colors[id];
454     return true;
455 }
GetNumTexCoordSets(int & n) const456 bool trpgGeometry::GetNumTexCoordSets(int &n) const
457 {
458     if (!isValid()) return false;
459     n = texData.size();
460     return true;
461 }
GetTexCoordSet(int id,trpgTexData * tx) const462 bool trpgGeometry::GetTexCoordSet(int id,trpgTexData *tx) const
463 {
464     if (!isValid() || id < 0 || id >= (int)texData.size()) return false;
465     *tx = texData[id];
466     return true;
467 }
GetTexCoordSet(int id) const468 const trpgTexData *trpgGeometry::GetTexCoordSet(int id) const
469 {
470     if (!isValid() || id < 0 || id >= (int)texData.size()) return 0;
471     return &(texData[id]);
472 }
GetNumEdgeFlag(int & n) const473 bool trpgGeometry::GetNumEdgeFlag(int &n) const
474 {
475     if (!isValid()) return false;
476     n = edgeFlags.size();
477     return true;
478 }
GetEdgeFlags(char * e) const479 bool trpgGeometry::GetEdgeFlags(char *e) const
480 {
481     if (!isValid()) return false;
482     for (unsigned int i=0;i<edgeFlags.size();i++)
483         e[i] = edgeFlags[i];
484     return true;
485 }
486 
487 // Validity check
488 // Note: maybe I should do this sometime
isValid() const489 bool trpgGeometry::isValid() const
490 {
491     return true;
492 }
493 
494 // Write geometry fields.
495 // Order doesn't matter very much for this
Write(trpgWriteBuffer & buf)496 bool trpgGeometry::Write(trpgWriteBuffer &buf)
497 {
498     unsigned int i,j;
499 
500     if (!isValid())
501         return false;
502 
503     buf.Begin(TRPG_GEOMETRY);
504     /* Primitive info
505         Primitive Type
506          Number of primitives
507         Primitive array lengths
508         */
509     buf.Begin(TRPG_GEOM_PRIM);
510      buf.Add(primType);
511     buf.Add(numPrim);
512     if (primLength.size() != 0) {
513         buf.Add((uint8)1);
514         for (i=0;i<(unsigned int)numPrim;i++)
515             buf.Add(primLength[i]);
516     } else
517         buf.Add((uint8)0);
518     buf.End();
519 
520     /* Material info
521         Num materials
522         Material indices
523         */
524     if (materials.size() > 0) {
525         buf.Begin(TRPG_GEOM_MATERIAL);
526         buf.Add((int32)materials.size());
527         for (i=0;i<materials.size();i++)
528             buf.Add(materials[i]);
529         buf.End();
530     }
531 
532     /* Vertices
533         Float and Double should never both be here
534         Num vertex
535         Vertex data
536         */
537     if (vertDataFloat.size() > 0) {
538         buf.Begin(TRPG_GEOM_VERT32);
539         int32 num = vertDataFloat.size()/3;
540         buf.Add(num);
541         for (i=0;i<(unsigned int)3*num;i++)
542             buf.Add(vertDataFloat[i]);
543         buf.End();
544     }
545     if (vertDataDouble.size() > 0) {
546         buf.Begin(TRPG_GEOM_VERT64);
547         int32 num = vertDataDouble.size()/3;
548         buf.Add(num);
549         for (i=0;i<(unsigned int)3*num;i++)
550             buf.Add(vertDataDouble[i]);
551         buf.End();
552     }
553 
554     /* Normals
555         Normal binding
556         Num normals
557         Normal data
558         */
559     if (normDataFloat.size() > 0) {
560         buf.Begin(TRPG_GEOM_NORM32);
561         buf.Add((int32)normBind);
562         int32 num = normDataFloat.size()/3;
563         buf.Add(num);
564         for (i=0;i<(unsigned int)3*num;i++)
565             buf.Add(normDataFloat[i]);
566         buf.End();
567     }
568     if (normDataDouble.size() > 0) {
569         buf.Begin(TRPG_GEOM_NORM64);
570         buf.Add((int32)normBind);
571         int32 num = normDataDouble.size()/3;
572         buf.Add(num);
573         for (i=0;i<(unsigned int)3*num;i++)
574             buf.Add(normDataDouble[i]);
575         buf.End();
576     }
577 
578     /* Colors
579         Color binding
580         Num colors
581         Colors
582            */
583     if (colors.size() > 0) {
584         for (i=0;i<colors.size();i++) {
585             trpgColorInfo &ci = colors[i];
586             if (ci.data.size()) {
587                 buf.Begin(TRPG_GEOM_COLOR);
588                 buf.Add((int32)ci.type);
589                 buf.Add((int32)ci.bind);
590                 buf.Add((int32)ci.data.size());
591                 for (j=0;j<ci.data.size();j++)
592                     buf.Add(ci.data[j]);
593                 buf.End();
594             }
595         }
596     }
597 
598     /* Texture coordinates
599         Binding
600         Num coords
601         Texture coords
602         */
603     for (i=0;i<texData.size();i++) {
604         trpgTexData &td = texData[i];
605         if (td.floatData.size()) {
606             buf.Begin(TRPG_GEOM_TEX32);
607             buf.Add((int32)td.bind);
608             int32 num = td.floatData.size()/2;
609             buf.Add(num);
610             for (j=0;j<(unsigned int)num*2;j++)
611                 buf.Add(td.floatData[j]);
612             buf.End();
613         }
614         if (td.doubleData.size()) {
615             buf.Begin(TRPG_GEOM_TEX64);
616             buf.Add((int32)td.bind);
617             int32 num = td.doubleData.size()/2;
618             buf.Add(num);
619             for (j=0;j<(unsigned int)num*2;j++)
620                 buf.Add(td.doubleData[j]);
621             buf.End();
622         }
623     }
624 
625     // Edge flags (for triangle strips, etc..)
626     if (edgeFlags.size() > 0) {
627         buf.Begin(TRPG_GEOM_EFLAG);
628         buf.Add((int32)edgeFlags.size());
629         for (i=0;i<edgeFlags.size();i++)
630             buf.Add(edgeFlags[i]);
631         buf.End();
632     }
633 
634     buf.End();
635 
636     return true;
637 }
638 
639 // Geometry class is made up of individual tokens.
640 class geomCB : public trpgr_Callback {
641 public:
642     void *Parse(trpgToken,trpgReadBuffer &buf);
643     trpgGeometry *geom;
644 };
645 
Parse(trpgToken tok,trpgReadBuffer & buf)646 void *geomCB::Parse(trpgToken tok,trpgReadBuffer &buf)
647 {
648     int32 *iData;
649     int32 num,primType,bind,type;
650     float32 *fData;
651     float64 *dData;
652     trpgColor *cData;
653     char *charData;
654     uint8 hasPrimLen;
655 
656     try {
657         switch (tok) {
658         case TRPG_GEOM_PRIM:
659             buf.Get(primType);
660             geom->SetPrimType((trpgGeometry::PrimType)primType);
661             buf.Get(num);
662             if (num < 0) throw 1;
663             geom->SetNumPrims(num);
664             buf.Get(hasPrimLen);
665             if (hasPrimLen) {
666                 buf.GetArray(num,&iData);
667                 if (ALIGNMENT_WORKAROUND)
668                 {
669                     int32 *aligned;
670                     aligned = (int32 *)calloc (num, sizeof(int32));
671                     memcpy (aligned, iData, num * sizeof(int32));
672                     geom->SetPrimLengths(num, aligned);
673                     free (aligned);
674                 }
675                 else
676                     geom->SetPrimLengths(num,iData);
677             }
678             break;
679         case TRPG_GEOM_MATERIAL:
680             buf.Get(num);
681             if (num < 0) throw 1;
682             buf.GetArray(num,&iData);
683             if (ALIGNMENT_WORKAROUND)
684             {
685                 int32 *aligned;
686                 aligned = (int32 *)calloc (num, sizeof(int32));
687                 memcpy (aligned, iData, num * sizeof(int32));
688                 geom->SetMaterials(num,aligned);
689                 free (aligned);
690             }
691             else
692                 geom->SetMaterials(num,iData);
693             break;
694         case TRPG_GEOM_VERT32:
695             buf.Get(num);
696             if (num < 0) throw 1;
697             buf.GetArray(3*num,&fData);
698             if (ALIGNMENT_WORKAROUND)
699             {
700                 float32 *aligned;
701                 aligned = (float32 *)calloc (3*num, sizeof(float32));
702                 memcpy (aligned, fData, 3*num * sizeof(float32));
703                 geom->SetVertices(num,aligned);
704                 free (aligned);
705             }
706             else
707                 geom->SetVertices(num,fData);
708             break;
709         case TRPG_GEOM_VERT64:
710             buf.Get(num);
711             if (num < 0) throw 1;
712             buf.GetArray(3*num,&dData);
713             if (ALIGNMENT_WORKAROUND)
714             {
715                 float64 *aligned;
716                 aligned = (float64 *)calloc (3*num, sizeof(float64));
717                 memcpy (aligned, dData, 3*num * sizeof(float64));
718                 geom->SetVertices(num,aligned);
719                 free (aligned);
720             }
721             else
722                 geom->SetVertices(num,dData);
723             break;
724         case TRPG_GEOM_NORM32:
725             buf.Get(bind);
726             buf.Get(num);
727             if (num < 0) throw 1;
728             buf.GetArray(3*num,&fData);
729             if (ALIGNMENT_WORKAROUND)
730             {
731                 float32 *aligned;
732                 aligned = (float32 *)calloc (3*num, sizeof(float32));
733                 memcpy (aligned, fData, 3*num * sizeof(float32));
734                 geom->SetNormals(num,(trpgGeometry::BindType)bind,aligned);
735                 free (aligned);
736             }
737             else
738                 geom->SetNormals(num,(trpgGeometry::BindType)bind,fData);
739             break;
740         case TRPG_GEOM_NORM64:
741             buf.Get(bind);
742             buf.Get(num);
743             if (num < 0) throw 1;
744             buf.GetArray(3*num,&dData);
745             if (ALIGNMENT_WORKAROUND)
746             {
747                 float64 *aligned;
748                 aligned = (float64 *)calloc (3*num, sizeof(float64));
749                 memcpy (aligned, dData, 3*num * sizeof(float64));
750                 geom->SetNormals(num,(trpgGeometry::BindType)bind,aligned);
751                 free (aligned);
752             }
753             else
754                 geom->SetNormals(num,(trpgGeometry::BindType)bind,dData);
755             break;
756         case TRPG_GEOM_COLOR:
757             buf.Get(num);
758             if (num < 0) throw 1;
759             buf.Get(type);
760             buf.Get(bind);
761             buf.GetArray(num,&cData);
762             if (ALIGNMENT_WORKAROUND)
763             {
764                 trpgColor *aligned;
765                 aligned = (trpgColor *)calloc (num, sizeof(trpgColor));
766                 memcpy (aligned, cData, num * sizeof(trpgColor));
767                 geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,aligned);
768                 free (aligned);
769             }
770             else
771                 geom->SetColors(num,(trpgGeometry::ColorType)type,(trpgGeometry::BindType)bind,cData);
772             break;
773         case TRPG_GEOM_TEX32:
774             buf.Get(bind);
775             buf.Get(num);
776             if (num < 0) throw 1;
777             buf.GetArray(2*num,&fData);
778             if (ALIGNMENT_WORKAROUND)
779             {
780                 float32 *aligned;
781                 aligned = (float32 *)calloc (2*num, sizeof(float32));
782                 memcpy (aligned, fData, 2*num * sizeof(float32));
783                 geom->SetTexCoords(num,(trpgGeometry::BindType)bind,aligned);
784                 free (aligned);
785             }
786             else
787                 geom->SetTexCoords(num,(trpgGeometry::BindType)bind,fData);
788             break;
789         case TRPG_GEOM_TEX64:
790             buf.Get(bind);
791             buf.Get(num);
792             if (num < 0) throw 1;
793             buf.GetArray(2*num,&dData);
794             if (ALIGNMENT_WORKAROUND)
795             {
796                 float64 *aligned;
797                 aligned = (float64 *)calloc (2*num, sizeof(float64));
798                 memcpy (aligned, dData, 2*num * sizeof(float64));
799                 geom->SetTexCoords(num,(trpgGeometry::BindType)bind,aligned);
800                 free (aligned);
801             }
802             else
803                 geom->SetTexCoords(num,(trpgGeometry::BindType)bind,dData);
804             break;
805         case TRPG_GEOM_EFLAG:
806             buf.Get(num);
807             if (num < 0) throw 1;
808             buf.GetArray(num,&charData);
809             geom->SetEdgeFlags(num,charData);
810             break;
811         default:
812             // Skip
813             break;
814         }
815     }
816     catch (...) {
817         return NULL;
818     }
819 
820     return geom;
821 }
822 
823 // Read Geometry
Read(trpgReadBuffer & buf)824 bool trpgGeometry::Read(trpgReadBuffer &buf)
825 {
826     trpgr_Parser parse;
827     geomCB gcb;
828 
829     gcb.geom = this;
830     parse.AddCallback(TRPG_GEOM_PRIM,&gcb,false);
831     parse.AddCallback(TRPG_GEOM_MATERIAL,&gcb,false);
832     parse.AddCallback(TRPG_GEOM_VERT32,&gcb,false);
833     parse.AddCallback(TRPG_GEOM_VERT64,&gcb,false);
834     parse.AddCallback(TRPG_GEOM_NORM32,&gcb,false);
835     parse.AddCallback(TRPG_GEOM_NORM64,&gcb,false);
836     parse.AddCallback(TRPG_GEOM_COLOR,&gcb,false);
837     parse.AddCallback(TRPG_GEOM_TEX32,&gcb,false);
838     parse.AddCallback(TRPG_GEOM_TEX64,&gcb,false);
839     parse.AddCallback(TRPG_GEOM_EFLAG,&gcb,false);
840     parse.Parse(buf);
841 
842     return isValid();
843 }
844