source: OGRE/trunk/ogrenew/Tools/LightwaveConverter/src/lwReader.cpp @ 692

Revision 692, 51.6 KB checked in by mattausch, 19 years ago (diff)

adding ogre 1.2 and dependencies

Line 
1#include "lwReader.h"
2
3lwObject *lwReader::readObjectFromFile( const char *nfilename)
4{
5        lwObject *nobject = NULL;
6
7        ifstream *ifs = new ifstream();
8        try
9        {
10                ifs->open(nfilename, ios::in|ios::binary);
11                if (ifs->fail())
12                        cout << "Could not open file: " << nfilename << endl;
13                else
14                        nobject = readObjectFromStream( ifs );
15        }
16        catch (...)
17        {
18                if (nobject) delete nobject;
19                nobject = NULL;
20        }
21        ifs->close();
22        delete ifs;
23        return nobject;
24}
25
26lwObject *lwReader::readObjectFromStream( istream *nis)
27{
28        lwObject *nobject = 0;
29        chunksize = 0;
30        currentchunkid = 0;
31        formsize = 0;
32        flen = 0;
33
34        is = nis;
35
36        try
37        {
38                long id = getU4();
39                if ( id == ID_FORM )
40                {
41                        formsize = getU4();
42                        long type = getU4();
43                       
44                        switch(type)
45                        {
46                        case ID_LWO2:
47                                nobject = lwGetLWO2(); // FORM0000LWXX -> filelength - 12
48                                break;
49                        case ID_LWOB:
50                        case ID_LWLO:
51                                nobject = lwGetLWLO(); // FORM0000LWXX -> filelength - 12
52                                break;
53                        default:
54                                throw "File does not contain Lightwave object.";
55                        }
56                }
57                else
58                        throw "Not an IFF FORM file.";
59        }
60        catch (char *errstr)
61        {
62                cout << "Error near byte " << is->tellg() << " in chunk " << currentchunkid << " : " << errstr << endl;
63        }
64        catch (...)
65        {
66                if (nobject) delete nobject;
67                nobject = NULL;
68        }
69        return nobject;
70}
71
72
73lwObject *lwReader::lwGetLWLO()
74{
75        long filepos = is->tellg();
76        if (filepos == -1) return NULL;
77        long formstart = filepos;
78        long formend = filepos + formsize; // FORM0000LWXX -> filelength - 12
79
80        lwObject *object = new lwObject;
81        if ( !object ) return NULL;
82
83        lwLayer *layer = new lwLayer;
84        if ( !layer ) goto Fail;
85
86        lwSurface *surface;
87        unsigned int rlen;
88        unsigned long i;
89        while ( filepos < formend )
90        {
91                currentchunkid = getU4();
92                chunksize = getU4();
93                chunksize += chunksize & 1;
94
95                switch ( currentchunkid )
96                {
97                case ID_SRFS:
98                        if ( !lwGetTags(object->tags ))
99                                goto Fail;
100                        break;
101                case ID_LAYR:
102                        if ( object->layers.size() > 0 )
103                        {
104                                layer = new lwLayer;
105                                if ( !layer ) goto Fail;
106                        }
107                        object->layers.push_back(layer);
108
109
110                        flen = 0;
111                        layer->index = getU2();
112                        layer->flags = getU2();
113                        layer->name = getS0();
114
115                        rlen = flen;
116                        if ( rlen < 0 || rlen > chunksize ) goto Fail;
117                        if ( rlen < chunksize )
118                                is->seekg(chunksize - rlen, ios_base::cur);
119                        break;
120                case ID_PNTS:
121                        if ( !lwGetPoints(layer->points ))
122                                goto Fail;
123                        break;
124
125                case ID_POLS:
126                        if ( !lwGetLWOBPolygons(layer->polygons, layer->pointsoffset ))
127                                goto Fail;
128                        break;
129
130                case ID_SURF:
131                        surface = lwGetLWOBSurface(object );
132                        if ( surface ) object->surfaces.push_back( surface );
133                        break;
134
135                case ID_SHCP:
136                default:
137                        is->seekg(chunksize, ios_base::cur);
138                        break;
139                }
140
141                /* end of the file? */
142
143                filepos = is->tellg();
144                if ( filepos == -1 ) break;
145                if ( filepos > formend ) break; // read too much
146        }
147
148        if ( object->layers.size() == 0 )
149                object->layers.push_back(layer);
150
151        for (i = 0; i < object->layers.size(); i++)
152        {
153                layer = object->layers[i];
154                layer->lwGetBoundingBox();
155                layer->lwResolveVertexPoints();
156                layer->calculatePolygonNormals();
157                layer->lwGetPointPolygons();
158
159                if ( !layer->lwResolvePolySurfaces(object->surfaces, object->tags)) goto Fail;
160                layer->calculateVertexNormals();
161        }
162
163        return object;
164Fail:
165        if (object) delete object;
166        return NULL;
167}
168
169lwObject *lwReader::lwGetLWO2()
170{
171        long filepos = is->tellg();
172        if (filepos == -1) return NULL;
173        long formstart = filepos;
174        long formend = filepos + formsize; // FORM0000LWXX -> filelength - 12
175
176        /* allocate an object and a default layer */
177
178        lwObject *object = new lwObject;
179        if ( !object ) return NULL;
180
181        lwLayer *layer = new lwLayer;
182        if ( !layer ) goto Fail;
183
184        unsigned int i, rlen;
185
186        lwVMap *vmap;
187        lwEnvelope *envelope;
188        lwClip *clip;
189        lwSurface *surface;
190
191        /* process chunks as they're encountered */
192
193        while ( filepos < formend )
194        {
195                currentchunkid = getU4();
196                chunksize = getU4();
197                chunksize += chunksize & 1;
198
199                switch ( currentchunkid )
200                {
201                case ID_LAYR:
202                        if ( object->layers.size() > 0 )
203                        {
204                                layer = new lwLayer;
205                                if ( !layer ) goto Fail;
206                        }
207                        object->layers.push_back(layer);
208
209                        flen = 0;
210                        layer->index = getU2();
211                        layer->flags = getU2();
212                        layer->pivot.x = getF4();
213                        layer->pivot.y = getF4();
214                        layer->pivot.z = getF4();
215                        layer->name = getS0();
216
217                        rlen = flen;
218                        if ( rlen < 0 || rlen > chunksize ) goto Fail;
219                        if ( rlen <= chunksize - 2 )
220                                layer->parent = getU2();
221                        rlen = flen;
222                        if ( rlen < chunksize )
223                                is->seekg(chunksize - rlen, ios_base::cur);
224                        break;
225
226                case ID_PNTS:
227                        if ( !lwGetPoints(layer->points ))
228                                goto Fail;
229                        break;
230
231                case ID_POLS:
232                        if ( !lwGetPolygons(layer->polygons, layer->pointsoffset ))
233                                goto Fail;
234                        break;
235
236                case ID_VMAP:
237                case ID_VMAD:
238                        vmap = lwGetVMap(layer->pointsoffset, layer->polygonsoffset, currentchunkid == ID_VMAD );
239                        if ( !vmap ) goto Fail;
240                        layer->vmaps.push_back(vmap);
241                        break;
242
243                case ID_PTAG:
244                        if ( !lwGetPolygonTags(object->tags, object->tagsoffset, layer->polygons, layer->polygonsoffset ))
245                                goto Fail;
246                        break;
247
248                case ID_BBOX:
249                        flen = 0;
250                        layer->bboxmin.x = getF4();
251                        layer->bboxmin.y = getF4();
252                        layer->bboxmin.z = getF4();
253                        layer->bboxmax.x = getF4();
254                        layer->bboxmax.y = getF4();
255                        layer->bboxmax.z = getF4();
256                        rlen = flen;
257                        if ( rlen < 0 || rlen > chunksize ) goto Fail;
258                        if ( rlen < chunksize )
259                                is->seekg(chunksize - rlen, ios_base::cur );
260                        break;
261
262                case ID_TAGS:
263                        if ( !lwGetTags(object->tags ))
264                                goto Fail;
265                        break;
266
267                case ID_ENVL:
268                        envelope = lwGetEnvelope();
269                        if ( !envelope ) goto Fail;
270                        object->envelopes.push_back( envelope );
271                        break;
272
273                case ID_CLIP:
274                        clip = lwGetClip();
275                        if ( !clip ) goto Fail;
276                        object->clips.push_back( clip );
277                        break;
278
279                case ID_SURF:
280                        surface = lwGetSurface();
281                        if ( !surface ) goto Fail;
282                        object->surfaces.push_back( surface );
283                        break;
284
285                case ID_DESC:
286                case ID_TEXT:
287                case ID_ICON:
288                default:
289                        is->seekg(chunksize, ios_base::cur );
290                        break;
291                }
292
293                /* end of the file? */
294                filepos = is->tellg();
295                if ( filepos == -1 ) break;
296                if ( filepos > formend ) break; // read too much
297        }
298       
299        if ( object->layers.size() == 0 )
300                object->layers.push_back(layer);
301                               
302        for (i = 0; i < object->layers.size(); i++)
303        {
304                layer = object->layers[i];
305                if ( !layer->lwResolvePolySurfaces(object->surfaces, object->tags)) goto Fail;
306
307                layer->lwGetBoundingBox();
308                layer->lwResolveVertexPoints();
309                layer->calculatePolygonNormals();
310                layer->lwGetPointPolygons();
311                layer->calculateVertexNormals();
312                layer->lwGetPointVMaps();
313                layer->lwGetPolyVMaps();
314        }
315
316        return object;
317Fail:
318        if(object) delete object;
319        return NULL;
320}
321
322#define FLEN_ERROR INT_MIN
323
324#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 || OGRE_PLATFORM == OGRE_PLATFORM_LINUX
325/*
326=====================================================================
327revbytes()
328
329Reverses byte order in place.
330 
331INPUTS
332bp               bytes to reverse
333elsize  size of the underlying data type
334elcount  number of elements to swap
335
336RESULTS
337Reverses the byte order in each of elcount elements.
338
339This only needs to be defined on little-endian platforms, most
340notably Windows.  lwo2.h replaces this with a #define on big-endian
341platforms.
342===================================================================== */
343
344unsigned short lwReader::swappedShort(unsigned short w)
345{
346        unsigned short tmp;
347        tmp =  (w & 0x00ff);
348        tmp = ((w & 0xff00) >> 0x08) | (tmp << 0x08);
349        return tmp;
350}
351
352unsigned long lwReader::swappedLong(unsigned long w)
353{
354        unsigned long tmp;
355        tmp =  (w & 0x000000ff);
356        tmp = ((w & 0x0000ff00) >> 0x08) | (tmp << 0x08);
357        tmp = ((w & 0x00ff0000) >> 0x10) | (tmp << 0x08);
358        tmp = ((w & 0xff000000) >> 0x18) | (tmp << 0x08);
359        return tmp;
360}
361
362void lwReader::revbytes( void *bp, int elsize, int elcount )
363{
364        register char *p, *q;
365       
366        p = ( char * ) bp;
367       
368        if ( elsize == 2 ) {
369                q = p + 1;
370                while ( elcount-- ) {
371                        *p ^= *q;
372                        *q ^= *p;
373                        *p ^= *q;
374                        p += 2;
375                        q += 2;
376                }
377                return;
378        }
379       
380        while ( elcount-- ) {
381                q = p + elsize - 1;
382                while ( p < q ) {
383                        *p ^= *q;
384                        *q ^= *p;
385                        *p ^= *q;
386                        ++p;
387                        --q;
388                }
389                p += elsize >> 1;
390        }
391}
392#endif
393
394char *lwReader::getbytes( int size )
395{
396        char *data;
397       
398        if ( flen == FLEN_ERROR ) return NULL;
399        if ( size < 0 ) {
400                flen = FLEN_ERROR;
401                return NULL;
402        }
403        if ( size == 0 ) return NULL;
404
405        data = (char*)malloc(size);
406
407        if ( !data )
408        {
409                flen = FLEN_ERROR;
410                return NULL;
411        }
412       
413        is->read((char *)data, size);
414        if (is->gcount() != size)
415        {
416                flen = FLEN_ERROR;
417                free (data);
418                return NULL;
419        }
420       
421        flen += size;
422        return data;
423}
424
425
426void lwReader::skipbytes( int n )
427{
428        if ( flen == FLEN_ERROR ) return;
429       
430        is->seekg(n, ios_base::cur);
431       
432        if (is->bad())
433                flen = FLEN_ERROR;
434        else
435                flen += n;
436}
437
438short lwReader::getI2()
439{
440        short i;
441       
442        if ( flen == FLEN_ERROR ) return 0;
443       
444        is->read((char *)&i, 2);
445        if (is->gcount() != 2)
446        {
447                flen = FLEN_ERROR;
448                return 0;
449        }
450        revbytes( &i, 2, 1 );
451        flen += 2;
452        return i;
453}
454
455
456long lwReader::getI4()
457{
458        long i;
459       
460        if ( flen == FLEN_ERROR ) return 0;
461       
462        is->read((char *)&i, 4);
463        if (is->gcount() != 4) {
464                flen = FLEN_ERROR;
465                return 0;
466        }
467        revbytes( &i, 4, 1 );
468        flen += 4;
469        return i;
470}
471
472
473unsigned char lwReader::getU1()
474{
475        unsigned char i;
476       
477        if ( flen == FLEN_ERROR ) return 0;
478        is->read((char *)&i, 1);
479        if (is->gcount() != 1)
480        {
481                flen = FLEN_ERROR;
482                return 0;
483        }
484        flen += 1;
485        return i;
486}
487
488
489unsigned short lwReader::getU2()
490{
491        unsigned short i;
492       
493        if ( flen == FLEN_ERROR ) return 0;
494        is->read((char *)&i, 2);
495        if (is->gcount() != 2)
496        {
497                flen = FLEN_ERROR;
498                return 0;
499        }
500        revbytes( &i, 2, 1 );
501        flen += 2;
502        return i;
503}
504
505
506unsigned long lwReader::getU4()
507{
508        unsigned long i;
509       
510        if ( flen == FLEN_ERROR ) return 0;
511        is->read((char *)&i, 4);
512        if (is->gcount() != 4)
513        {
514                flen = FLEN_ERROR;
515                return 0;
516        }
517        revbytes( &i, 4, 1 );
518        flen += 4;
519        return i;
520}
521
522
523int lwReader::getVX()
524{
525        int i;
526        short c;
527       
528        if ( flen == FLEN_ERROR ) return 0;
529       
530        is->read((char *)&c, 2);
531       
532        if ( (c & 0x00FF) != 0xFF )
533        {
534                i = swappedShort(c);
535                flen += 2;
536        }
537        else
538        {
539                i = (swappedShort(c) & 0x00FF) << 16;
540                is->read((char *)&c, 2);
541                i |= swappedShort(c);
542                flen += 4;
543        }
544       
545        if ( is->bad() ) {
546                flen = FLEN_ERROR;
547                return 0;
548        }
549        return i;
550}
551
552
553float lwReader::getF4()
554{
555        float f;
556       
557        if ( flen == FLEN_ERROR ) return 0.0f;
558        is->read((char *)&f, 4);
559        if (is->gcount() != 4)
560        {
561                flen = FLEN_ERROR;
562                return 0.0f;
563        }
564        revbytes( &f, 4, 1 );
565        flen += 4;
566        return f;
567}
568
569char *lwReader::getS0()
570{
571        char *s;
572        int i, len, pos;
573        char c;
574
575        if ( flen == FLEN_ERROR ) return NULL;
576
577        pos = is->tellg();
578        if (pos == -1) return 0;
579
580        i = 0;
581        do
582        {
583                is->read(&c, 1);
584                i ++;
585        }
586        while (c > 0);
587
588        if ( i == 1 ) // word align
589        {
590                is->read(&c, 1);
591                flen += 2;
592                return NULL;
593        }
594
595        len = i + ( i & 1 );
596
597        s = (char *)malloc(len);
598        if ( !s )
599        {
600                flen = FLEN_ERROR;
601                return NULL;
602        }
603
604        is->seekg(pos, ios_base::beg);
605        if (is->bad())
606        {
607                flen = FLEN_ERROR;
608                return NULL;
609        }
610
611        is->read(s, len);
612        if (is->gcount() != len)
613        {
614                flen = FLEN_ERROR;
615                return NULL;
616        }
617       
618        flen += len;
619        return s;
620}
621
622short lwReader::sgetI2( char **bp )
623{
624        short i;
625       
626        if ( flen == FLEN_ERROR ) return 0;
627        memcpy( &i, *bp, 2 );
628        revbytes( &i, 2, 1 );
629        flen += 2;
630        *bp += 2;
631        return i;
632}
633
634
635long lwReader::sgetI4( char **bp )
636{
637        long i;
638       
639        if ( flen == FLEN_ERROR ) return 0;
640        memcpy( &i, *bp, 4 );
641        revbytes( &i, 4, 1 );
642        flen += 4;
643        *bp += 4;
644        return i;
645}
646
647
648unsigned char lwReader::sgetU1( char **bp )
649{
650        unsigned char c;
651       
652        if ( flen == FLEN_ERROR ) return 0;
653        c = **bp;
654        flen += 1;
655        *bp++;
656        return c;
657}
658
659unsigned short lwReader::sgetU2(char **bp )
660{
661        unsigned char *buf = (unsigned char *)*bp;
662        unsigned short i;
663       
664        if ( flen == FLEN_ERROR ) return 0;
665        i = ( buf[ 0 ] << 8 ) | buf[ 1 ];
666        flen += 2;
667        *bp += 2;
668        return i;
669}
670
671unsigned long lwReader::sgetU4( char **bp )
672{
673        unsigned long i;
674       
675        if ( flen == FLEN_ERROR ) return 0;
676        memcpy( &i, *bp, 4 );
677        revbytes( &i, 4, 1 );
678        flen += 4;
679        *bp += 4;
680        return i;
681}
682
683int lwReader::sgetVX( char **bp )
684{
685        unsigned char *buf = (unsigned char *)*bp;
686        int i;
687       
688        if ( flen == FLEN_ERROR ) return 0;
689       
690        if ( buf[ 0 ] != 0xFF )
691        {
692                i = buf[ 0 ] << 8 | buf[ 1 ];
693                flen += 2;
694                *bp += 2;
695        }
696        else
697        {
698                i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
699                flen += 4;
700                *bp += 4;
701        }
702        return i;
703}
704
705
706float lwReader::sgetF4( char **bp )
707{
708        float f;
709       
710        if ( flen == FLEN_ERROR ) return 0.0f;
711        memcpy( &f, *bp, 4 );
712        revbytes( &f, 4, 1 );
713        flen += 4;
714        *bp += 4;
715        return f;
716}
717
718
719char *lwReader::sgetS0( char **bp )
720{
721        char *s;
722        const char *buf = (const char *)*bp;
723        unsigned int len;
724       
725        if ( flen == FLEN_ERROR ) return NULL;
726       
727        len = strlen( buf ) + 1;
728        if ( len == 1 ) {
729                flen += 2;
730                *bp += 2;
731                return NULL;
732        }
733        len += len & 1;
734        s = (char *)malloc(len);
735        if ( !s )
736        {
737                flen = FLEN_ERROR;
738                return NULL;
739        }
740       
741        memcpy( s, buf, len );
742        flen += len;
743        *bp += len;
744        return s;
745}
746
747lwClip *lwReader::lwGetClip()
748{
749        lwClip *clip;
750        lwPlugin *filt;
751        unsigned int id;
752        unsigned short sz;
753        unsigned int pos, rlen;
754       
755       
756        /* allocate the Clip structure */
757       
758        clip = new lwClip;
759        if ( !clip ) goto Fail;
760       
761        /* remember where we started */
762       
763        flen = 0;
764        pos = is->tellg();
765       
766        /* index */
767       
768        clip->index = getI4();
769       
770        /* first subchunk header */
771       
772        clip->type = getU4();
773        sz = getU2();
774        if ( 0 > flen ) goto Fail;
775       
776        sz += sz & 1;
777        flen = 0;
778
779        switch ( clip->type )
780        {
781        case ID_STIL:
782                {
783                        lwClipStill *still = new lwClipStill;
784                        still->name = getS0();
785                        clip->source.still = still;
786                }
787                break;
788               
789        case ID_ISEQ:
790                {
791                        lwClipSeq *seq = new lwClipSeq;
792                        seq->digits  = getU1();
793                        seq->flags   = getU1();
794                        seq->offset  = getI2();
795                        getU2();  /* reserved */
796                        seq->start   = getI2();
797                        seq->end     = getI2();
798                        seq->prefix  = getS0();
799                        seq->suffix  = getS0();
800                        clip->source.seq = seq;
801                }
802                break;
803               
804        case ID_ANIM:
805                {
806                        lwClipAnim *anim = new lwClipAnim;
807                        anim->name = getS0();
808                        anim->server = getS0();
809                        rlen = flen;
810                        anim->data = getbytes( sz - rlen );
811                        clip->source.anim = anim;
812                }
813                break;
814               
815        case ID_XREF:
816                {
817                        lwClipXRef *xref = new lwClipXRef;
818                        xref->index  = getI4();
819                        xref->string = getS0();
820                        clip->source.xref = xref;
821                }
822                break;
823               
824        case ID_STCC:
825                {
826                        lwClipCycle *cycle = new lwClipCycle;
827                        cycle->lo   = getI2();
828                        cycle->hi   = getI2();
829                        cycle->name = getS0();
830                        clip->source.cycle = cycle;
831                }
832                break;
833               
834        default:
835                break;
836        }
837       
838        /* error while reading current subchunk? */
839       
840        rlen = flen;
841        if ( rlen < 0 || rlen > sz ) goto Fail;
842       
843        /* skip unread parts of the current subchunk */
844       
845        if ( rlen < sz )
846                is->seekg(sz - rlen, ios_base::cur );
847       
848        /* end of the CLIP chunk? */
849       
850        rlen = is->tellg();
851        rlen -= pos;
852        if ( chunksize < rlen ) goto Fail;
853        if ( chunksize == rlen )
854                return clip;
855       
856        /* process subchunks as they're encountered */
857       
858        id = getU4();
859        sz = getU2();
860        if ( 0 > flen ) goto Fail;
861       
862        for (;;) {
863                sz += sz & 1;
864                flen = 0;
865               
866                switch ( id ) {
867                case ID_TIME:
868            clip->start_time = getF4();
869            clip->duration = getF4();
870            clip->frame_rate = getF4();
871            break;
872                       
873                case ID_CONT:
874            clip->contrast.val = getF4();
875            clip->contrast.eindex = getVX();
876            break;
877                       
878                case ID_BRIT:
879            clip->brightness.val = getF4();
880            clip->brightness.eindex = getVX();
881            break;
882                       
883                case ID_SATR:
884            clip->saturation.val = getF4();
885            clip->saturation.eindex = getVX();
886            break;
887                       
888                case ID_HUE:
889            clip->hue.val = getF4();
890            clip->hue.eindex = getVX();
891            break;
892                       
893                case ID_GAMM:
894            clip->gamma.val = getF4();
895            clip->gamma.eindex = getVX();
896            break;
897                       
898                case ID_NEGA:
899            clip->negative = getU2();
900            break;
901                       
902                case ID_IFLT:
903                case ID_PFLT:
904            filt = new lwPlugin;
905            if ( !filt ) goto Fail;
906                       
907            filt->name = getS0();
908            filt->flags = getU2();
909            rlen = flen;
910            filt->data = getbytes( sz - rlen );
911                       
912            if ( id == ID_IFLT )
913                                clip->ifilters.push_back(filt);
914            else
915                                clip->pfilters.push_back(filt);
916
917            break;
918                       
919                default:
920            break;
921                }
922               
923                /* error while reading current subchunk? */
924               
925                rlen = flen;
926                if ( rlen < 0 || rlen > sz ) goto Fail;
927               
928                /* skip unread parts of the current subchunk */
929               
930                if ( rlen < sz )
931                        is->seekg(sz - rlen, ios_base::cur );
932               
933                /* end of the CLIP chunk? */
934               
935                rlen = is->tellg();
936                rlen -= pos;
937                if ( chunksize < rlen ) goto Fail;
938                if ( chunksize == rlen ) break;
939               
940                /* get the next chunk header */
941               
942                flen = 0;
943                id = getU4();
944                sz = getU2();
945                if ( 6 != flen ) goto Fail;
946        }
947       
948        return clip;
949       
950Fail:
951        delete clip;
952        return NULL;
953}
954
955lwEnvelope *lwReader::lwGetEnvelope()
956{
957        lwEnvelope *env;
958        lwKey *key;
959        lwPlugin *plug;
960        unsigned int id;
961        unsigned short sz;
962        float f[ 4 ];
963        int i, nparams, pos;
964        unsigned int rlen;
965       
966        /* allocate the Envelope structure */
967       
968        env = new lwEnvelope;
969        if ( !env ) goto Fail;
970       
971        /* remember where we started */
972       
973        flen = 0;
974        pos = is->tellg();
975       
976        /* index */
977       
978        env->index = getVX();
979       
980        /* first subchunk header */
981       
982        id = getU4();
983        sz = getU2();
984        if ( 0 > flen ) goto Fail;
985       
986        /* process subchunks as they're encountered */
987       
988        for (;;) {
989                sz += sz & 1;
990                flen = 0;
991               
992                switch ( id ) {
993                case ID_TYPE:
994            env->type = getU2();
995            break;
996                       
997                case ID_NAME:
998            env->name = getS0();
999            break;
1000                       
1001                case ID_PRE:
1002            env->behavior[ 0 ] = getU2();
1003            break;
1004                       
1005                case ID_POST:
1006            env->behavior[ 1 ] = getU2();
1007            break;
1008                       
1009                case ID_KEY:
1010                        key = env->addKey(getF4(), getF4());
1011            break;
1012                       
1013                case ID_SPAN:
1014            if ( !key ) goto Fail;
1015            key->shape = getU4();
1016                       
1017            nparams = ( sz - 4 ) / 4;
1018            if ( nparams > 4 ) nparams = 4;
1019            for ( i = 0; i < nparams; i++ )
1020                                f[ i ] = getF4();
1021                       
1022            switch ( key->shape ) {
1023                        case ID_TCB:
1024                                key->tension = f[ 0 ];
1025                                key->continuity = f[ 1 ];
1026                                key->bias = f[ 2 ];
1027                                break;
1028                               
1029                        case ID_BEZI:
1030                        case ID_HERM:
1031                        case ID_BEZ2:
1032                                for ( i = 0; i < nparams; i++ )
1033                                        key->param[ i ] = f[ i ];
1034                                break;
1035            }
1036            break;
1037                       
1038                        case ID_CHAN:
1039                                plug = new lwPlugin;
1040                                if ( !plug ) goto Fail;
1041                               
1042                                plug->name = getS0();
1043                                plug->flags = getU2();
1044                                plug->data = getbytes( sz - flen );
1045                               
1046                                env->cfilters.push_back( plug );
1047                                env->ncfilters++;
1048                                break;
1049                               
1050                        default:
1051                                break;
1052                }
1053               
1054                /* error while reading current subchunk? */
1055               
1056                rlen = flen;
1057                if ( rlen < 0 || rlen > sz ) goto Fail;
1058               
1059                /* skip unread parts of the current subchunk */
1060               
1061                if ( rlen < sz )
1062                        is->seekg(sz - rlen, ios_base::cur );
1063               
1064                /* end of the ENVL chunk? */
1065               
1066                rlen = is->tellg();
1067                rlen -= pos;
1068                if ( chunksize < rlen ) goto Fail;
1069                if ( chunksize == rlen ) break;
1070               
1071                /* get the next subchunk header */
1072               
1073                flen = 0;
1074                id = getU4();
1075                sz = getU2();
1076                if ( 6 != flen ) goto Fail;
1077        }
1078       
1079        return env;
1080       
1081Fail:
1082        delete env;
1083        return NULL;
1084}
1085
1086/*
1087======================================================================
1088lwGetPoints()
1089
1090  Read point records from a PNTS chunk in an LWO2 file.  The points are
1091  added to the array in the lwPointags.
1092====================================================================== */
1093
1094int lwReader::lwGetPoints( vpoints &points )
1095{
1096        if ( chunksize == 1 ) return 1;
1097
1098        int npoints;
1099
1100        npoints = chunksize / 12;
1101
1102        int rpoints = npoints >= 4096 ? 4096 : npoints;
1103        float *f = (float *)malloc(rpoints * 3 * sizeof(float));
1104
1105        while(npoints > 0)
1106        {
1107                is->read((char *)f, rpoints * 3 * sizeof(float));
1108                revbytes( f, sizeof(float), rpoints * 3 );
1109                for (int i = 0 ; i < rpoints * 3; i += 3 )
1110                        points.push_back(new lwPoint(f[ i ], f[ i + 1 ], f[ i + 2 ]));
1111
1112                npoints -= rpoints;
1113                rpoints = npoints >= 4096 ? 4096 : npoints;     
1114        }
1115
1116        free(f);
1117        return 1;
1118}
1119
1120/*
1121======================================================================
1122lwGetPolygons5()
1123
1124Read polygon records from a POLS chunk in an LWOB file. The polygons
1125are added to the array in the vpolygons.
1126======================================================================*/
1127
1128int lwReader::lwGetLWOBPolygons( vpolygons &polygons, int ptoffset )
1129{
1130        lwPolygon *polygon;
1131
1132        char *buf, *bp;
1133        int i, j, k, nv, nvertices, npolygons;
1134
1135        if ( chunksize == 0 ) return 1;
1136
1137        /* read the whole chunk */
1138
1139        flen = 0;
1140        buf = getbytes( chunksize );
1141        if ( !buf ) goto Fail;
1142
1143        /* count the polygons and vertices */
1144
1145        nvertices = 0;
1146        npolygons = 0;
1147        bp = buf;
1148
1149        while ( bp < buf + chunksize )
1150        {
1151                nv = sgetU2( &bp );
1152                nvertices += nv;
1153                npolygons++;
1154                bp += 2 * nv;
1155                i = sgetI2( &bp );
1156                if ( i < 0 ) bp += 2;           /* detail polygons */
1157        }
1158
1159        k = 0;
1160        bp = buf;
1161
1162        for ( i = 0; i < npolygons; i++ )
1163        {
1164                polygon = new lwPolygon;
1165                nv = sgetU2( &bp );
1166
1167                polygon->type = ID_FACE;
1168                for ( j = 0; j < nv; j++ )
1169                        polygon->vertices.push_back(new lwVertex(sgetU2( &bp ) + ptoffset));
1170
1171                j = sgetI2( &bp );
1172                if ( j < 0 ) {
1173                        j = -j;
1174                        bp += 2;
1175                }
1176                j -= 1;
1177
1178                polygon->surfidx = j;
1179                polygons.push_back(polygon);
1180        }
1181
1182        free(buf);
1183        return 1;
1184
1185Fail:
1186        free(buf);
1187        return 0;
1188}
1189
1190int lwReader::lwGetPolygons( vpolygons &polygons, int ptoffset )
1191{
1192        lwPolygon *polygon;
1193        char *buf, *bp;
1194
1195        int i, j, flags, nv, nvertices, npolygons;
1196        unsigned int type;     
1197       
1198        if ( chunksize == 0 ) return 1;
1199       
1200        /* read the whole chunk */
1201       
1202        flen = 0;
1203        type = getU4();
1204        buf = getbytes( chunksize - 4 );
1205        if ( chunksize != flen ) goto Fail;
1206       
1207        /* count the polygons and vertices */
1208       
1209        nvertices = 0;
1210        npolygons = 0;
1211        bp = buf;
1212       
1213        while ( bp < buf + chunksize - 4 )
1214        {
1215                nv = sgetU2( &bp );
1216                nv &= 0x03FF;
1217                nvertices += nv;
1218                npolygons++;
1219                for ( i = 0; i < nv; i++ )
1220                        j = sgetVX( &bp );
1221        }
1222       
1223        /* fill in the new polygons */
1224
1225        bp = buf;
1226       
1227        for ( i = 0; i < npolygons; i++ )
1228        {
1229                nv = sgetU2( &bp );
1230                flags = nv & 0xFC00;
1231                nv &= 0x03FF;
1232               
1233                polygon = new lwPolygon;
1234               
1235                polygon->flags = flags;
1236                polygon->type = type;
1237
1238                for (j = 0; j < nv; j++ )
1239                        polygon->vertices.push_back(new lwVertex( sgetVX( &bp ) + ptoffset ));
1240
1241                polygons.push_back(polygon);
1242        }
1243       
1244        free(buf);
1245        return 1;
1246       
1247Fail:
1248        free(buf);
1249        return 0;
1250}
1251
1252/*
1253======================================================================
1254lwGetTags()
1255
1256  Read tag strings from a TAGS chunk in an LWO2 file.  The tags are
1257  added to the lwTag array.
1258====================================================================== */
1259
1260int lwReader::lwGetTags( vtags &tags )
1261{
1262        char *buf, *bp;
1263       
1264        if ( chunksize == 0 ) return 1;
1265       
1266        /* read the whole chunk */
1267       
1268        flen = 0;
1269        buf = getbytes( chunksize );
1270        if ( !buf ) return 0;
1271       
1272        bp = buf;
1273        while ( bp < buf + chunksize )
1274                tags.push_back( sgetS0( &bp ));
1275
1276        free(buf);
1277        return 1;
1278}
1279
1280
1281/*
1282======================================================================
1283lwGetPolygonTags()
1284
1285  Read polygon tags from a PTAG chunk in an LWO2 file.
1286====================================================================== */
1287
1288int lwReader::lwGetPolygonTags( vtags &tags, int tagsoffset, vpolygons &polygons, int polygonsoffset )
1289{
1290        unsigned int type;
1291        unsigned int rlen;
1292        int     i, j;
1293       
1294        flen = 0;
1295        type = getU4();
1296        rlen = flen;
1297        if ( rlen < 0 ) return 0;
1298       
1299        if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
1300                is->seekg(chunksize - 4, ios_base::cur );
1301                return 1;
1302        }
1303       
1304        switch ( type )
1305        {
1306        case ID_SURF:
1307                while ( rlen < chunksize )
1308                {
1309                        i = getVX() + polygonsoffset;
1310                        j = getVX() + tagsoffset;
1311                       
1312                        rlen = flen;
1313                        if ( rlen < 0 || rlen > chunksize ) return 0;
1314                       
1315                        polygons[ i ]->surface = 0;
1316                        polygons[ i ]->surfidx = j;
1317                }
1318                break;
1319        case ID_PART:
1320                while ( rlen < chunksize )
1321                {
1322                        i = getVX() + polygonsoffset;
1323                        j = getVX() + tagsoffset;
1324                        rlen = flen;
1325                        if ( rlen < 0 || rlen > chunksize ) return 0;
1326                       
1327                        polygons[ i ]->part = j;
1328                       
1329                }
1330                break;
1331        case ID_SMGP:
1332                while ( rlen < chunksize )
1333                {
1334                        i = getVX() + polygonsoffset;
1335                        j = getVX() + tagsoffset;
1336                        rlen = flen;
1337                        if ( rlen < 0 || rlen > chunksize ) return 0;
1338                       
1339                        polygons[ i ]->smoothgrp = j;
1340                       
1341                }
1342                break;
1343        }
1344       
1345       
1346        return 1;
1347}
1348
1349/*
1350======================================================================
1351lwGetTHeader()
1352
1353  Read a texture map header from a SURF.BLOK in an LWO2 file.  This is
1354  the first subchunk in a BLOK, and its contents are common to all three
1355  texture types.
1356  ======================================================================
1357*/
1358
1359int lwReader::lwGetTHeader( int hsz, lwTexture &tex )
1360{
1361        unsigned int id;
1362        unsigned short sz;
1363        int pos, rlen;
1364       
1365        /* remember where we started */
1366       
1367        flen = 0;
1368        pos = is->tellg();
1369       
1370        /* ordinal string */
1371       
1372        tex.ord = getS0();
1373       
1374        /* first subchunk header */
1375       
1376        id = getU4();
1377        sz = getU2();
1378        if ( 0 > flen ) return 0;
1379       
1380        /* process subchunks as they're encountered */
1381       
1382        for (;;) {
1383                sz += sz & 1;
1384                flen = 0;
1385               
1386                switch ( id ) {
1387                case ID_CHAN:
1388                        tex.chan = getU4();
1389                        break;
1390                       
1391                case ID_OPAC:
1392                        tex.opac_type = getU2();
1393                        tex.opacity.val = getF4();
1394                        tex.opacity.eindex = getVX();
1395                        break;
1396                       
1397                case ID_ENAB:
1398                        tex.enabled = getU2();
1399                        break;
1400                       
1401                case ID_NEGA:
1402                        tex.negative = getU2();
1403                        break;
1404                       
1405                case ID_AXIS:
1406                        tex.axis = getU2();
1407                        break;
1408                       
1409                default:
1410                        break;
1411                }
1412               
1413                /* error while reading current subchunk? */
1414               
1415                rlen = flen;
1416                if ( rlen < 0 || rlen > sz ) return 0;
1417               
1418                /* skip unread parts of the current subchunk */
1419               
1420                if ( rlen < sz )
1421                        is->seekg(sz - rlen, ios_base::cur );
1422               
1423                /* end of the texture header subchunk? */
1424               
1425                int fpos = is->tellg();
1426                if ( fpos == -1 ) break;
1427                if ( hsz + pos <= fpos ) break;
1428
1429//              if ( hsz + pos <= is->tellg())
1430//                      break;
1431               
1432                /* get the next subchunk header */
1433               
1434                flen = 0;
1435                id = getU4();
1436                sz = getU2();
1437                if ( 6 != flen ) return 0;
1438        };
1439       
1440        int g = is->tellg();
1441        flen = g - pos;
1442        return 1;
1443}
1444
1445/*======================================================================
1446lwGetTMap()
1447
1448  Read a texture map from a SURF.BLOK in an LWO2 file.  The TMAP
1449  defines the mapping from texture to world or object coordinates.
1450====================================================================== */
1451
1452int lwReader::lwGetTMap( int tmapsz, lwTMap &tmap )
1453{
1454        unsigned int id;
1455        unsigned short sz;
1456        int rlen, pos, i;
1457       
1458        pos = is->tellg();
1459        id = getU4();
1460        sz = getU2();
1461        if ( 0 > flen ) return 0;
1462       
1463        for (;;) {
1464                sz += sz & 1;
1465                flen = 0;
1466               
1467                switch ( id ) {
1468                case ID_SIZE:
1469                        for ( i = 0; i < 3; i++ )
1470                                tmap.size.val[ i ] = getF4();
1471                        tmap.size.eindex = getVX();
1472                        break;
1473                       
1474                case ID_CNTR:
1475                        for ( i = 0; i < 3; i++ )
1476                                tmap.center.val[ i ] = getF4();
1477                        tmap.center.eindex = getVX();
1478                        break;
1479                       
1480                case ID_ROTA:
1481                        for ( i = 0; i < 3; i++ )
1482                                tmap.rotate.val[ i ] = getF4();
1483                        tmap.rotate.eindex = getVX();
1484                        break;
1485                       
1486                case ID_FALL:
1487                        tmap.fall_type = getU2();
1488                        for ( i = 0; i < 3; i++ )
1489                                tmap.falloff.val[ i ] = getF4();
1490                        tmap.falloff.eindex = getVX();
1491                        break;
1492                       
1493                case ID_OREF:
1494                        tmap.ref_object = getS0();
1495                        break;
1496                       
1497                case ID_CSYS:
1498                        tmap.coord_sys = getU2();
1499                        break;
1500                       
1501                default:
1502                        break;
1503                }
1504               
1505                /* error while reading the current subchunk? */
1506               
1507                rlen = flen;
1508                if ( rlen < 0 || rlen > sz ) return 0;
1509               
1510                /* skip unread parts of the current subchunk */
1511               
1512                if ( rlen < sz )
1513                        is->seekg(sz - rlen, ios_base::cur );
1514               
1515                /* end of the TMAP subchunk? */
1516                int fpos = is->tellg();
1517                if ( fpos == -1 ) break;
1518                if ( tmapsz + pos <= fpos ) break;
1519               
1520//              if ( tmapsz + pos <= is->tellg() )
1521//                      break;
1522               
1523                /* get the next subchunk header */
1524               
1525                flen = 0;
1526                id = getU4();
1527                sz = getU2();
1528                if ( 6 != flen ) return 0;
1529        };
1530       
1531        int g = is->tellg();
1532        flen = g - pos;
1533        return 1;
1534}
1535
1536/*======================================================================
1537lwGetImageMap()
1538
1539Read an lwImageMap from a SURF.BLOK in an LWO2 file.
1540====================================================================== */
1541
1542lwImageMap *lwReader::lwGetImageMap( int rsz, lwTexture &tex )
1543{
1544        unsigned int id;
1545        unsigned short sz;
1546        int rlen, pos;
1547       
1548        pos = is->tellg();
1549        id = getU4();
1550        sz = getU2();
1551        if ( 0 > flen ) return 0;
1552
1553        lwImageMap *imap = new lwImageMap;
1554        if (!imap) return NULL;
1555
1556        for (;;) {
1557                sz += sz & 1;
1558                flen = 0;
1559               
1560                switch ( id ) {
1561                case ID_TMAP:
1562                        if ( !lwGetTMap( sz, tex.tmap )) return 0;
1563                        break;
1564                       
1565                case ID_PROJ:
1566                        imap->projection = getU2();
1567                        break;
1568                       
1569                case ID_VMAP:
1570                        imap->vmap_name = getS0();
1571                        break;
1572                       
1573                case ID_AXIS:
1574                        imap->axis = getU2();
1575                        break;
1576                       
1577                case ID_IMAG:
1578                        imap->cindex = getVX();
1579                        break;
1580                       
1581                case ID_WRAP:
1582                        imap->wrapw_type = getU2();
1583                        imap->wraph_type = getU2();
1584                        break;
1585                       
1586                case ID_WRPW:
1587                        imap->wrapw.val = getF4();
1588                        imap->wrapw.eindex = getVX();
1589                        break;
1590                       
1591                case ID_WRPH:
1592                        imap->wraph.val = getF4();
1593                        imap->wraph.eindex = getVX();
1594                        break;
1595                       
1596                case ID_AAST:
1597                        imap->aas_flags = getU2();
1598                        imap->aa_strength = getF4();
1599                        break;
1600                       
1601                case ID_PIXB:
1602                        imap->pblend = getU2();
1603                        break;
1604                       
1605                case ID_STCK:
1606                        imap->stck.val = getF4();
1607                        imap->stck.eindex = getVX();
1608                        break;
1609                       
1610                case ID_TAMP:
1611                        imap->amplitude.val = getF4();
1612                        imap->amplitude.eindex = getVX();
1613                        break;
1614                       
1615                default:
1616                        break;
1617                }
1618               
1619                /* error while reading the current subchunk? */
1620               
1621                rlen = flen;
1622                if ( rlen < 0 || rlen > sz ) return 0;
1623               
1624                /* skip unread parts of the current subchunk */
1625               
1626                if ( rlen < sz )
1627                        is->seekg(sz - rlen, ios_base::cur );
1628               
1629                /* end of the image map? */
1630               
1631                int fpos = is->tellg();
1632                if ( fpos == -1 ) break;
1633                if ( rsz + pos <= fpos ) break;
1634
1635//              if ( rsz + pos <= is->tellg() )
1636//                      break;
1637               
1638                /* get the next subchunk header */
1639               
1640                flen = 0;
1641                id = getU4();
1642                sz = getU2();
1643                if ( 6 != flen ) return 0;
1644        };
1645       
1646        int g = is->tellg();
1647        flen = g - pos;
1648        return imap;
1649}
1650
1651
1652/*
1653======================================================================
1654lwGetProcedural()
1655
1656Read an lwProcedural from a SURF.BLOK in an LWO2 file.
1657======================================================================
1658*/
1659 
1660lwProcedural *lwReader::lwGetProcedural( int rsz, lwTexture &tex )
1661{
1662        unsigned int id;
1663        unsigned short sz;
1664        int rlen, pos, fpos;
1665       
1666        pos = is->tellg();
1667        id = getU4();
1668        sz = getU2();
1669        if ( 0 > flen ) return 0;
1670
1671        lwProcedural *proc = new lwProcedural;
1672        if (!proc) return NULL;
1673       
1674        for (;;) {
1675                sz += sz & 1;
1676                flen = 0;
1677               
1678                switch ( id ) {
1679                case ID_TMAP:
1680                        if ( !lwGetTMap( sz, tex.tmap )) return 0;
1681                        break;
1682                       
1683                case ID_AXIS:
1684                        proc->axis = getU2();
1685                        break;
1686                       
1687                case ID_VALU:
1688                        proc->value[ 0 ] = getF4();
1689                        if ( sz >= 8 ) proc->value[ 1 ] = getF4();
1690                        if ( sz >= 12 ) proc->value[ 2 ] = getF4();
1691                        break;
1692                       
1693                case ID_FUNC:
1694                        proc->name = getS0();
1695                        rlen = flen;
1696                        proc->data = getbytes( sz - rlen );
1697                        break;
1698                       
1699                default:
1700                        break;
1701                }
1702               
1703                /* error while reading the current subchunk? */
1704               
1705                rlen = flen;
1706                if ( rlen < 0 || rlen > sz ) return 0;
1707               
1708                /* skip unread parts of the current subchunk */
1709               
1710                if ( rlen < sz )
1711                        is->seekg(sz - rlen, ios_base::cur );
1712               
1713                /* end of the procedural block? */
1714               
1715                fpos = is->tellg();
1716               
1717                if (fpos == -1)
1718                {
1719                        flen  = -pos;
1720                        return proc;
1721                }
1722               
1723                if ( rsz + pos <= fpos )
1724                        break;
1725               
1726                //              if ( rsz + pos <= is->tellg())
1727                //                      break;
1728               
1729                /* get the next subchunk header */
1730               
1731                flen = 0;
1732                id = getU4();
1733                sz = getU2();
1734                if ( 6 != flen ) return 0;
1735        };
1736       
1737        int g = is->tellg();
1738        flen = g - pos;
1739        return proc;
1740}
1741 
1742 
1743/*
1744======================================================================
1745lwGetGradient()
1746
1747Read an lwGradient from a SURF.BLOK in an LWO2 file.
1748====================================================================== */
1749 
1750lwGradient *lwReader::lwGetGradient( int rsz, lwTexture &tex )
1751{
1752        unsigned int id;
1753        unsigned short sz;
1754        int rlen, pos, i, j, nkeys;
1755       
1756        pos = is->tellg();
1757        id = getU4();
1758        sz = getU2();
1759        if ( 0 > flen ) return 0;
1760
1761        lwGradient *grad = new lwGradient;
1762        if (!grad) return NULL;
1763
1764        for (;;) {
1765                sz += sz & 1;
1766                flen = 0;
1767               
1768                switch ( id ) {
1769                case ID_TMAP:
1770                        if ( !lwGetTMap( sz, tex.tmap )) return 0;
1771                        break;
1772                       
1773                case ID_PNAM:
1774                        grad->paramname = getS0();
1775                        break;
1776                       
1777                case ID_INAM:
1778                        grad->itemname = getS0();
1779                        break;
1780                       
1781                case ID_GRST:
1782                        grad->start = getF4();
1783                        break;
1784                       
1785                case ID_GREN:
1786                        grad->end = getF4();
1787                        break;
1788                       
1789                case ID_GRPT:
1790                        grad->repeat = getU2();
1791                        break;
1792                       
1793                case ID_FKEY:
1794                        nkeys = sz / sizeof( lwGradKey );
1795                        grad->key = (lwGradKey *)malloc(nkeys * sizeof(lwGradKey));
1796                        if ( !grad->key ) return 0;
1797                        for ( i = 0; i < nkeys; i++ ) {
1798                                grad->key[ i ].value = getF4();
1799                                for ( j = 0; j < 4; j++ )
1800                                        grad->key[ i ].rgba[ j ] = getF4();
1801                        }
1802                        break;
1803                       
1804                case ID_IKEY:
1805                        nkeys = sz / 2;
1806                        grad->ikey = (short *)malloc(nkeys * sizeof(short));
1807                        if ( !grad->ikey ) return 0;
1808                        for ( i = 0; i < nkeys; i++ )
1809                                grad->ikey[ i ] = getU2();
1810                        break;
1811                       
1812                default:
1813                        break;
1814                }
1815               
1816                /* error while reading the current subchunk? */
1817               
1818                rlen = flen;
1819                if ( rlen < 0 || rlen > sz ) return 0;
1820               
1821                /* skip unread parts of the current subchunk */
1822               
1823                if ( rlen < sz )
1824                        is->seekg(sz - rlen, ios_base::cur );
1825               
1826                /* end of the gradient? */
1827               
1828                int fpos = is->tellg();
1829                if ( fpos == -1 ) break;
1830                if ( rsz + pos <= fpos ) break;
1831
1832//              if ( rsz + pos <= is->tellg() )
1833//                      break;
1834               
1835                /* get the next subchunk header */
1836               
1837                flen = 0;
1838                id = getU4();
1839                sz = getU2();
1840                if ( 6 != flen ) return 0;
1841        };
1842       
1843        int g = is->tellg();
1844        flen = g - pos;
1845        return grad;
1846}
1847
1848
1849/*
1850======================================================================
1851lwGetTexture()
1852
1853Read an lwTexture from a SURF.BLOK in an LWO2 file.
1854====================================================================== */
1855 
1856lwTexture *lwReader::lwGetTexture( int bloksz, unsigned int type )
1857{
1858        lwTexture *tex;
1859        unsigned short sz;
1860        bool ok;
1861       
1862        tex = new lwTexture;
1863        if ( !tex ) return NULL;
1864       
1865        tex->type = type;
1866       
1867        sz = getU2();
1868        if ( !lwGetTHeader( sz, *tex )) {
1869                delete tex;
1870                return NULL;
1871        }
1872       
1873        sz = bloksz - sz - 6;
1874        switch ( type ) {
1875        case ID_IMAP:
1876                tex->param.imap = lwGetImageMap( sz, *tex );
1877                ok = tex->param.imap!=0;
1878                break;
1879        case ID_PROC:
1880                tex->param.proc = lwGetProcedural( sz, *tex );
1881                ok = tex->param.proc!=0;
1882                break;
1883        case ID_GRAD:
1884                tex->param.grad = lwGetGradient( sz, *tex );
1885                ok = tex->param.grad!=0;
1886                break;
1887        default:
1888                ok = !is->seekg(sz, ios_base::cur );
1889        }
1890       
1891        if ( !ok )
1892        {
1893                delete tex;
1894                return NULL;
1895        }
1896       
1897        flen = bloksz;
1898        return tex;
1899}
1900 
1901/*
1902======================================================================
1903lwGetShader()
1904
1905Read a shader record from a SURF.BLOK in an LWO2 file.
1906====================================================================== */
1907
1908lwPlugin *lwReader::lwGetShader( int bloksz )
1909{
1910        lwPlugin *shdr;
1911        unsigned int id;
1912        unsigned short sz;
1913        int hsz, rlen, pos;
1914        int g = 0;
1915       
1916        shdr = new lwPlugin;
1917        if ( !shdr ) return NULL;
1918       
1919        pos = is->tellg();
1920        flen = 0;
1921        hsz = getU2();
1922        shdr->ord = getS0();
1923        id = getU4();
1924        sz = getU2();
1925        if ( 0 > flen ) goto Fail;
1926       
1927        while ( hsz > 0 )
1928        {
1929                sz += sz & 1;
1930                hsz -= sz;
1931                if ( id == ID_ENAB ) {
1932                        shdr->flags = getU2();
1933                        break;
1934                }
1935                else {
1936                        is->seekg(sz, ios_base::cur );
1937                        id = getU4();
1938                        sz = getU2();
1939                }
1940        }
1941       
1942        id = getU4();
1943        sz = getU2();
1944        if ( 0 > flen ) goto Fail;
1945       
1946        for (;;)
1947        {
1948                sz += sz & 1;
1949                flen = 0;
1950               
1951                switch ( id ) {
1952                case ID_FUNC:
1953                        shdr->name = getS0();
1954                        rlen = flen;
1955                        shdr->data = getbytes( sz - rlen );
1956                        break;
1957                       
1958                default:
1959                        break;
1960                }
1961               
1962                /* error while reading the current subchunk? */
1963               
1964                rlen = flen;
1965                if ( rlen < 0 || rlen > sz ) goto Fail;
1966               
1967                /* skip unread parts of the current subchunk */
1968               
1969                if ( rlen < sz )
1970                        is->seekg(sz - rlen, ios_base::cur );
1971               
1972                /* end of the shader block? */
1973               
1974                int fpos = is->tellg();
1975                if ( fpos == -1 ) break;
1976                if ( bloksz + pos <= fpos ) break;
1977               
1978               
1979                //              if ( bloksz + pos <= is->tellg() )
1980                //                      break;
1981               
1982                /* get the next subchunk header */
1983               
1984                flen = 0;
1985                id = getU4();
1986                sz = getU2();
1987                if ( 6 != flen ) goto Fail;
1988        };
1989       
1990        g = is->tellg();
1991        flen = g - pos;
1992        return shdr;
1993       
1994Fail:
1995        delete shdr;
1996        return NULL;
1997}
1998
1999/*======================================================================
2000add_clip()
2001
2002Add a clip to the clip list. Used to store the contents of an RIMG or
2003TIMG surface subchunk.
2004======================================================================*/
2005
2006int lwReader::add_clip( char *s, vclips &clips )
2007{
2008        lwClip *clip;
2009        char *p;
2010
2011        clip = new lwClip;
2012        if ( !clip ) return 0;
2013
2014        if ( p = strstr( s, "(sequence)" ))
2015        {
2016                p[ -1 ] = 0;
2017                clip->type = ID_ISEQ;
2018                lwClipSeq *seq = new lwClipSeq;
2019                seq->prefix = s;
2020                seq->digits = 3;
2021                clip->source.seq = seq;
2022        }
2023        else
2024        {
2025                clip->type = ID_STIL;
2026                lwClipStill *still = new lwClipStill;
2027                still->name = s;
2028                clip->source.still = still;
2029        }
2030
2031        clips.push_back( clip );
2032        clip->index = clips.size()-1;
2033
2034        return clip->index;
2035}
2036
2037
2038/*======================================================================
2039add_tvel()
2040
2041Add a triple of envelopes to simulate the old texture velocity
2042parameters.
2043======================================================================*/
2044
2045int lwReader::add_tvel( float pos[], float vel[], venvelopes &envelopes )
2046{
2047        lwEnvelope *env;
2048        lwKey *key0, *key1;
2049        int i;
2050
2051        for ( i = 0; i < 3; i++ )
2052        {
2053                env = new lwEnvelope;
2054                key0 = new lwKey(0.0f, pos[ i ]);
2055                key1 = new lwKey(1.0f, pos[ i ] + vel[ i ] * 30.0f); // 30.0f == NTSC related ?
2056
2057                key0->shape = key1->shape = ID_LINE;
2058
2059                env->keys.push_back( key0 );
2060                env->keys.push_back( key1 );
2061
2062                env->type = 0x0301 + i;
2063                env->name = (char *)malloc(11);
2064                if ( env->name )
2065                {
2066                        strcpy( env->name, "Position.X" );
2067                        env->name[ 9 ] += i;
2068                }
2069
2070                env->behavior[ 0 ] = BEH_LINEAR;
2071                env->behavior[ 1 ] = BEH_LINEAR;
2072
2073                envelopes.push_back( env );
2074                env->index = envelopes.size()-1;
2075        }
2076        return env->index - 2;
2077}
2078
2079
2080/*======================================================================
2081get_texture()
2082
2083Create a new texture for BTEX, CTEX, etc. subchunks.
2084======================================================================*/
2085
2086lwTexture *lwReader::get_texture( char *s )
2087{
2088        lwTexture *tex = new lwTexture;
2089        if ( !tex ) return NULL;
2090
2091        if ( strstr( s, "Image Map" ))
2092        {
2093                tex->type = ID_IMAP;
2094                lwImageMap *imap = new lwImageMap;
2095                tex->param.imap = imap;
2096                if ( strstr( s, "Planar" )) imap->projection = 0;
2097                else if ( strstr( s, "Cylindrical" )) imap->projection = 1;
2098                else if ( strstr( s, "Spherical" )) imap->projection = 2;
2099                else if ( strstr( s, "Cubic" )) imap->projection = 3;
2100                else if ( strstr( s, "Front" )) imap->projection = 4;
2101                imap->aa_strength = 1.0f;
2102                imap->amplitude.val = 1.0f;
2103                free(s);
2104        }
2105        else
2106        {
2107                tex->type = ID_PROC;
2108                lwProcedural *proc = new lwProcedural;
2109                tex->param.proc = proc;
2110                proc->name = s;
2111        }
2112        return tex;
2113}
2114
2115lwSurface *lwReader::lwGetLWOBSurface( lwObject *obj )
2116{
2117        lwTexture *tex = 0;
2118        lwPlugin *shdr = 0;
2119        char *s;
2120        float v[ 3 ];
2121        unsigned int flags;
2122        unsigned short sz;
2123        int rlen, i;
2124
2125        long filepos = is->tellg();
2126        long chunkstart = filepos;
2127        long chunkend = chunkstart + chunksize;
2128
2129        /* allocate the Surface structure */
2130
2131        lwSurface *surf = new lwSurface;
2132        if ( !surf ) return NULL;
2133
2134        /* name */
2135
2136        surf->name = getS0();
2137
2138        /* process subchunks as they're encountered */
2139        filepos = is->tellg();
2140        if (filepos == -1) return surf;
2141        if ( filepos > chunkend ) return surf; // error: read too much
2142
2143        while( filepos < chunkend )
2144        {
2145                currentchunkid = getU4();
2146                sz = getU2();
2147                sz += sz & 1;
2148                flen = 0;
2149
2150                switch ( currentchunkid )
2151                {
2152                case ID_COLR:
2153                        surf->color.rgb[ 0 ] = getU1() / 255.0f;
2154                        surf->color.rgb[ 1 ] = getU1() / 255.0f;
2155                        surf->color.rgb[ 2 ] = getU1() / 255.0f;
2156                        break;
2157
2158                case ID_FLAG:
2159                        flags = getU2();
2160                        if ( flags & 4 ) surf->smooth = 1.56207f;
2161                        if ( flags & 8 ) surf->color_hilite.val = 1.0f;
2162                        if ( flags & 16 ) surf->color_filter.val = 1.0f;
2163                        if ( flags & 128 ) surf->dif_sharp.val = 0.5f;
2164                        if ( flags & 256 ) surf->sideflags = 3;
2165                        if ( flags & 512 ) surf->add_trans.val = 1.0f;
2166                        break;
2167
2168                case ID_LUMI:
2169                        surf->luminosity.val = getI2() / 256.0f;
2170                        break;
2171
2172                case ID_VLUM:
2173                        surf->luminosity.val = getF4();
2174                        break;
2175
2176                case ID_DIFF:
2177                        surf->diffuse.val = getI2() / 256.0f;
2178                        break;
2179
2180                case ID_VDIF:
2181                        surf->diffuse.val = getF4();
2182                        break;
2183
2184                case ID_SPEC:
2185                        surf->specularity.val = getI2() / 256.0f;
2186                        break;
2187
2188                case ID_VSPC:
2189                        surf->specularity.val = getF4();
2190                        break;
2191
2192                case ID_GLOS:
2193                        surf->glossiness.val = (float)log((double)getU2()) / 20.7944f;
2194                        break;
2195
2196                case ID_SMAN:
2197                        surf->smooth = getF4();
2198                        break;
2199
2200                case ID_REFL:
2201                        surf->reflection.val.val = getI2() / 256.0f;
2202                        break;
2203
2204                case ID_RFLT:
2205                        surf->reflection.options = getU2();
2206                        break;
2207
2208                case ID_RIMG:
2209                        s = getS0();
2210                        surf->reflection.cindex = add_clip( s, obj->clips );
2211                        surf->reflection.options = 3;
2212                        break;
2213
2214                case ID_RSAN:
2215                        surf->reflection.seam_angle = getF4();
2216                        break;
2217
2218                case ID_TRAN:
2219                        surf->transparency.val.val = getI2() / 256.0f;
2220                        break;
2221
2222                case ID_RIND:
2223                        surf->eta.val = getF4();
2224                        break;
2225
2226                case ID_BTEX:
2227                        s = getbytes( sz );
2228                        tex = get_texture( s );
2229                        surf->bump.textures.push_back( tex );
2230                        break;
2231
2232                case ID_CTEX:
2233                        s = getbytes( sz );
2234                        tex = get_texture( s );
2235                        surf->color.textures.push_back( tex );
2236                        break;
2237
2238                case ID_DTEX:
2239                        s = getbytes( sz );
2240                        tex = get_texture( s );
2241                        surf->diffuse.textures.push_back( tex );
2242                        break;
2243
2244                case ID_LTEX:
2245                        s = getbytes( sz );
2246                        tex = get_texture( s );
2247                        surf->luminosity.textures.push_back( tex );
2248                        break;
2249
2250                case ID_RTEX:
2251                        s = getbytes( sz );
2252                        tex = get_texture( s );
2253                        surf->reflection.val.textures.push_back( tex );
2254                        break;
2255
2256                case ID_STEX:
2257                        s = getbytes( sz );
2258                        tex = get_texture( s );
2259                        surf->specularity.textures.push_back( tex );
2260                        break;
2261
2262                case ID_TTEX:
2263                        s = getbytes( sz );
2264                        tex = get_texture( s );
2265                        surf->transparency.val.textures.push_back( tex );
2266                        break;
2267
2268                case ID_TFLG:
2269                        flags = getU2();
2270
2271                        if ( flags & 1 ) i = 0;
2272                        if ( flags & 2 ) i = 1;
2273                        if ( flags & 4 ) i = 2;
2274                        tex->axis = i;
2275                        if ( tex->type == ID_IMAP )
2276                        {
2277                                tex->param.imap->axis = i;
2278                                if ( flags & 32 )
2279                                        tex->param.imap->pblend = 1;
2280                                if ( flags & 64 )
2281                                {
2282                                        tex->param.imap->aa_strength = 1.0f;
2283                                        tex->param.imap->aas_flags = 1;
2284                                }
2285                        }
2286                        if ( tex->type == ID_PROC )
2287                                tex->param.proc->axis = i;
2288
2289                        if ( flags & 8 ) tex->tmap.coord_sys = 1;
2290                        if ( flags & 16 ) tex->negative = 1;
2291                        break;
2292
2293                case ID_TSIZ:
2294                        for ( i = 0; i < 3; i++ )
2295                                tex->tmap.size.val[ i ] = getF4();
2296                        break;
2297
2298                case ID_TCTR:
2299                        for ( i = 0; i < 3; i++ )
2300                                tex->tmap.center.val[ i ] = getF4();
2301                        break;
2302
2303                case ID_TFAL:
2304                        for ( i = 0; i < 3; i++ )
2305                                tex->tmap.falloff.val[ i ] = getF4();
2306                        break;
2307
2308                case ID_TVEL:
2309                        for ( i = 0; i < 3; i++ )
2310                                v[ i ] = getF4();
2311                        tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v, obj->envelopes );
2312                        break;
2313
2314                case ID_TCLR:
2315                        if ( tex->type == ID_PROC )
2316                                for ( i = 0; i < 3; i++ )
2317                                        tex->param.proc->value[ i ] = getU1() / 255.0f;
2318                                break;
2319
2320                case ID_TVAL:
2321                        if ( tex->type == ID_PROC )
2322                                tex->param.proc->value[ 0 ] = getI2() / 256.0f;
2323                        break;
2324
2325                case ID_TAMP:
2326                        if ( tex->type == ID_IMAP )
2327                                tex->param.imap->amplitude.val = getF4();
2328                        break;
2329
2330                case ID_TIMG:
2331                        if ( tex->type == ID_IMAP )
2332                        {
2333                                s = getS0();
2334                                tex->param.imap->cindex = add_clip( s, obj->clips );
2335                        }
2336                        break;
2337
2338                case ID_TAAS:
2339                        if ( tex->type == ID_IMAP )
2340                        {
2341                                tex->param.imap->aa_strength = getF4();
2342                                tex->param.imap->aas_flags = 1;
2343                        }
2344                        break;
2345
2346                case ID_TREF:
2347                        tex->tmap.ref_object = getbytes( sz );
2348                        break;
2349
2350                case ID_TOPC:
2351                        tex->opacity.val = getF4();
2352                        break;
2353
2354                case ID_TFP0:
2355                        if ( tex->type == ID_IMAP )
2356                                tex->param.imap->wrapw.val = getF4();
2357                        break;
2358
2359                case ID_TFP1:
2360                        if ( tex->type == ID_IMAP )
2361                                tex->param.imap->wraph.val = getF4();
2362                        break;
2363
2364                case ID_SHDR:
2365                        shdr = new lwPlugin;
2366                        if ( !shdr ) goto Fail;
2367                        shdr->name = getbytes( sz );
2368                        surf->shaders.push_back( shdr );
2369                        break;
2370
2371                case ID_SDAT:
2372                        shdr->data = getbytes( sz );
2373                        break;
2374                default:
2375                        break;
2376                }
2377
2378                /* error while reading current subchunk? */
2379
2380                rlen = flen;
2381                if ( rlen < 0 || rlen > sz ) goto Fail;
2382
2383                /* skip unread parts of the current subchunk */
2384
2385                if ( rlen < sz )
2386                        is->seekg(sz - rlen, ios_base::cur );
2387
2388                /* end of the SURF chunk? */
2389
2390                filepos = is->tellg();
2391                if ( filepos == -1 ) break; // end of file ?
2392                if ( filepos > chunkend ) // error: read too much
2393                {
2394                        is->seekg(chunkend, ios_base::beg );
2395                        break;
2396                }
2397        }
2398        return surf;
2399Fail:
2400        if ( surf ) delete surf;
2401        return NULL;
2402}
2403
2404
2405/*
2406======================================================================
2407lwGetSurface()
2408
2409Read an lwSurface from an LWO2 file.
2410====================================================================== */
2411
2412lwSurface *lwReader::lwGetSurface()
2413{
2414        lwSurface *surf;
2415        lwTexture *tex;
2416        lwPlugin *shdr;
2417        unsigned int id, type;
2418        unsigned short sz;
2419        unsigned int pos, rlen, fpos;
2420       
2421        /* allocate the Surface structure */
2422       
2423        surf = new lwSurface;
2424        if ( !surf ) goto Fail;
2425       
2426        /* remember where we started */
2427       
2428        flen = 0;
2429        pos = is->tellg();
2430       
2431        /* names */
2432       
2433        surf->name = getS0();
2434        surf->srcname = getS0();
2435       
2436        /* first subchunk header */
2437       
2438        id = getU4();
2439        sz = getU2();
2440        if ( 0 > flen ) goto Fail;
2441       
2442        /* process subchunks as they're encountered */
2443       
2444        for (;;) {
2445                sz += sz & 1;
2446                flen = 0;
2447               
2448                switch ( id ) {
2449                case ID_COLR:
2450                        surf->color.rgb[ 0 ] = getF4();
2451                        surf->color.rgb[ 1 ] = getF4();
2452                        surf->color.rgb[ 2 ] = getF4();
2453                        surf->color.eindex = getVX();
2454                        break;
2455                       
2456                case ID_LUMI:
2457                        surf->luminosity.val = getF4();
2458                        surf->luminosity.eindex = getVX();
2459                        break;
2460                       
2461                case ID_DIFF:
2462                        surf->diffuse.val = getF4();
2463                        surf->diffuse.eindex = getVX();
2464                        break;
2465                       
2466                case ID_SPEC:
2467                        surf->specularity.val = getF4();
2468                        surf->specularity.eindex = getVX();
2469                        break;
2470                       
2471                case ID_GLOS:
2472                        surf->glossiness.val = getF4();
2473                        surf->glossiness.eindex = getVX();
2474                        break;
2475                       
2476                case ID_REFL:
2477                        surf->reflection.val.val = getF4();
2478                        surf->reflection.val.eindex = getVX();
2479                        break;
2480                       
2481                case ID_RFOP:
2482                        surf->reflection.options = getU2();
2483                        break;
2484                       
2485                case ID_RIMG:
2486                        surf->reflection.cindex = getVX();
2487                        break;
2488                       
2489                case ID_RSAN:
2490                        surf->reflection.seam_angle = getF4();
2491                        break;
2492                       
2493                case ID_TRAN:
2494                        surf->transparency.val.val = getF4();
2495                        surf->transparency.val.eindex = getVX();
2496                        break;
2497                       
2498                case ID_TROP:
2499                        surf->transparency.options = getU2();
2500                        break;
2501                       
2502                case ID_TIMG:
2503                        surf->transparency.cindex = getVX();
2504                        break;
2505                       
2506                case ID_RIND:
2507                        surf->eta.val = getF4();
2508                        surf->eta.eindex = getVX();
2509                        break;
2510                       
2511                case ID_TRNL:
2512                        surf->translucency.val = getF4();
2513                        surf->translucency.eindex = getVX();
2514                        break;
2515                       
2516                case ID_BUMP:
2517                        surf->bump.val = getF4();
2518                        surf->bump.eindex = getVX();
2519                        break;
2520                       
2521                case ID_SMAN:
2522                        surf->smooth = getF4();
2523                        break;
2524                       
2525                case ID_SIDE:
2526                        surf->sideflags = getU2();
2527                        break;
2528                       
2529                case ID_CLRH:
2530                        surf->color_hilite.val = getF4();
2531                        surf->color_hilite.eindex = getVX();
2532                        break;
2533                       
2534                case ID_CLRF:
2535                        surf->color_filter.val = getF4();
2536                        surf->color_filter.eindex = getVX();
2537                        break;
2538                       
2539                case ID_ADTR:
2540                        surf->add_trans.val = getF4();
2541                        surf->add_trans.eindex = getVX();
2542                        break;
2543                       
2544                case ID_SHRP:
2545                        surf->dif_sharp.val = getF4();
2546                        surf->dif_sharp.eindex = getVX();
2547                        break;
2548                       
2549                case ID_GVAL:
2550                        surf->glow.val = getF4();
2551                        surf->glow.eindex = getVX();
2552                        break;
2553                       
2554                case ID_LINE:
2555                        surf->line.enabled = 1;
2556                        if ( sz >= 2 ) surf->line.flags = getU2();
2557                        if ( sz >= 6 ) surf->line.size.val = getF4();
2558                        if ( sz >= 8 ) surf->line.size.eindex = getVX();
2559                        break;
2560                       
2561                case ID_ALPH:
2562                        surf->alpha_mode = getU2();
2563                        surf->alpha = getF4();
2564                        break;
2565                       
2566                case ID_AVAL:
2567                        surf->alpha = getF4();
2568                        break;
2569                       
2570                case ID_BLOK:
2571                        type = getU4();
2572                       
2573                        switch ( type ) {
2574                        case ID_IMAP:
2575                        case ID_PROC:
2576                        case ID_GRAD:
2577                                tex = lwGetTexture( sz - 4, type );
2578                                if ( !tex ) goto Fail;
2579                                if ( !surf->addTexture(tex) ) delete tex;
2580                                flen += 4;
2581                                break;
2582                        case ID_SHDR:
2583                                shdr = lwGetShader( sz - 4 );
2584                                if ( !shdr ) goto Fail;
2585                                surf->shaders.insert(lower_bound(surf->shaders.begin(), surf->shaders.end(), shdr), shdr);
2586                                flen += 4;
2587                                break;
2588                        }
2589                        break;
2590                       
2591                        default:
2592                                break;
2593        }
2594       
2595        /* error while reading current subchunk? */
2596       
2597        rlen = flen;
2598        if ( rlen < 0 || rlen > sz ) goto Fail;
2599       
2600        /* skip unread parts of the current subchunk */
2601       
2602        if ( rlen < sz )
2603                is->seekg(sz - rlen, ios_base::cur );
2604       
2605        /* end of the SURF chunk? */
2606       
2607        fpos = is->tellg();
2608        if ( fpos == -1 ) break;
2609        if ( chunksize + pos <= fpos ) break;
2610       
2611        /* get the next subchunk header */
2612       
2613        flen = 0;
2614        id = getU4();
2615        sz = getU2();
2616        if ( 6 != flen ) goto Fail;
2617   }
2618   
2619   return surf;
2620   
2621Fail:
2622   if ( surf ) delete surf;
2623   return NULL;
2624}
2625
2626/*
2627======================================================================
2628lwGetVMap()
2629
2630  Read an lwVMap from a VMAP or VMAD chunk in an LWO2.
2631====================================================================== */
2632
2633lwVMap *lwReader::lwGetVMap( int ptoffset, int poloffset, int perpoly )
2634{
2635        char *buf, *bp;
2636        lwVMap *vmap;
2637        unsigned int i, j, npts, rlen;
2638       
2639        /* read the whole chunk */
2640       
2641        flen = 0;
2642        buf = getbytes( chunksize );
2643        if ( !buf ) return NULL;
2644       
2645        vmap = new lwVMap;
2646        if ( !vmap ) {
2647                free(buf);
2648                return NULL;
2649        }
2650       
2651        /* initialize the vmap */
2652       
2653        vmap->perpoly = perpoly;
2654       
2655        bp = buf;
2656        flen = 0;
2657        vmap->type = sgetU4( &bp );
2658        vmap->dim  = sgetU2( &bp );
2659        vmap->name = sgetS0( &bp );
2660        rlen = flen;
2661       
2662        /* count the vmap records */
2663       
2664        npts = 0;
2665        while ( bp < buf + chunksize ) {
2666                i = sgetVX( &bp );
2667                if ( perpoly )
2668                        i = sgetVX( &bp );
2669                bp += vmap->dim * sizeof( float );
2670                ++npts;
2671        }
2672       
2673        /* allocate the vmap */
2674       
2675        vmap->nverts = npts;
2676        vmap->vindex = (int *)malloc(npts * sizeof(int));
2677        if ( !vmap->vindex ) goto Fail;
2678        if ( perpoly )
2679        {
2680                vmap->pindex = (int *)malloc(npts * sizeof(int));
2681                if ( !vmap->pindex ) goto Fail;
2682        }
2683       
2684        if ( vmap->dim > 0 )
2685        {
2686                vmap->val = (float **)malloc(npts * sizeof(float *));
2687                if ( !vmap->val ) goto Fail;
2688                for ( i = 0; i < npts; i++ )
2689                        vmap->val[ i ] = (float *)malloc(vmap->dim * sizeof( float ));
2690        }
2691       
2692        /* fill in the vmap values */
2693       
2694        bp = buf + rlen;
2695        for ( i = 0; i < npts; i++ ) {
2696                vmap->vindex[ i ] = sgetVX( &bp );
2697                if ( perpoly )
2698                        vmap->pindex[ i ] = sgetVX( &bp );
2699                for ( j = 0; j < vmap->dim; j++ )
2700                        vmap->val[ i ][ j ] = sgetF4( &bp );
2701        }
2702       
2703        free(buf);
2704        return vmap;
2705       
2706Fail:
2707        free(buf);
2708        delete vmap;
2709        return NULL;
2710}
Note: See TracBrowser for help on using the repository browser.