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