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

Revision 13041, 14.2 kB (checked in by robert, 3 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
21/* trpage_tile.cpp
22    This source file contains the implementation of trpgTileTable and trpgTileHeader.
23    You'll need to edit these if you want to add something to the Tile Table (at
24     the front of an archive) or the Tile Header (at the beginning of each tile).
25     */
26
27#include <trpage_geom.h>
28#include <trpage_read.h>
29
30/* Write Tile Table
31    Keeps track of tiles written to disk.
32    */
33
34// Constructor
35trpgTileTable::trpgTileTable()
36{
37    localBlock = false;
38    Reset();
39}
40
41// Reset function
42void trpgTileTable::Reset()
43{
44    errMess[0] = '\0';
45    mode = External;
46    lodInfo.resize(0);
47    valid = true;
48    currentRow = -1;
49    currentCol = -1;
50
51}
52
53// Destructor
54trpgTileTable::~trpgTileTable()
55{
56}
57
58// Set functions
59
60void trpgTileTable::SetMode(TileMode inMode)
61{
62    Reset();
63    mode = inMode;
64}
65
66void trpgTileTable::SetNumLod(int numLod)
67{
68    lodInfo.resize(numLod);
69}
70
71
72void trpgTileTable::SetNumTiles(int nx,int ny,int lod)
73{
74
75    if(localBlock) {
76        LodInfo &li = lodInfo[lod];
77        li.numX = nx;  li.numY = ny;
78        li.addr.resize(1);
79        li.elev_min.resize(1,0.0);
80        li.elev_max.resize(1,0.0);
81        valid = true;
82        // no need to do anything else if we only have one block.
83        return;
84    }
85    if (nx <= 0 || ny <= 0 || lod < 0 || lod >= static_cast<int>(lodInfo.size()))
86        return;
87
88    // Got a table we need to maintain
89    if (mode == Local || mode == ExternalSaved) {
90        // If there's a pre-existing table, we need to preserve the entries
91        LodInfo oldLodInfo = lodInfo[lod];
92
93        LodInfo &li = lodInfo[lod];
94        li.numX = nx;  li.numY = ny;
95        int numTile = li.numX*li.numY;
96        li.addr.resize(numTile);
97        li.elev_min.resize(numTile,0.0);
98        li.elev_max.resize(numTile,0.0);
99
100        // Copy pre-existing data if it's there
101        if (oldLodInfo.addr.size() > 0) {
102            for (int x=0;x<oldLodInfo.numX;x++) {
103            for (int y=0;y<oldLodInfo.numY;y++) {
104                int oldLoc = y*oldLodInfo.numX + x;
105                int newLoc = y*li.numX + x;
106                li.addr[newLoc] = oldLodInfo.addr[oldLoc];
107                li.elev_min[newLoc] = oldLodInfo.elev_min[oldLoc];
108                li.elev_max[newLoc] = oldLodInfo.elev_max[oldLoc];
109            }
110            }
111        }
112    }
113    valid = true;
114}
115void trpgTileTable::SetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 zmin,float32 zmax)
116{
117    if (lod < 0 || lod >= static_cast<int>(lodInfo.size()))
118        return;
119    if (mode == External)
120        return;
121    LodInfo &li = lodInfo[lod];
122    int loc;
123    if(localBlock) {
124        loc = 0;
125    }
126    else {
127        if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
128            return;
129        loc = y*li.numX + x;
130    }
131    li.addr[loc] = ref;
132    li.elev_min[loc] = zmin;
133    li.elev_max[loc] = zmax;
134}
135
136bool trpgTileTable::isValid() const
137{
138    return valid;
139}
140
141// Get methods
142
143bool trpgTileTable::GetMode(TileMode &outMode) const
144{
145    if (!isValid())  return false;
146
147    outMode = mode;
148    return true;
149}
150
151bool trpgTileTable::GetTile(int x,int y,int lod,trpgwAppAddress &ref,float32 &zmin,float32 &zmax) const
152{
153    if (!isValid()) return false;
154
155    if (lod < 0 || lod >= static_cast<int>(lodInfo.size())) return false;
156    if (mode == External)
157        return false;
158
159    const LodInfo &li = lodInfo[lod];
160    int loc;
161    if(localBlock) {
162        loc = 0;
163    }
164    else {
165        if (x < 0 || x >= li.numX || y < 0 || y >= li.numY)
166            return false;
167        loc = y*li.numX + x;
168    }
169
170    ref = li.addr[loc];
171    zmin = li.elev_min[loc];
172    zmax = li.elev_max[loc];
173
174    return true;
175}
176
177// Write tile table
178bool trpgTileTable::Write(trpgWriteBuffer &buf)
179{
180    if (!isValid())
181        return false;
182
183    buf.Begin(TRPGTILETABLE2);
184
185    // Write the mode
186    buf.Add(mode);
187
188    // Depending on the mode we'll have a lot or a little data
189    if (mode == Local || mode == ExternalSaved) {
190        // The lod sizing is redundant, but it's convenient here
191        int numLod = lodInfo.size();
192        buf.Add(numLod);
193
194        // Write each terrain LOD set
195        for (int i=0;i<numLod;i++) {
196            LodInfo &li = lodInfo[i];
197            if(localBlock) {
198                // only one x and one y in a local archive
199                buf.Add(1);
200                buf.Add(1);
201                // local blocks always use index 0
202                trpgwAppAddress &ref = li.addr[0];
203                buf.Add((int32)ref.file);
204                buf.Add((int32)ref.offset);
205
206                buf.Add(li.elev_min[0]);
207                buf.Add(li.elev_max[0]);
208            }
209            else {
210                buf.Add(li.numX);
211                buf.Add(li.numY);
212                // Now for the interesting stuff
213                unsigned int j;
214                for (j=0;j<li.addr.size();j++) {
215                    trpgwAppAddress &ref = li.addr[j];
216                    buf.Add((int32)ref.file);
217                    buf.Add((int32)ref.offset);
218                }
219                for (j=0;j<li.elev_min.size();j++) {
220                    buf.Add(li.elev_min[j]);
221                    buf.Add(li.elev_max[j]);
222                }
223            }
224        }
225    }
226
227    buf.End();
228
229    return true;
230}
231
232/*    **************
233    Tile Table Read method
234    **************
235    */
236
237
238bool trpgTileTable::Read(trpgReadBuffer &buf)
239{
240    valid = false;
241
242    try {
243        int imode;
244        buf.Get(imode);  mode = (TileMode)imode;
245        if (mode != External && mode != Local && mode != ExternalSaved)  throw 1;
246        if (mode == Local || mode == ExternalSaved) {
247            int numLod;
248            buf.Get(numLod);
249            if (numLod <= 0) throw 1;
250            lodInfo.resize(numLod);
251
252            for (int i=0;i<numLod;i++) {
253
254                LodInfo &li = lodInfo[i];
255                if(localBlock) {
256                    if(li.addr.size()==0) {
257                        li.addr.resize(1);
258                        li.elev_min.resize(1,0.0);
259                        li.elev_max.resize(1,0.0);
260                    }
261                    int32 x,y;
262                    buf.Get(x);
263                    buf.Get(y);
264                    int pos = (currentRow * li.numX) + currentCol;
265                    int32 file,offset;
266                    buf.Get(file);
267                    buf.Get(offset);
268                    trpgwAppAddress &ref = li.addr[pos];
269                    ref.file = file;
270                    ref.offset = offset;
271                    ref.col = currentCol;
272                    ref.row = currentRow;
273
274                    float emin,emax;
275                    buf.Get(emin);
276                    buf.Get(emax);
277
278                    li.elev_max[pos] = emax;
279                    li.elev_min[pos] = emin;
280                }
281                else {
282                    buf.Get(li.numX);
283                    buf.Get(li.numY);
284                    if (li.numX <= 0 || li.numY <= 0)
285                        throw 1;
286                    int numTile = li.numX*li.numY;
287                    li.addr.resize(numTile);
288                    li.elev_min.resize(numTile);
289                    li.elev_max.resize(numTile);
290                    int j;
291                    for (j=0;j<numTile;j++) {
292                        int32 file,offset;
293                        buf.Get(file);
294                        buf.Get(offset);
295                        trpgwAppAddress &ref = li.addr[j];
296                        ref.file = file;
297                        ref.offset = offset;
298                    }
299                    for (j=0;j<numTile;j++) {
300                        float emin,emax;
301                        buf.Get(emin);
302                        buf.Get(emax);
303                        li.elev_max[j] = emax;
304                        li.elev_min[j] = emin;
305                    }
306                }
307            }
308        }
309
310        valid = true;
311    }
312    catch (...) {
313        printf("Caught an exception\n");
314        return false;
315    }
316
317    return isValid();
318}
319
320/* Tile Header
321    Each distinct tile (or model) must have a header
322     which tells you what models and materials are
323     referenced in that tile.
324     */
325// Constructor
326trpgTileHeader::trpgTileHeader()
327{
328    col = -1;
329    row = -1;
330}
331trpgTileHeader::~trpgTileHeader()
332{
333}
334
335void trpgTileHeader::Reset()
336{
337    matList.resize(0);
338    modelList.resize(0);
339    locMats.resize(0);
340    col = -1;
341    row = -1;
342}
343
344// Set functions
345void trpgTileHeader::SetMaterial(int no,int id)
346{
347    if (no < 0 || no >= static_cast<int>(matList.size()))
348        return;
349    matList[no] = id;
350}
351void trpgTileHeader::SetModel(int no,int id)
352{
353    if (no < 0 || no >= static_cast<int>(modelList.size()))
354        return;
355    modelList[no] = id;
356}
357
358// Set functions
359void trpgTileHeader::AddMaterial(int id)
360{
361    // Look for it first
362    for (unsigned int i=0;i<matList.size();i++)
363        if (matList[i] == id)
364            return;
365    // Didn't find it, add it.
366    matList.push_back(id);
367}
368void trpgTileHeader::AddModel(int id)
369{
370    for (unsigned int i=0;i<modelList.size();i++)
371        if (modelList[i] == id)
372            return;
373    modelList.push_back(id);
374}
375void trpgTileHeader::SetDate(int32 d)
376{
377    date = d;
378}
379
380// Local material methods
381
382void trpgTileHeader::AddLocalMaterial(trpgLocalMaterial &locMat)
383{
384    locMats.push_back(locMat);
385}
386
387bool trpgTileHeader::GetNumLocalMaterial(int32 &retNum) const
388{
389    if (!isValid()) return false;
390    retNum = locMats.size();
391
392    return true;
393}
394
395bool trpgTileHeader::GetLocalMaterial(int32 id,trpgLocalMaterial &retMat) const
396{
397    if (id < 0 || id >= static_cast<int>(locMats.size()))
398    return false;
399
400    retMat = locMats[id];
401
402    return true;
403}
404
405const std::vector<trpgLocalMaterial> *trpgTileHeader::GetLocalMaterialList() const
406{
407    if (!isValid())  return NULL;
408
409    return &locMats;
410}
411
412// Get methods
413bool trpgTileHeader::GetNumMaterial(int32 &no) const
414{
415    if (!isValid()) return false;
416    no = matList.size();
417    return true;
418}
419bool trpgTileHeader::GetMaterial(int32 id,int32 &mat) const
420{
421    if (!isValid() || id < 0 || id >= static_cast<int>(matList.size()))
422        return false;
423    mat = matList[id];
424    return true;
425}
426bool trpgTileHeader::GetNumModel(int32 &no) const
427{
428    if (!isValid()) return false;
429    no = modelList.size();
430    return true;
431}
432bool trpgTileHeader::GetModel(int32 id,int32 &m) const
433{
434    if (!isValid() || id < 0 || id >= static_cast<int>(modelList.size()))
435        return false;
436    m = modelList[id];
437    return true;
438}
439bool trpgTileHeader::GetDate(int32 &d) const
440{
441    if (!isValid()) return false;
442    d = date;
443    return true;
444}
445
446// Validity check
447bool trpgTileHeader::isValid() const
448{
449    return true;
450}
451
452// Write to a buffer
453bool trpgTileHeader::Write(trpgWriteBuffer &buf)
454{
455    unsigned int i;
456
457    if (!isValid())
458        return false;
459    for (i=0;i<locMats.size();i++)
460        if (!locMats[i].isValid())
461        return false;
462
463    buf.Begin(TRPGTILEHEADER);
464
465    buf.Begin(TRPG_TILE_MATLIST);
466    buf.Add((int32)matList.size());
467    for (i=0;i<matList.size();i++)
468        buf.Add(matList[i]);
469    buf.End();
470    buf.Begin(TRPG_TILE_MODELLIST);
471    buf.Add((int32)modelList.size());
472    for (i=0;i<modelList.size();i++)
473        buf.Add(modelList[i]);
474    buf.End();
475    buf.Begin(TRPG_TILE_DATE);
476    buf.Add(date);
477    buf.End();
478    buf.Begin(TRPG_TILE_LOCMATLIST);
479    buf.Add((int32)locMats.size());
480    for (i=0;i<locMats.size();i++)
481        locMats[i].Write(buf);
482    buf.End();
483
484    buf.End();
485
486    return true;
487}
488
489// Tile Header CB
490// Used to aid in parsing tile header
491// We want the tile header to be expandable, so be careful here
492class tileHeaderCB : public trpgr_Callback {
493public:
494    void * Parse(trpgToken,trpgReadBuffer &);
495    trpgTileHeader *head;
496};
497
498void * tileHeaderCB::Parse(trpgToken tok,trpgReadBuffer &buf)
499{
500    int32 no,id,date,i;
501
502    try {
503        switch (tok) {
504        case TRPG_TILE_MATLIST:
505            buf.Get(no);
506            if (no < 0)  throw 1;
507            for (i = 0;i < no; i++) {
508                buf.Get(id);
509                head->AddMaterial(id);
510            }
511            break;
512        case TRPG_TILE_MODELLIST:
513            buf.Get(no);
514            if (no < 0)  throw 1;
515            for (i=0;i<no;i++) {
516                buf.Get(id);
517                head->AddModel(id);
518            }
519            break;
520        case TRPG_TILE_DATE:
521            buf.Get(date);
522            head->SetDate(date);
523            break;
524        case TRPG_TILE_LOCMATLIST:
525            {
526                int32 numLocMat;
527                buf.Get(numLocMat);
528                if (numLocMat < 0)  throw 1;
529                std::vector<trpgLocalMaterial> *locMats;
530                locMats = const_cast<std::vector<trpgLocalMaterial> *> (head->GetLocalMaterialList());
531                locMats->resize(numLocMat);
532                for (i=0;i<numLocMat;i++) {
533                    trpgToken matTok;
534                    int32 len;
535                    buf.GetToken(matTok,len);
536                    if (matTok != TRPGLOCALMATERIAL)  throw 1;
537                    buf.PushLimit(len);
538                    trpgLocalMaterial &locMat = (*locMats)[i];
539                    locMat.Read(buf);
540                    // Set the row/col for later finding
541                    trpgwAppAddress addr;
542                    locMat.GetAddr(addr);
543                    head->GetBlockNo(addr.row,addr.col);
544                    locMat.SetAddr(addr);
545
546                    buf.PopLimit();
547                }
548            }
549            break;
550        default:
551            // Don't care
552            break;
553        }
554    }
555    catch (...) {
556        return NULL;
557    }
558
559    return head;
560}
561
562// Read tile header
563bool trpgTileHeader::Read(trpgReadBuffer &buf)
564{
565    tileHeaderCB tcb;
566    trpgr_Parser parse;
567
568    tcb.head = this;
569    parse.AddCallback(TRPG_TILE_MATLIST,&tcb,false);
570    parse.AddCallback(TRPG_TILE_MODELLIST,&tcb,false);
571    parse.AddCallback(TRPG_TILE_DATE,&tcb,false);
572    // New for 2.0
573    parse.AddCallback(TRPG_TILE_LOCMATLIST,&tcb,false);
574    parse.Parse(buf);
575
576    return isValid();
577}
Note: See TracBrowser for help on using the browser.