root/OpenSceneGraph/trunk/src/osgPlugins/txp/trpage_material.cpp @ 13041

Revision 13041, 43.2 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
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#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19
20/* trpage_material.cpp
21   This source file contains the methods for trpgMatTable, trpgTextureEnv,
22   trpgMaterial, and trpgTexTable.
23   You should only modify this code if you want to add data to these classes.
24*/
25
26#include <trpage_geom.h>
27#include <trpage_read.h>
28
29#ifdef _MSC_VER
30#define strcasecmp _stricmp
31#endif
32
33/* Write Material Table class
34   Keeps track of the materials that have been added.
35*/
36
37// Constructor
38trpgMatTable::trpgMatTable()
39{
40    numTable = numMat = 0;
41}
42trpgMatTable::~trpgMatTable()
43{
44}
45
46// Reset function
47void trpgMatTable::Reset()
48{
49    numTable = 0;
50    numMat = 0;
51    materialMap.clear();
52}
53
54// Validity check
55bool trpgMatTable::isValid() const
56{
57    if(materialMap.size()==0)
58    return false;
59    // get an iterator for the materialMap
60    MaterialMapType::const_iterator itr = materialMap.begin();
61    for (  ; itr != materialMap.end( ); itr++) {
62        if(!(*itr).second.isValid()) {
63            return false;
64        }
65    }
66
67    return true;
68}
69
70// Set functions
71void trpgMatTable::SetNumTable(int no)
72{
73    if ((no < 0) || (no==numTable))
74        return;
75    numTable = no;
76}
77void trpgMatTable::SetNumMaterial(int /*no*/)
78{
79    // This method is obsolete since we're using the project handle
80    // and a map to store the materials, instead of a vector
81}
82
83
84void trpgMatTable::SetMaterial(int nm,const trpgMaterial &mat)
85{
86    materialMap[nm] = mat;
87    numMat = materialMap.size();
88}
89
90#define CEQ(ca,cb) (ca.red == cb.red && ca.green == cb.green && ca.blue == cb.blue)
91
92int trpgMatTable::AddMaterial(const trpgMaterial &mat,bool lookForExisting)
93{
94    trpgMaterial cmat = mat; // necessary?
95
96    // having a shadeModel of 999 indicates that the entry is free.  I thought this would
97    // work fine, until I realized that evidently most of the time the shademodel isn't set
98    // at all.  Now my kludge takes so much work it's almost worth doing it right.
99
100    if (cmat.shadeModel>100) cmat.shadeModel=trpgMaterial::Smooth;
101
102    int baseMat=0;
103    //bool spaceInTable=false;
104    //int offset=baseMat;
105
106    if (lookForExisting) {
107        // Look for a matching base material minus the textures
108        //for (baseMat = 0;baseMat < numMat;baseMat++) {
109        MaterialMapType::const_iterator itr = materialMap.begin();
110        for (  ; itr != materialMap.end( ); itr++) {
111            baseMat = itr->first;
112            const trpgMaterial &bm = itr->second;
113            if (bm.shadeModel==999) {
114                // this is an 'empty' entry.  Means we won't find it, either.
115                //spaceInTable=true;
116                break;
117            }
118
119            // Compare structures
120            if (CEQ(cmat.color,bm.color) && CEQ(cmat.ambient,bm.ambient) &&
121                CEQ(cmat.diffuse,bm.diffuse) && CEQ(cmat.specular,bm.specular) &&
122                CEQ(cmat.emission,bm.emission) && cmat.shininess == bm.shininess &&
123                cmat.shadeModel == bm.shadeModel && cmat.pointSize == bm.pointSize &&
124                cmat.lineWidth == bm.lineWidth && cmat.cullMode == bm.cullMode &&
125                cmat.alphaFunc == bm.alphaFunc && cmat.alphaRef == bm.alphaRef &&
126                cmat.attrSet.fid == bm.attrSet.fid && cmat.attrSet.smc == bm.attrSet.smc &&
127                cmat.attrSet.stp == bm.attrSet.stp && cmat.attrSet.swc == bm.attrSet.swc &&
128                cmat.autoNormal == bm.autoNormal && cmat.texEnvs.size() == bm.texEnvs.size()) {
129                // Test the texture envs
130                bool isSame=true;
131                unsigned int i;
132                for (i=0;i<cmat.texEnvs.size();i++) {
133                            const trpgTextureEnv &e1 = cmat.texEnvs[i];
134                    const trpgTextureEnv &e2 = bm.texEnvs[i];
135                    if (e1.envMode != e2.envMode ||
136                    e1.minFilter != e2.minFilter ||
137                    e1.magFilter != e2.magFilter ||
138                    e1.wrapS != e2.wrapS || e1.wrapT != e2.wrapT ||
139                    !CEQ(e1.borderCol,e2.borderCol))
140                    isSame = false;
141                }
142                // Test the texture IDs
143                for (i=0;i<cmat.texids.size();i++) {
144                    if (cmat.texids[i] != bm.texids[i])
145                    isSame = false;
146                }
147                if (isSame)
148                    return baseMat;
149            }
150        }
151    }
152
153    // Didn't find it.  Add it
154    int idx;
155    if(cmat.writeHandle)
156        idx = cmat.GetHandle();
157    else
158        idx = numMat;
159    materialMap[idx] = cmat;
160    numMat = materialMap.size();
161    return idx;
162}
163
164// Write out material table
165bool trpgMatTable::Write(trpgWriteBuffer &buf)
166{
167    if (!isValid())
168        return false;
169
170    buf.Begin(TRPGMATTABLE);
171
172    // Total number of materials
173    buf.Add((int32)numTable);
174    buf.Add((int32)numMat);
175
176    // Write the materials
177    MaterialMapType::const_iterator itr = materialMap.begin();
178    for (  ; itr != materialMap.end( ); itr++) {
179        ((trpgMaterial)(*itr).second).Write(buf);
180    }
181    buf.End();
182
183    return true;
184}
185
186/* ************
187    Material Table Read
188   ***********
189   */
190
191// Get functions
192bool trpgMatTable::GetNumTable(int &no) const
193{
194    if (!isValid()) {
195        no = 0; // otherwise this causes errors because it is uninitialized.
196        return false;
197    }
198    no = numTable;
199    return true;
200}
201bool trpgMatTable::GetNumMaterial(int &no) const
202{
203    if (!isValid()) {
204        no = 0;
205        return false;
206    }
207    no = numMat;
208    return true;
209}
210
211bool trpgMatTable::GetMaterial(int nt,int nm,trpgMaterial &mat) const
212{
213    if (!isValid()) return false;
214
215    MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);
216    if(itr == materialMap.end())
217        return false;
218
219    mat = (*itr).second;
220    return true;
221}
222
223const trpgMaterial *trpgMatTable::GetMaterialRef(int nt,int nm) const
224{
225    MaterialMapType::const_iterator itr = materialMap.find((nt*numMat)+nm);
226    if(itr == materialMap.end())
227        return false;
228    return const_cast<trpgMaterial *>(&(*itr).second);
229}
230
231
232bool trpgMatTable::Read(trpgReadBuffer &buf)
233{
234    trpgMaterial mat;
235    trpgToken matTok;
236    int32 len;
237    bool status;
238    int i,j;
239    int nMat,nTable;
240
241    try {
242        buf.Get(nTable);
243        buf.Get(nMat);
244        if (nTable <= 0 || nMat < 0) throw 1;
245        // Read the materials
246        for (i=0;i<nTable;i++)
247            for (j=0;j<nMat;j++) {
248                buf.GetToken(matTok,len);
249                if (matTok != TRPGMATERIAL) throw 1;
250                buf.PushLimit(len);
251                mat.Reset();
252                status = mat.Read(buf);
253                buf.PopLimit();
254                if (!status) throw 1;
255                AddMaterial(mat,false);
256            }
257            numTable += nTable;
258            numMat = materialMap.size();
259    }
260    catch (...) {
261        return false;
262    }
263
264    return isValid();
265}
266
267/* Write Texture Environment class
268    Used to specify how a texture is applied.
269    Associated with materials.
270    */
271
272// Constructor
273trpgTextureEnv::trpgTextureEnv()
274{
275    Reset();
276}
277trpgTextureEnv::~trpgTextureEnv()
278{
279}
280
281// Reset function
282void trpgTextureEnv::Reset()
283{
284    envMode = Decal;
285    minFilter = Linear;
286    magFilter = MipmapBilinear;
287    wrapS = wrapT = Repeat;
288    borderCol = trpgColor(0,0,0);
289}
290
291bool trpgTextureEnv::isValid() const
292{
293    return true;
294}
295
296// Set functions
297void trpgTextureEnv::SetEnvMode(int mode)
298{
299    envMode = mode;
300}
301void trpgTextureEnv::SetMinFilter(int fl)
302{
303    minFilter = fl;
304}
305void trpgTextureEnv::SetMagFilter(int fl)
306{
307    magFilter = fl;
308}
309void trpgTextureEnv::SetWrap(int s,int t)
310{
311    wrapS = s;
312    wrapT = t;
313}
314void trpgTextureEnv::SetBorderColor(const trpgColor &col)
315{
316    borderCol = col;
317}
318
319// Write function
320bool trpgTextureEnv::Write(trpgWriteBuffer &buf)
321{
322    if (!isValid())
323    return false;
324
325    buf.Begin(TRPGMAT_TEXENV);
326
327    buf.Begin(TRPGMAT_TXENV_MODE);
328    buf.Add(envMode);
329    buf.End();
330
331    buf.Begin(TRPGMAT_TXENV_FILTER);
332    buf.Add(minFilter);
333    buf.Add(magFilter);
334    buf.End();
335
336    buf.Begin(TRPGMAT_TXENV_WRAP);
337    buf.Add(wrapS);
338    buf.Add(wrapT);
339    buf.End();
340
341    buf.Begin(TRPGMAT_TXENV_BORDER);
342    buf.Add(borderCol);
343    buf.End();
344
345    buf.End();
346
347    return true;
348}
349
350/* **************
351   Texture Env Read support
352   **************
353   */
354// Get functions
355bool trpgTextureEnv::GetEnvMode(int32 &ret) const
356{
357    if (!isValid()) return false;
358    ret = envMode;
359    return true;
360}
361bool trpgTextureEnv::GetMinFilter(int32 &ret) const
362{
363    if (!isValid()) return false;
364    ret = minFilter;
365    return true;
366}
367bool trpgTextureEnv::GetMagFilter(int32 &ret) const
368{
369    if (!isValid()) return false;
370    ret = magFilter;
371    return true;
372}
373bool trpgTextureEnv::GetWrap(int &S,int &T) const
374{
375    if (!isValid()) return false;
376    S = wrapS;
377    T = wrapT;
378    return true;
379}
380bool trpgTextureEnv::GetBorderColor(trpgColor &col) const
381{
382    if (!isValid()) return false;
383    col = borderCol;
384    return true;
385}
386
387/* Texture Env CB
388   Used to parse tokens for a texture Env.
389*/
390class textureEnvCB : public trpgr_Callback {
391public:
392    void *Parse(trpgToken,trpgReadBuffer &);
393    trpgTextureEnv *tenv;
394};
395
396void * textureEnvCB::Parse(trpgToken tok,trpgReadBuffer &buf)
397{
398    int envMode;
399    int minFilter;
400    int magFilter;
401    int wrapS,wrapT;
402    trpgColor borderCol;
403
404    try {
405        switch (tok) {
406        case TRPGMAT_TXENV_MODE:
407            buf.Get(envMode);
408            tenv->SetEnvMode(envMode);
409            break;
410        case TRPGMAT_TXENV_FILTER:
411            buf.Get(minFilter);
412            buf.Get(magFilter);
413            tenv->SetMinFilter(minFilter);
414            tenv->SetMagFilter(magFilter);
415            break;
416        case TRPGMAT_TXENV_WRAP:
417            buf.Get(wrapS);
418            buf.Get(wrapT);
419            tenv->SetWrap(wrapS,wrapT);
420            break;
421        case TRPGMAT_TXENV_BORDER:
422            buf.Get(borderCol);
423            tenv->SetBorderColor(borderCol);
424            break;
425        default:
426            // Don't know this token.  Skip
427            break;
428        }
429    }
430    catch (...) {
431    return NULL;
432    }
433
434    return tenv;
435}
436
437bool trpgTextureEnv::Read(trpgReadBuffer &buf)
438{
439    trpgr_Parser parse;
440    textureEnvCB teCb;
441
442    // Texture environment is a bunch of tokens in random order
443    // Interface to it with a parser
444    teCb.tenv = this;
445    parse.AddCallback(TRPGMAT_TXENV_MODE,&teCb,false);
446    parse.AddCallback(TRPGMAT_TXENV_FILTER,&teCb,false);
447    parse.AddCallback(TRPGMAT_TXENV_WRAP,&teCb,false);
448    parse.AddCallback(TRPGMAT_TXENV_BORDER,&teCb,false);
449    parse.Parse(buf);
450
451    return isValid();
452}
453
454/* Write Material class
455   Material representation.
456*/
457
458// Constructor
459trpgMaterial::trpgMaterial()
460{
461    Reset();
462}
463trpgMaterial::~trpgMaterial()
464{
465}
466
467// Reset function
468void trpgMaterial::Reset()
469{
470    color = trpgColor(1,1,1);
471    ambient = trpgColor(0,0,0);
472    diffuse = trpgColor(1,1,1);
473    specular = trpgColor(0,0,0);
474    emission = trpgColor(0,0,0);
475    shininess = 0;
476    shadeModel = 999; // kludge to identify 'empty' material table entries
477    pointSize = 1;
478    lineWidth = 1;
479    cullMode = Back;
480    alphaFunc = GreaterThan;
481    alphaRef = 0;
482    alpha = 1.0;
483    autoNormal = false;
484    numTex = 0;
485    texids.resize(0);
486    texEnvs.resize(0);
487    numTile = 0;
488    isBump = false;
489    attrSet.fid = -1;
490    attrSet.smc = -1;
491    attrSet.stp = -1;
492    attrSet.swc = -1;
493    handle = -1;
494    writeHandle = false;
495}
496
497// Validity check
498bool trpgMaterial::isValid() const
499{
500    // Only thing we really care about is texture
501    if (numTex < 0)
502    return false;
503
504    for (int i=0;i<numTex;i++)
505    if (!texEnvs[i].isValid())
506        return false;
507
508    return true;
509}
510
511
512
513// Set functions
514void trpgMaterial::SetColor(const trpgColor &col)
515{
516    color = col;
517}
518void trpgMaterial::SetAmbient(const trpgColor &col)
519{
520    ambient = col;
521}
522void trpgMaterial::SetDiffuse(const trpgColor &col)
523{
524    diffuse = col;
525}
526void trpgMaterial::SetSpecular(const trpgColor &col)
527{
528    specular = col;
529}
530void trpgMaterial::SetEmission(const trpgColor &col)
531{
532    emission = col;
533}
534void trpgMaterial::SetShininess(float64 val)
535{
536    shininess = val;
537}
538void trpgMaterial::SetShadeModel(int val)
539{
540    shadeModel = val;
541}
542void trpgMaterial::SetPointSize(float64 val)
543{
544    pointSize = val;
545}
546void trpgMaterial::SetLineWidth(float64 val)
547{
548    lineWidth = val;
549}
550void trpgMaterial::SetCullMode(int val)
551{
552    cullMode = val;
553}
554void trpgMaterial::SetAlphaFunc(int val)
555{
556    alphaFunc = val;
557}
558void trpgMaterial::SetAlphaRef(float64 val)
559{
560    alphaRef = val;
561}
562void trpgMaterial::SetAlpha(float64 val)
563{
564    alpha = val;
565}
566void trpgMaterial::SetAutoNormal(bool val)
567{
568    autoNormal = val;
569}
570void trpgMaterial::SetNumTexture(int no)
571{
572    if (no < 0)    return;
573    numTex = no;
574    texids.resize(no);
575    texEnvs.resize(no);
576}
577void trpgMaterial::SetTexture(int no,int id,const trpgTextureEnv &env)
578{
579    if (no < 0 || (unsigned int)no >= texids.size())
580    return;
581
582    texids[no] = id;
583    texEnvs[no] = env;
584}
585int trpgMaterial::AddTexture(int id,const trpgTextureEnv &env)
586{
587    texids.push_back(id);
588    texEnvs.push_back(env);
589    numTex++;
590
591    return numTex-1;
592}
593void trpgMaterial::SetNumTiles(int no)
594{
595    numTile = no;
596}
597int trpgMaterial::AddTile()
598{
599    return(++numTile);
600}
601void trpgMaterial::SetIsBumpMap(bool val)
602{
603    isBump = val;
604}
605void trpgMaterial::SetAttr(int attrCode,int val)
606{
607    switch (attrCode) {
608    case TR_FID:
609        attrSet.fid = val;
610        break;
611    case TR_SMC:
612        attrSet.smc = val;
613        break;
614    case TR_STP:
615        attrSet.stp = val;
616        break;
617    case TR_SWC:
618        attrSet.swc = val;
619        break;
620    }
621
622    return;
623}
624
625// Write to buffer
626bool trpgMaterial::Write(trpgWriteBuffer &buf)
627{
628    if (!isValid())
629        return false;
630
631    buf.Begin(TRPGMATERIAL);
632
633    // Bundle the basic material parameters together
634    buf.Begin(TRPGMAT_BASIC);
635    buf.Add(color);
636    buf.Add(ambient);
637    buf.Add(diffuse);
638    buf.Add(specular);
639    buf.Add(emission);
640    buf.Add(shininess);
641    buf.Add(numTile);
642    buf.End();
643
644    // Most everything else is a single token.
645    // This is inefficient, but expandable
646    buf.Begin(TRPGMAT_SHADE);
647    buf.Add(shadeModel);
648    buf.End();
649
650    buf.Begin(TRPGMAT_SIZES);
651    buf.Add(pointSize);
652    buf.Add(lineWidth);
653    buf.End();
654
655    buf.Begin(TRPGMAT_CULL);
656    buf.Add(cullMode);
657    buf.End();
658
659    buf.Begin(TRPGMAT_ALPHA);
660    buf.Add(alphaFunc);
661    buf.Add(alphaRef);
662    buf.Add(alpha);
663    buf.End();
664
665    buf.Begin(TRPGMAT_NORMAL);
666    buf.Add((int32)autoNormal);
667    buf.End();
668
669    buf.Begin(TRPGMAT_TEXTURE);
670    buf.Add(numTex);
671    for (int i=0;i<numTex;i++) {
672        buf.Add(texids[i]);
673        texEnvs[i].Write(buf);
674    }
675    buf.End();
676
677    // Bump mapping properties
678    buf.Begin(TRPGMAT_BUMP);
679    buf.Add((int32)isBump);
680    buf.End();
681
682    // Attributes (e.g. fid, smc)
683    buf.Begin(TRPGMAT_ATTR);
684    buf.Add(attrSet.fid);
685    buf.Add(attrSet.smc);
686    buf.Add(attrSet.stp);
687    buf.Add(attrSet.swc);
688    buf.End();
689
690    /**
691     * If the terrapage version is >= 2.3, handle will be set to a unique identifier.
692     **/
693    if(writeHandle) {
694        buf.Begin(TRPGMAT_HANDLE);
695        buf.Add((int)handle);
696        buf.End();
697    }
698
699    buf.End();
700
701    return true;
702}
703
704
705/* ***************
706   Material Read methods
707   ***************
708   */
709// Get methods
710bool trpgMaterial::GetColor(trpgColor &col) const
711{
712    if (!isValid()) return false;
713    col = color;
714    return true;
715}
716bool trpgMaterial::GetAmbient(trpgColor &col) const
717{
718    if (!isValid()) return false;
719    col = ambient;
720    return true;
721}
722bool trpgMaterial::GetDiffuse(trpgColor &col) const
723{
724    if (!isValid()) return false;
725    col = diffuse;
726    return true;
727}
728bool trpgMaterial::GetSpecular(trpgColor &col) const
729{
730    if (!isValid()) return false;
731    col = specular;
732    return true;
733}
734bool trpgMaterial::GetEmission(trpgColor &col) const
735{
736    if (!isValid()) return false;
737    col = emission;
738    return true;
739}
740bool trpgMaterial::GetShininess(float64 &shin) const
741{
742    if (!isValid()) return false;
743    shin = shininess;
744    return true;
745}
746bool trpgMaterial::GetShadeModel(int &sm) const
747{
748    if (!isValid()) return false;
749    sm = shadeModel;
750    return true;
751}
752bool trpgMaterial::GetPointSize(float64 &ps) const
753{
754    if (!isValid()) return false;
755    ps = pointSize;
756    return true;
757}
758bool trpgMaterial::GetLineWidth(float64 &lw) const
759{
760    if (!isValid()) return false;
761    lw = lineWidth;
762    return true;
763}
764bool trpgMaterial::GetCullMode(int32 &cull) const
765{
766    if (!isValid()) return false;
767    cull = cullMode;
768    return true;
769}
770bool trpgMaterial::GetAlphaFunc(int &af) const
771{
772    if (!isValid()) return false;
773    af = alphaFunc;
774    return true;
775}
776bool trpgMaterial::GetAlphaRef(float64 &ar) const
777{
778    if (!isValid()) return false;
779    ar = alphaRef;
780    return true;
781}
782bool trpgMaterial::GetAlpha(float64 &a) const
783{
784    if (!isValid()) return false;
785    a = alpha;
786    return true;
787}
788bool trpgMaterial::GetAutoNormal(bool &an) const
789{
790    if (!isValid()) return false;
791    an = autoNormal;
792    return true;
793}
794bool trpgMaterial::GetNumTexture(int &no) const
795{
796    if (!isValid()) return false;
797    no = numTex;
798    return true;
799}
800bool trpgMaterial::GetTexture(int no,int &id,trpgTextureEnv &te) const
801{
802    if (!isValid() || no < 0  || no >= numTex)
803        return false;
804    id = texids[no];
805    te = texEnvs[no];
806    return true;
807}
808bool trpgMaterial::GetNumTile(int &no) const
809{
810    if (!isValid()) return false;
811    no = numTile;
812    return true;
813}
814bool trpgMaterial::GetIsBumpMap(bool &ret) const
815{
816    if (!isValid()) return false;
817    ret = isBump;
818    return true;
819}
820bool trpgMaterial::GetAttr(int attrCode,int &ret) const
821{
822    switch (attrCode) {
823    case TR_FID:
824        ret = attrSet.fid;
825        break;
826    case TR_SMC:
827        ret = attrSet.smc;
828        break;
829    case TR_STP:
830        ret = attrSet.stp;
831        break;
832    case TR_SWC:
833        ret = attrSet.swc;
834        break;
835    default:
836        return false;
837    }
838
839    return true;
840}
841
842
843/* Material CB
844   Used to parse tokens for a material.
845*/
846class materialCB : public trpgr_Callback {
847public:
848    void * Parse(trpgToken,trpgReadBuffer &);
849    trpgMaterial *mat;
850};
851void * materialCB::Parse(trpgToken tok,trpgReadBuffer &buf)
852{
853    trpgColor color;
854    float64 shininess;
855    int shadeModel;
856    float64 size;
857    int cullMode;
858    int alphaFunc;
859    float64 alphaRef,alpha;
860    bool autoNormal;
861    int numTex,texId;
862    trpgToken envTok;
863    trpgTextureEnv texEnv;
864    int32 len,numtile;
865    bool status;
866    int i;
867
868    try {
869        switch (tok) {
870        case TRPGMAT_BASIC:
871            buf.Get(color);
872            mat->SetColor(color);
873            buf.Get(color);
874            mat->SetAmbient(color);
875            buf.Get(color);
876            mat->SetDiffuse(color);
877            buf.Get(color);
878            mat->SetSpecular(color);
879            buf.Get(color);
880            mat->SetEmission(color);
881            buf.Get(shininess);
882            mat->SetShininess(shininess);
883            buf.Get(numtile);
884            mat->SetNumTiles(numtile);
885            break;
886        case TRPGMAT_SHADE:
887            buf.Get(shadeModel);
888            mat->SetShadeModel(shadeModel);
889            break;
890        case TRPGMAT_SIZES:
891            buf.Get(size);
892            mat->SetPointSize(size);
893            buf.Get(size);
894            mat->SetLineWidth(size);
895            break;
896        case TRPGMAT_CULL:
897            buf.Get(cullMode);
898            mat->SetCullMode(cullMode);
899            break;
900        case TRPGMAT_ALPHA:
901            buf.Get(alphaFunc);
902            buf.Get(alphaRef);
903            buf.Get(alpha);
904            mat->SetAlphaFunc(alphaFunc);
905            mat->SetAlphaRef(alphaRef);
906            mat->SetAlpha(alpha);
907            break;
908        case TRPGMAT_NORMAL:
909        {
910            int32 tmp;
911            buf.Get(tmp);
912            if (tmp)
913            autoNormal = true;
914            else
915            autoNormal = false;
916            mat->SetAutoNormal(autoNormal);
917        }
918        break;
919        case TRPGMAT_TEXTURE:
920            buf.Get(numTex);
921            for (i=0;i<numTex;i++) {
922                buf.Get(texId);
923                // Parse the texture Env
924                buf.GetToken(envTok,len);
925                if (envTok != TRPGMAT_TEXENV)  throw 1;
926                buf.PushLimit(len);
927                status = texEnv.Read(buf);
928                buf.PopLimit();
929                if (!status) throw 1;
930
931                mat->AddTexture(texId,texEnv);
932            }
933            break;
934        case TRPGMAT_BUMP:
935        {
936            int32 tmp;
937            buf.Get(tmp);
938            bool isBump = (tmp) ? true : false;
939            mat->SetIsBumpMap(isBump);
940        }
941        break;
942        case TRPGMAT_ATTR:
943        {
944            int tmp;
945            buf.Get(tmp);
946            mat->SetAttr(trpgMaterial::TR_FID,tmp);
947            buf.Get(tmp);
948            mat->SetAttr(trpgMaterial::TR_SMC,tmp);
949            buf.Get(tmp);
950            mat->SetAttr(trpgMaterial::TR_STP,tmp);
951            buf.Get(tmp);
952            mat->SetAttr(trpgMaterial::TR_SWC,tmp);
953        }
954        break;
955        case TRPGMAT_HANDLE:
956        {
957            int hdl;
958            buf.Get(hdl);
959            mat->SetHandle(hdl);
960        }
961        break;
962        default:
963            break;
964        }
965    }
966    catch (...) {
967        return NULL;
968    }
969
970    return mat;
971}
972
973bool trpgMaterial::Read(trpgReadBuffer &buf)
974{
975    trpgr_Parser parse;
976    materialCB matCb;
977
978    // Material is just a bunch of unordered tokens.
979    // Interface to it with a generic parser
980    matCb.mat = this;
981    parse.AddCallback(TRPGMAT_BASIC,&matCb,false);
982    parse.AddCallback(TRPGMAT_SHADE,&matCb,false);
983    parse.AddCallback(TRPGMAT_SIZES,&matCb,false);
984    parse.AddCallback(TRPGMAT_CULL,&matCb,false);
985    parse.AddCallback(TRPGMAT_ALPHA,&matCb,false);
986    parse.AddCallback(TRPGMAT_NORMAL,&matCb,false);
987    parse.AddCallback(TRPGMAT_TEXTURE,&matCb,false);
988    parse.AddCallback(TRPGMAT_BUMP,&matCb,false);
989    parse.AddCallback(TRPGMAT_ATTR,&matCb,false);
990    parse.AddCallback(TRPGMAT_HANDLE,&matCb,false);
991    parse.Parse(buf);
992
993    return isValid();
994}
995
996/* Texture
997   Really just a container for a texture name and use count.
998   The use count is used for paging.
999*/
1000
1001// Constructor
1002trpgTexture::trpgTexture()
1003{
1004    mode = External;
1005    type = trpg_Unknown;
1006    numLayer = -1;
1007    name = NULL;
1008    useCount = 0;
1009    sizeX = sizeY = -1;
1010    addr.file = 0;
1011    addr.offset = 0;
1012    addr.col = -1;
1013    addr.row = -1;
1014    isMipmap = false;
1015    writeHandle = false;
1016    handle = -1;
1017}
1018
1019// Copy construction
1020trpgTexture::trpgTexture(const trpgTexture &in):
1021    trpgReadWriteable(in)
1022{
1023    mode = in.mode;
1024    type = in.type;
1025    numLayer = in.numLayer; // RGBX
1026    name = NULL;
1027    SetName(in.name);
1028    useCount = in.useCount;
1029    sizeX = in.sizeX;  sizeY = in.sizeY;
1030    addr.file = in.addr.file;
1031    addr.offset = in.addr.offset;
1032    addr.row = in.addr.row;
1033    addr.col = in.addr.col;
1034    isMipmap = in.isMipmap;
1035    // storageSize + levelOffset
1036    handle = in.handle;
1037    writeHandle = in.writeHandle;
1038}
1039
1040// Destruction
1041trpgTexture::~trpgTexture()
1042{
1043    Reset();
1044}
1045
1046// Reset
1047void trpgTexture::Reset()
1048{
1049    mode = External;
1050    type = trpg_Unknown;
1051    numLayer = -1;
1052    if (name)
1053        delete [] name;
1054    name = NULL;
1055    useCount = 0;
1056    sizeX = sizeY = -1;
1057    addr.file = 0;
1058    addr.offset = 0;
1059    addr.row = -1;
1060    addr.col = -1;
1061    isMipmap = false;
1062    storageSize.clear();
1063    levelOffset.clear();
1064    handle = -1;
1065    writeHandle = false;
1066}
1067
1068
1069
1070
1071// Valid if we've got a name
1072bool trpgTexture::isValid() const
1073{
1074    switch (mode) {
1075    case External:
1076        return (name != NULL);
1077    case Local:
1078        return (type != trpg_Unknown && sizeX != -1 && sizeY != -1);
1079    case Global:
1080        return (type != trpg_Unknown);
1081    case Template:
1082        return (type != trpg_Unknown && sizeX != -1 && sizeY != -1);
1083    default:
1084        return false;
1085    }
1086}
1087
1088
1089// Set Name
1090void trpgTexture::SetName(const char *inName)
1091{
1092    if (name)
1093        delete [] name;
1094    name = NULL;
1095
1096    if (!inName)
1097        return;
1098
1099    name = new char[strlen(inName)+1];
1100    strcpy(name,inName);
1101}
1102
1103// Get Name
1104bool trpgTexture::GetName(char *outName,int outLen) const
1105{
1106    if (!isValid())
1107        return false;
1108
1109    int len = (name) ? strlen(name) : 0;
1110    strncpy(outName,name,MIN(len,outLen)+1);
1111
1112    return true;
1113}
1114
1115void trpgTexture::SetImageMode(ImageMode inMode)
1116{
1117    mode = inMode;
1118}
1119bool trpgTexture::GetImageMode(ImageMode &outMode) const
1120{
1121    outMode = mode;
1122
1123    return true;
1124}
1125void trpgTexture::SetImageType(ImageType inType)
1126{
1127    type = inType;
1128}
1129bool trpgTexture::GetImageType(ImageType &outType) const
1130{
1131    outType = type;
1132
1133    return true;
1134}
1135
1136void trpgTexture::SetImageSize(const trpg2iPoint &inSize)
1137{
1138    sizeX = inSize.x;
1139    sizeY = inSize.y;
1140}
1141bool trpgTexture::GetImageSize(trpg2iPoint &outSize) const
1142{
1143    if (mode != Local && mode != Template)
1144        return false;
1145    outSize.x = sizeX;
1146    outSize.y = sizeY;
1147
1148    return true;
1149}
1150void trpgTexture::SetIsMipmap(bool val)
1151{
1152    isMipmap = val;
1153}
1154bool trpgTexture::GetIsMipmap(bool &ret) const
1155{
1156    ret = isMipmap;
1157    return true;
1158}
1159bool trpgTexture::GetImageAddr(trpgwAppAddress &outAddr) const
1160{
1161    if (mode != Local)
1162        return false;
1163
1164    outAddr = addr;
1165
1166    return true;
1167}
1168void trpgTexture::SetImageAddr(const trpgwAppAddress &inAddr)
1169{
1170    addr = inAddr;
1171}
1172bool trpgTexture::GetImageDepth(int32 &depth) const
1173{
1174    switch (type) {
1175    case trpg_RGB8:
1176        depth = 3;
1177        break;
1178    case trpg_RGBA8:
1179        depth = 4;
1180        break;
1181    case trpg_INT8:
1182        depth = 1;
1183        break;
1184    case trpg_INTA8:
1185        depth = 2;
1186        break;
1187    case trpg_FXT1:
1188        depth = 3;
1189        break;
1190    case trpg_RGBX:
1191        depth = numLayer;
1192        break;
1193    case trpg_DXT1:
1194        depth = 3;
1195        break;
1196    case trpg_DXT3:
1197        depth = 3;
1198        break;
1199    case trpg_DXT5:
1200        depth = 3;
1201        break;
1202    case trpg_MCM5:
1203        depth = 5;
1204        break;
1205    case trpg_MCM6R:
1206    case trpg_MCM6A:
1207        depth = 6;
1208        break;
1209    case trpg_MCM7RA:
1210    case trpg_MCM7AR:
1211        depth = 7;
1212        break;
1213    default:
1214        depth = -1;
1215        break;
1216    }
1217
1218    return true;
1219}
1220
1221void trpgTexture::SetNumLayer(int layers)
1222{
1223    numLayer = layers;
1224}
1225
1226bool trpgTexture::GetNumLayer(int &layers) const
1227{
1228    if (!isValid())
1229        return false;
1230    GetImageDepth(layers);
1231    return true;
1232}
1233
1234// Use count management
1235void trpgTexture::SetNumTile(int num)
1236{
1237    useCount = num;
1238}
1239void trpgTexture::AddTile()
1240{
1241    useCount++;
1242}
1243bool trpgTexture::GetNumTile(int &num) const
1244{
1245    if (!isValid())
1246        return false;
1247    num = useCount;
1248    return true;
1249}
1250
1251// Copy operator
1252trpgTexture &trpgTexture::operator = (const trpgTexture &in)
1253{
1254    mode = in.mode;
1255    type = in.type;
1256
1257    if (in.name)
1258        SetName(in.name);
1259
1260    useCount = in.useCount;
1261
1262    sizeX = in.sizeX;
1263    sizeY = in.sizeY;
1264
1265    // RGBX
1266    numLayer = in.numLayer;
1267
1268    isMipmap = in.isMipmap;
1269    addr = in.addr;
1270
1271    writeHandle = in.writeHandle;
1272    handle = in.handle;
1273
1274    return *this;
1275}
1276
1277// Equality operator
1278int trpgTexture::operator == (const trpgTexture &in) const
1279{
1280    if (mode != in.mode)
1281        return 0;
1282
1283    switch (mode) {
1284    case External:
1285        if (!in.name && !name)
1286            return 1;
1287        if (!in.name || !name)
1288            return 0;
1289        return (!strcmp(in.name,name));
1290        break;
1291    case Local:
1292        if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY &&
1293            isMipmap == in.isMipmap &&
1294            addr.file == in.addr.file && addr.offset == in.addr.offset &&
1295            addr.row == in.addr.row && addr.col==in.addr.col )
1296            return 1;
1297        break;
1298    case Global:
1299    case Template:
1300        if (type == in.type && sizeX == in.sizeX && sizeY == in.sizeY &&
1301            isMipmap == in.isMipmap)
1302            return 1;
1303        break;
1304    }
1305
1306    return 0;
1307}
1308
1309// Utility functions
1310
1311int32 trpgTexture::CalcNumMipmaps() const
1312{
1313    // We're going to assume these are powers of two.
1314    // If not, then the writer's a moron.
1315
1316    // :))) The comment line above made me really loughing, Steve. - Nick
1317    int bval = MAX(sizeX,sizeY);
1318
1319    // Now look for the highest bit
1320    int p2;
1321    for (p2=0;p2<32;p2++)
1322        if ((1<<p2) & bval)
1323            break;
1324
1325    return p2+1;
1326}
1327
1328
1329// Note: replacing this with explicit sizes
1330int32 trpgTexture::CalcTotalSize() const
1331{
1332    (const_cast<trpgTexture *>(this))->CalcMipLevelSizes();
1333
1334    int totSize = 0;
1335    for (unsigned int i=0;i<storageSize.size();i++)
1336        totSize += storageSize[i];
1337
1338    return totSize;
1339}
1340
1341// Calculate the size of a given mip level
1342int32 trpgTexture::MipLevelSize(int miplevel)
1343{
1344
1345    if ( miplevel >= 0 && miplevel < CalcNumMipmaps() ) {
1346        if ( !storageSize.size() )
1347            CalcMipLevelSizes();
1348        return storageSize[miplevel];
1349    }
1350
1351    return 0;
1352}
1353
1354int32 trpgTexture::MipLevelOffset(int miplevel)
1355{
1356    if ( miplevel > 0 && miplevel < CalcNumMipmaps() ) {
1357        if ( !levelOffset.size() )
1358            CalcMipLevelSizes();
1359        return levelOffset[miplevel];
1360    }
1361
1362    return 0;
1363}
1364
1365
1366// Write function
1367bool trpgTexture::Write(trpgWriteBuffer &buf)
1368{
1369    if (!isValid()) return false;
1370
1371    buf.Begin(TRPGTEXTURE);
1372
1373    buf.Add(name);
1374    buf.Add(useCount);
1375    // New in 2.0 from here down
1376    buf.Add((unsigned char)mode);
1377    buf.Add((unsigned char)type);
1378    buf.Add(sizeX);
1379    buf.Add(sizeY);
1380    buf.Add(addr.file);
1381    buf.Add(addr.offset);
1382    buf.Add((int32)isMipmap);
1383    if(writeHandle) {
1384        buf.Add((int32)handle);
1385    }
1386    buf.End();
1387
1388    return true;
1389}
1390
1391// Read function
1392bool trpgTexture::Read(trpgReadBuffer &buf)
1393{
1394    char texName[1024];
1395
1396    try {
1397        buf.Get(texName,1023);
1398        SetName(texName);
1399        buf.Get(useCount);
1400
1401        mode = External;
1402        // New in 2.0 from here down
1403        unsigned char bval;
1404        buf.Get(bval);  mode = (trpgTexture::ImageMode)bval;
1405        buf.Get(bval);    type = (trpgTexture::ImageType)bval;
1406        GetImageDepth(numLayer); // heh
1407        buf.Get(sizeX);
1408        buf.Get(sizeY);
1409        buf.Get(addr.file);
1410        buf.Get(addr.offset);
1411        int32 ival;
1412        buf.Get(ival);
1413        // Read the handle if we can..
1414        try {
1415            int32 tempHandle;
1416            if(buf.Get(tempHandle))
1417            {
1418                writeHandle = true;
1419                handle = tempHandle;
1420            }
1421            else
1422            {
1423                handle = -1;
1424            }
1425        }
1426        catch (...) {
1427            handle = -1;
1428        }
1429        isMipmap = (ival) ? true : false;
1430    }
1431    catch (...) {
1432        return false;
1433    }
1434
1435    if (!isValid()) return false;
1436
1437    // calculate the mip level sizes
1438    CalcMipLevelSizes();
1439
1440    return true;
1441}
1442
1443void trpgTexture::CalcMipLevelSizes()
1444{
1445    int num_miplevels = (isMipmap ? CalcNumMipmaps() : 1);
1446    int level_size = 0;
1447    int level_offset = 0;
1448    int block_size = 0;
1449    int pixel_size = 0;
1450    int pad_size = 0;
1451    bool isDXT = false;
1452    bool isFXT = false;
1453
1454    switch (type) {
1455    case trpg_DXT1:
1456        isDXT = true;
1457        block_size = 8;
1458        break;
1459    case trpg_DXT3:
1460    case trpg_DXT5:
1461        isDXT = true;
1462        block_size = 16;
1463        break;
1464    case trpg_RGB8:
1465        pad_size = 4;
1466        pixel_size = 3;
1467        break;
1468    case trpg_RGBA8:
1469        pad_size = 4;
1470        pixel_size = 4;
1471        break;
1472    case trpg_RGBX:
1473        pad_size = 4;
1474        pixel_size = numLayer;
1475        break;
1476    case trpg_MCM5:
1477        pad_size = 4;
1478        pixel_size = 5;
1479        break;
1480    case trpg_MCM6R:
1481    case trpg_MCM6A:
1482        pad_size = 4;
1483        pixel_size = 6;
1484        break;
1485    case trpg_MCM7RA:
1486    case trpg_MCM7AR:
1487        pad_size = 4;
1488        pixel_size = 7;
1489        break;
1490    case trpg_INT8:
1491        pad_size = 4;
1492        pixel_size = 1;
1493        break;
1494    case trpg_INTA8:
1495        pad_size = 4;
1496        pixel_size = 2;
1497        break;
1498    case trpg_FXT1:
1499        isFXT = true;
1500        break;
1501    default:
1502        break;
1503    }
1504
1505
1506    levelOffset.clear();
1507    storageSize.clear();
1508
1509    levelOffset.push_back(level_offset);
1510
1511
1512
1513    if ( isDXT ) { // DXT compressed
1514        int num_x_blocks = ((sizeX/4)+(sizeX%4?1:0));
1515        int num_y_blocks = ((sizeY/4)+(sizeY%4?1:0));
1516
1517        level_size = num_x_blocks * num_y_blocks * block_size;
1518        storageSize.push_back(level_size);
1519
1520        for ( int i = 1; i < num_miplevels; i++ ) {
1521            level_offset += level_size;
1522            levelOffset.push_back(level_offset);
1523
1524            num_x_blocks /= 2;
1525            num_y_blocks /= 2;
1526            num_x_blocks = MAX(1,num_x_blocks);
1527            num_y_blocks = MAX(1,num_y_blocks);
1528
1529            level_size = num_x_blocks * num_y_blocks * block_size;
1530            storageSize.push_back(level_size);
1531        }
1532
1533        return;
1534    }
1535    if ( isFXT) {
1536        // bits per pixel and size
1537        int bpp = 4;
1538        int x = sizeX;
1539        int y = sizeY;
1540
1541        int nummiplevels = (isMipmap ? CalcNumMipmaps() : 1);
1542        for (int i = 0; i < nummiplevels; i++) {
1543            if (i > 0)
1544            levelOffset.push_back(level_offset);
1545
1546            x = ( x + 0x7 ) & ~0x7;
1547            y = ( y + 0x3 ) & ~0x3;
1548
1549            // Number of bytes
1550            level_size = ( x * y * bpp ) >> 3;
1551            storageSize.push_back(level_size);
1552            level_offset += level_size;
1553
1554            if (x > 1)  x /= 2;
1555            if (y > 1)  y /= 2;
1556        }
1557
1558        return;
1559    }
1560
1561    {
1562        int x_size = sizeX;
1563        int y_size = sizeY;
1564
1565        // Pad to a given size, if necessary
1566        int row_size = x_size * pixel_size;
1567        if (pad_size > 0) {
1568            int left = row_size%pad_size;
1569            if (left)
1570                row_size += pad_size - left;
1571        }
1572
1573        level_size = row_size * y_size;
1574        storageSize.push_back(level_size);
1575        for ( int i = 1; i < num_miplevels; i++ ) {
1576            level_offset += level_size;
1577            levelOffset.push_back(level_offset);
1578
1579            x_size /= 2;
1580            y_size /= 2;
1581            x_size = MAX(1,x_size);
1582            y_size = MAX(1,y_size);
1583
1584            row_size = x_size * pixel_size;
1585            if (pad_size > 0) {
1586                int left = row_size%pad_size;
1587                if (left)
1588                    row_size += pad_size - left;
1589            }
1590            level_size = row_size * y_size;
1591            storageSize.push_back(level_size);
1592        }
1593    }
1594}
1595
1596/* Texture Table
1597   Just a list of texture names so we can index.
1598*/
1599
1600// Constructor
1601trpgTexTable::trpgTexTable()
1602{
1603    currentRow = -1;
1604    currentCol = -1;
1605}
1606trpgTexTable::trpgTexTable(const trpgTexTable &in):
1607    trpgReadWriteable(in)
1608{
1609    *this = in;
1610}
1611
1612// Reset function
1613void trpgTexTable::Reset()
1614{
1615    errMess[0] = '\0';
1616    textureMap.clear();
1617    currentRow = -1;
1618    currentCol = -1;
1619}
1620
1621// Destructor
1622trpgTexTable::~trpgTexTable()
1623{
1624    Reset();
1625}
1626
1627// Validity check
1628bool trpgTexTable::isValid() const
1629{
1630    if (!textureMap.size())
1631    {
1632        strcpy(errMess, "Texture table list is empty");
1633        return false;
1634    }
1635
1636    TextureMapType::const_iterator itr = textureMap.begin();
1637    for (  ; itr != textureMap.end( ); itr++) {
1638        if(!itr->second.isValid()) {
1639            strcpy(errMess, "A texture in the texture table is invalid");
1640            return false;
1641        }
1642    }
1643    return true;
1644}
1645
1646
1647// Set functions
1648void trpgTexTable::SetNumTextures(int /*no*/)
1649{
1650    // obsolete. This method doesn't need to do anything since we're using a map instead of a vector.
1651    //    texList.resize(no);
1652}
1653int trpgTexTable::AddTexture(const trpgTexture &inTex)
1654{
1655
1656    TeAttrHdl hdl = inTex.GetHandle();
1657    if(hdl==-1) {
1658        // if no handle is specified, we will use an index as the handle (just like before 2.3)
1659        hdl = textureMap.size();
1660    }
1661    TextureMapType::iterator itr = textureMap.find(hdl);
1662    // Don't overwrite the texture if it was already there
1663    if(itr==textureMap.end())
1664        textureMap[hdl] = inTex;
1665    return hdl;
1666}
1667int trpgTexTable::FindAddTexture(const trpgTexture &inTex)
1668{
1669    TextureMapType::iterator itr = textureMap.begin();
1670    for (  ; itr != textureMap.end( ); itr++) {
1671        trpgTexture tx = itr->second;
1672        if(tx == inTex) {
1673            return itr->first;
1674        }
1675    }
1676    return AddTexture(inTex);
1677}
1678void trpgTexTable::SetTexture(int id,const trpgTexture &inTex)
1679{
1680    if (id < 0)
1681        return;
1682    textureMap[id] = inTex;
1683}
1684
1685// Copy operator
1686trpgTexTable &trpgTexTable::operator = (const trpgTexTable &in)
1687{
1688    Reset();
1689    TextureMapType::const_iterator itr = in.textureMap.begin();
1690    for (  ; itr != in.textureMap.end( ); itr++) {
1691        trpgTexture tex = itr->second;
1692        in.GetTexture(itr->first,tex);
1693        AddTexture(tex);
1694    }
1695
1696    return *this;
1697}
1698
1699// Write Texture table
1700bool trpgTexTable::Write(trpgWriteBuffer &buf)
1701{
1702    int32 numTex;
1703
1704    if (!isValid())
1705        return false;
1706
1707    buf.Begin(TRPGTEXTABLE2);
1708    numTex = textureMap.size();
1709    buf.Add(numTex);
1710    TextureMapType::iterator itr = textureMap.begin();
1711    for (  ; itr != textureMap.end( ); itr++) {
1712        itr->second.Write(buf);
1713    }
1714    buf.End();
1715
1716    return true;
1717}
1718
1719/* ***********
1720   Read Texture Table
1721   ***********
1722   */
1723// Get functions
1724bool trpgTexTable::GetNumTextures(int &no) const
1725{
1726    no = textureMap.size();
1727    if (!isValid()) return false;
1728    return true;
1729}
1730bool trpgTexTable::GetTexture(int id,trpgTexture &ret) const
1731{
1732    if (!isValid())
1733        return false;
1734    if (id < 0)
1735        return false;
1736    TextureMapType::const_iterator itr = textureMap.find(id);
1737    if(itr == textureMap.end()) {
1738        return false;
1739    }
1740    ret = itr->second;
1741
1742    return true;
1743}
1744const trpgTexture *trpgTexTable::GetTextureRef(int id) const
1745{
1746    if (id < 0)
1747        return false;
1748    TextureMapType::const_iterator itr = textureMap.find(id);
1749    if(itr == textureMap.end()) {
1750        return false;
1751    }
1752    const trpgTexture *ret = &(itr->second);
1753    return ret;
1754}
1755
1756const trpgTexture *trpgTexTable::FindByName(const char *name, int &texid) const
1757{
1758    TextureMapType::const_iterator itr = textureMap.begin();
1759    for (  ; itr != textureMap.end( ); itr++) {
1760        char thisName[1024];
1761        thisName[0] = '\0';
1762        itr->second.GetName(thisName,1023);
1763        if(strcasecmp(thisName,name)==0)
1764        {
1765            texid = itr->first;
1766            return &(itr->second);
1767        }
1768    }
1769    return false;
1770
1771}
1772
1773bool trpgTexTable::Read(trpgReadBuffer &buf)
1774{
1775    int32 numTex;
1776    trpgToken texTok;
1777    int32 len;
1778
1779    try {
1780        buf.Get(numTex);
1781
1782        for (int i=0;i<numTex;i++) {
1783            buf.GetToken(texTok,len);
1784            if (texTok != TRPGTEXTURE) throw 1;
1785            buf.PushLimit(len);
1786            trpgTexture tex;
1787            bool status = tex.Read(buf);
1788            //set the block for multi-archive archives (version>=2.3)
1789            if((currentRow!=-1)&&(currentCol!=-1)) {
1790                trpgwAppAddress taddr;
1791                tex.GetImageAddr(taddr);
1792                taddr.col = currentCol;
1793                taddr.row = currentRow;
1794                tex.SetImageAddr(taddr);
1795            }
1796            AddTexture(tex);
1797            buf.PopLimit();
1798            if (!status) throw 1;
1799        }
1800    }
1801    catch (...) {
1802        return false;
1803    }
1804
1805    return true;
1806}
1807
1808
1809/* **************
1810   Local Material
1811   **************
1812   */
1813
1814trpgLocalMaterial::trpgLocalMaterial()
1815{
1816    baseMat = -1;
1817    sx = sy = ex = ey = destWidth = destHeight = 0;
1818    addr.resize(1);
1819    addr[0].file = 0;
1820    addr[0].offset = 0;
1821    addr[0].col = -1;
1822    addr[0].row = -1;
1823}
1824
1825trpgLocalMaterial::~trpgLocalMaterial()
1826{
1827}
1828
1829void trpgLocalMaterial::SetBaseMaterial(int32 subTable,int32 inMatID)
1830{
1831    baseMatTable = subTable;
1832    baseMat = inMatID;
1833}
1834
1835void trpgLocalMaterial::Reset()
1836{
1837    baseMat = -1;
1838    sx = sy = ex = ey = destWidth = destHeight = 0;
1839//    storageSize.resize(0);
1840    addr.resize(1);
1841    addr[0].file = 0;
1842    addr[0].offset = 0;
1843    addr[0].col = -1;
1844    addr[0].row = -1;
1845}
1846
1847bool trpgLocalMaterial::GetBaseMaterial(int32 &subTable,int32 &matID) const
1848{
1849    if (!isValid()) return false;
1850
1851    subTable = baseMatTable;
1852    matID = baseMat;
1853    return true;
1854}
1855
1856void trpgLocalMaterial::SetSubImageInfo(const SubImageInfo &info)
1857{
1858    sx = info.sx;
1859    sy = info.sy;
1860    ex = info.ex;
1861    ey = info.ey;
1862    destWidth = info.destWidth;
1863    destHeight = info.destHeight;
1864}
1865
1866bool trpgLocalMaterial::GetSubImageInfo(SubImageInfo &info) const
1867{
1868    if (!isValid()) return false;
1869
1870    info.sx = sx;
1871    info.sy = sy;
1872    info.ex = ex;
1873    info.ey = ey;
1874    info.destWidth = destWidth;
1875    info.destHeight = destHeight;
1876
1877    return true;
1878}
1879
1880void trpgLocalMaterial::SetAddr(const trpgwAppAddress &inAddr)
1881{
1882    addr[0] = inAddr;
1883}
1884
1885void trpgLocalMaterial::SetNthAddr(unsigned int subtable, const trpgwAppAddress &inAddr)
1886{
1887    if (addr.size()<=subtable) addr.resize(subtable+1);
1888    addr[subtable] = inAddr;
1889}
1890
1891bool trpgLocalMaterial::GetAddr(trpgwAppAddress &inAddr) const
1892{
1893    if (!isValid()) return false;
1894
1895    inAddr = addr[0];
1896    return true;
1897}
1898
1899bool trpgLocalMaterial::GetNthAddr(unsigned int subtable, trpgwAppAddress &inAddr) const
1900{
1901    if (!isValid()) return false;
1902    if (addr.size()<=subtable) return false;
1903    inAddr = addr[subtable];
1904    return true;
1905}
1906
1907bool trpgLocalMaterial::GetNumLocals(int &numLocals) const
1908{
1909    if (!isValid()) return false;
1910    // not checking for tile local, that's up to you.
1911    numLocals=addr.size();
1912    return true;
1913}
1914
1915/*bool trpgLocalMaterial::SetStorageSizes(int level,vector<int> *inSizes)
1916  {
1917  storageSize.resize(inSizes->size());
1918  for (int i=0;i<inSizes->size();i++)
1919  storageSize[i] = (*inSizes)[i];
1920
1921  return true;
1922  }*/
1923
1924/*bool trpgLocalMaterial::GetStorageSizes(const vector<int> *retSize)
1925  {
1926  if (!isValid()) return false;
1927
1928  retSize = storageSize;
1929  return true;
1930  }*/
1931
1932bool trpgLocalMaterial::isValid() const
1933{
1934    if (baseMat < 0) return false;
1935
1936    return true;
1937}
1938
1939// Write method
1940
1941bool trpgLocalMaterial::Write(trpgWriteBuffer &buf)
1942{
1943    if (!isValid())
1944        return false;
1945
1946    buf.Begin(TRPGLOCALMATERIAL);
1947
1948    // Write the data
1949    buf.Add(baseMatTable);
1950    buf.Add(baseMat);
1951    buf.Add(sx);
1952    buf.Add(sy);
1953    buf.Add(ex);
1954    buf.Add(ey);
1955    buf.Add(destWidth);
1956    buf.Add(destHeight);
1957    buf.Add(addr[0].file);
1958    buf.Add(addr[0].offset);
1959    // and in case there's more...
1960    int numAddrs=(int)(addr.size());
1961    if (numAddrs>1) {
1962        buf.Add(numAddrs-1); // suppressed due to breaking old readers.
1963        for (int i=1;i<numAddrs;i++) {
1964            buf.Add(addr[i].file);
1965            buf.Add(addr[i].offset);
1966        }
1967    }
1968    buf.End();
1969
1970    return true;
1971}
1972
1973// Read method
1974
1975bool trpgLocalMaterial::Read(trpgReadBuffer &buf)
1976{
1977    try {
1978        buf.Get(baseMatTable);
1979        buf.Get(baseMat);
1980        buf.Get(sx);
1981        buf.Get(sy);
1982        buf.Get(ex);
1983        buf.Get(ey);
1984        buf.Get(destWidth);
1985        buf.Get(destHeight);
1986        buf.Get(addr[0].file);
1987        buf.Get(addr[0].offset);
1988        if ( !buf.isEmpty() ) {
1989            // there might be more
1990            int extraAddrs;
1991            buf.Get(extraAddrs);
1992            if (extraAddrs!=0) {
1993                addr.resize(extraAddrs+1);
1994                for (int i=1;i<=extraAddrs;i++) {
1995                    buf.Get(addr[i].file);
1996                    buf.Get(addr[i].offset);
1997                    addr[i].col = -1;
1998                    addr[i].row = -1;
1999                }
2000            }
2001        }
2002    }
2003    catch (...) {
2004        return false;
2005    }
2006
2007    return isValid();
2008}
Note: See TracBrowser for help on using the browser.