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

Revision 13041, 16.6 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
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20
21/* trpage_scene.cpp
22    This file implements a bunch of stuff, all of it optional.  See trpage_scene.h
23     for more information.
24    Scene Graph nodes -
25     All the methods for the simple scene graph are here.
26    trpgSceneGraphParser -
27     This is a subclass of trpgSceneParser.  It uses that utility class to keep track
28      of pushes and pops.  It also registers an interest in all the node types it
29      knows about (Geometry,Group,LOD,ModelRef).  When one of those is encountered
30      by the trpgr_Parser (which it's also a subclass of) it reads it into the
31      appropriate trpgRead* type.
32     Unless you're reading into the scene graph defined in trpage_scene.h, you won't
33      use this class directly.  Instead, copy it and use it as a template for how
34      to read into a scene graph.  You'll need to replace the helpers, primarily.
35    */
36
37#include <trpage_read.h>
38#include <trpage_scene.h>
39
40/*  ****************
41    MBR Calculation and handling
42    ****************
43    */
44trpgMBR::trpgMBR()
45{
46    valid = false;
47}
48bool trpgMBR::isValid() const
49{
50    return valid;
51}
52void trpgMBR::Reset()
53{
54    valid = false;
55}
56trpg3dPoint trpgMBR::GetLL() const
57{
58    return ll;
59}
60trpg3dPoint trpgMBR::GetUR() const
61{
62    return ur;
63}
64void trpgMBR::AddPoint(const trpg3dPoint &pt)
65{
66    if (valid) {
67        ll.x = MIN(pt.x,ll.x);
68        ll.y = MIN(pt.y,ll.y);
69        ll.z = MIN(pt.z,ll.z);
70        ur.x = MAX(pt.x,ur.x);
71        ur.y = MAX(pt.y,ur.y);
72        ur.z = MAX(pt.z,ur.z);
73    } else {
74        valid = true;
75        ll = ur = pt;
76    }
77}
78void trpgMBR::AddPoint(double x,double y,double z)
79{
80    AddPoint(trpg3dPoint(x,y,z));
81}
82void trpgMBR::GetMBR(trpg3dPoint &oll,trpg3dPoint &our) const
83{
84    oll = ll;
85    our = ur;
86}
87// Add the input MBR to this one
88void trpgMBR::Union(const trpgMBR &in)
89{
90    if (valid) {
91        if (in.isValid()) {
92            AddPoint(in.GetLL());
93            AddPoint(in.GetUR());
94        }
95    } else {
96        valid = true;
97        *this = in;
98    }
99}
100// See if there's any overlap between the two MBRs
101bool trpgMBR::Overlap(const trpg2dPoint &ill, const trpg2dPoint &iur) const
102{
103    if (!isValid()) return false;
104
105    trpg2dPoint ilr = trpg2dPoint(iur.x,ill.y);
106    trpg2dPoint iul = trpg2dPoint(ill.x,iur.y);
107
108    // B MBR falls within A
109    if (Within(ill) || Within(iur) || Within(ilr) || Within(iul))
110        return true;
111
112    // A MBR falls within B
113    if ((inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ll.y)) ||
114        (inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ll.y)) ||
115        (inRange(ill.x,iur.x,ur.x) && inRange(ill.y,iur.y,ur.y)) ||
116        (inRange(ill.x,iur.x,ll.x) && inRange(ill.y,iur.y,ur.y)))
117        return true;
118
119    if ((inRange(ll.x,ur.x,ill.x) && ill.y < ll.y && iur.y > ur.y) ||
120        (inRange(ll.y,ur.y,ill.y) && ill.x < ll.x && iur.x > ur.x))
121        return true;
122
123    return false;
124}
125// Check if a given 2d point is within the MBR
126bool trpgMBR::Within(const trpg2dPoint &pt) const
127{
128    if (inRange(ll.x,ur.x,pt.x) && inRange(ll.y,ur.y,pt.y))
129        return true;
130    return false;
131}
132
133/*    ****************
134    Read Group Base
135    Base class for all group structures.
136    ****************
137    */
138
139// Destructor
140trpgReadGroupBase::~trpgReadGroupBase()
141{
142    DeleteChildren();
143}
144
145// Delete all children
146void trpgReadGroupBase::DeleteChildren()
147{
148    for (unsigned int i=0;i<children.size();i++)
149        if (children[i])
150            delete children[i];
151}
152
153// Add a child to the list
154void trpgReadGroupBase::AddChild(trpgReadNode *n)
155{
156    children.push_back(n);
157}
158
159// Unref a child (but don't delete it)
160void trpgReadGroupBase::unRefChild(int id)
161{
162    if (id < 0 || id >= (int)children.size())
163        return;
164    children[id] = NULL;
165}
166
167// Unref all the children (they've probably been moved elsewhere)
168void trpgReadGroupBase::unRefChildren()
169{
170    for (unsigned int i=0;i<children.size();i++)
171        unRefChild(i);
172}
173
174// Calculate an MBR
175trpgMBR trpgReadGroupBase::GetMBR() const
176{
177    if (mbr.isValid())
178        return mbr;
179    else {
180        // Calculate and cache a new MBR
181        trpgMBR *cmbr = const_cast<trpgMBR *>(&mbr);
182        trpgMBR kmbr;
183        // Ask the kids
184        for (unsigned int i=0;i<children.size();i++) {
185            kmbr = children[i]->GetMBR();
186            cmbr->Union(kmbr);
187        }
188        return *cmbr;
189    }
190}
191
192/*  ****************
193    Read Geometry
194    ****************
195    */
196// Calculate an MBR
197trpgMBR trpgReadGeometry::GetMBR() const
198{
199    if (mbr.isValid())
200        return mbr;
201
202    trpgMBR *pmbr = const_cast<trpgMBR *>(&mbr);
203
204    int numVert,i;
205    trpg3dPoint pt;
206    data.GetNumVertex(numVert);
207    numVert /= 3;
208    for (i=0;i<numVert;i++) {
209        data.GetVertex(i,pt);
210        pmbr->AddPoint(pt);
211    }
212
213    return mbr;
214}
215
216/*    ****************
217    Scene Graph Parser
218    ****************
219    */
220
221/* Scene Graph Parser Helpers
222    Each of these classes reads a certain kind of data (e.g. a group)
223     and creates the appropriate trpgrRead* form and returns that.
224     */
225
226/* This is a helper registered by trpgSceneGraphParser that readers trpgGeometry
227    nodes and adds them to the current scene graph.  trpgGeometry nodes are
228    always leaves so there should be no pushes after this node.  The Parse method
229    also adds the new node as a child to any existing (e.g. top) group.
230    {group:Demonstration Scene Graph}
231 */
232class trpgReadGeometryHelper : public trpgr_Callback {
233public:
234    trpgReadGeometryHelper(trpgSceneGraphParser *in_parse) { parse = in_parse;}
235    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
236        trpgReadGeometry *geom = new trpgReadGeometry();
237        trpgGeometry *data = geom->GetData();
238        if (!data->Read(buf)) {
239            delete geom;
240            return NULL;
241        }
242        trpgReadGroupBase *top = parse->GetCurrTop();
243        if (top)
244            top->AddChild(geom);
245        else
246            delete geom;
247
248        return geom;
249    }
250protected:
251    trpgSceneGraphParser *parse;
252};
253
254/* This helper is registered by trpgSceneGraphParser.  It reads a trpgGroup
255    from the trpgReadBuffer.  It then adds it to our current scene graph.
256    It also adds an index corresponding to the group's group ID in our group
257    mapping in trpgSceneGraphParser.  The new group becomes the top one
258    after returning from the Parse call.
259    {group:Demonstration Scene Graph}
260 */
261class trpgReadGroupHelper : public trpgr_Callback {
262public:
263    trpgReadGroupHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
264    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
265        trpgReadGroup *group = new trpgReadGroup();
266        trpgGroup *data = group->GetData();
267        if (!data->Read(buf)) {
268            delete group;
269            return NULL;
270        }
271        trpgReadGroupBase *top = parse->GetCurrTop();
272        if (top)
273            top->AddChild(group);
274        else
275            delete group;
276        // Add to the group map
277        int id;
278        data->GetID(id);
279        trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
280        (*gmap)[id] = group;
281        return group;
282    }
283protected:
284    trpgSceneGraphParser *parse;
285};
286class trpgReadBillboardHelper : public trpgr_Callback {
287public:
288    trpgReadBillboardHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
289    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
290        trpgReadBillboard *group = new trpgReadBillboard();
291        trpgBillboard *data = group->GetData();
292        if (!data->Read(buf)) {
293            delete group;
294            return NULL;
295        }
296        trpgReadGroupBase *top = parse->GetCurrTop();
297        if (top)
298            top->AddChild(group);
299        else
300            delete group;
301        // Add to the group map
302        int id;
303        data->GetID(id);
304        trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
305        (*gmap)[id] = group;
306        return group;
307    }
308protected:
309    trpgSceneGraphParser *parse;
310};
311class trpgReadAttachHelper : public trpgr_Callback {
312public:
313    trpgReadAttachHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
314    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
315        trpgReadAttach *attach = new trpgReadAttach();
316        trpgAttach *data = attach->GetData();
317        if (!data->Read(buf)) {
318            delete attach;
319            return NULL;
320        }
321        trpgReadGroupBase *top = parse->GetCurrTop();
322        if (top)
323            top->AddChild(attach);
324        else
325            delete attach;
326        // Add to the group map
327        int id;
328        data->GetID(id);
329        trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
330        (*gmap)[id] = attach;
331        return attach;
332    }
333protected:
334    trpgSceneGraphParser *parse;
335};
336
337class trpgReadChildRefHelper : public trpgr_Callback {
338public:
339    trpgReadChildRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
340    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
341        trpgReadChildRef *childRef = new trpgReadChildRef();
342        trpgChildRef *data = childRef->GetData();
343        if (!data->Read(buf)) {
344            delete childRef;
345            return NULL;
346        }
347        trpgReadGroupBase *top = parse->GetCurrTop();
348        // NOTE: this is bad, we delete the pointer then we save it.
349      //       this is done everywhere and should be corrected
350      if (top)
351            top->AddChild(childRef);
352        else
353            delete childRef;
354
355        return childRef;
356    }
357protected:
358    trpgSceneGraphParser *parse;
359};
360class trpgReadLodHelper : public trpgr_Callback {
361public:
362    trpgReadLodHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
363    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
364        trpgReadLod *lod = new trpgReadLod();
365        trpgLod *data = lod->GetData();
366        if (!data->Read(buf)) {
367            delete lod;
368            return NULL;
369        }
370        trpgReadGroupBase *top = parse->GetCurrTop();
371        if (top)
372            top->AddChild(lod);
373        else
374            delete lod;
375        // Add to the group map
376        int id;
377        data->GetID(id);
378        trpgSceneGraphParser::GroupMap *gmap = parse->GetGroupMap();
379        (*gmap)[id] = lod;
380        return lod;
381    }
382protected:
383    trpgSceneGraphParser *parse;
384};
385class trpgReadModelRefHelper : public trpgr_Callback {
386public:
387    trpgReadModelRefHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
388    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
389        trpgReadModelRef *mod = new trpgReadModelRef();
390        trpgModelRef *data = mod->GetData();
391        if (!data->Read(buf)) {
392            delete mod;
393            return NULL;
394        }
395        trpgReadGroupBase *top = parse->GetCurrTop();
396        if (top)
397            top->AddChild(mod);
398        else
399            delete mod;
400        return mod;
401    }
402protected:
403    trpgSceneGraphParser *parse;
404};
405class trpgReadTileHeaderHelper : public trpgr_Callback {
406public:
407    trpgReadTileHeaderHelper(trpgSceneGraphParser *in_parse) { parse = in_parse; }
408    void *Parse(trpgToken /*tok*/,trpgReadBuffer &buf) {
409        trpgReadTileHeader *th = parse->GetTileHeaderRef();
410        trpgTileHeader *data = th->GetData();
411        if (!data->Read(buf))
412            return NULL;
413        return th;
414    }
415protected:
416    trpgSceneGraphParser *parse;
417};
418
419/* The Scene Graph Parser constructor does two things.  First, it sets
420    up any internal variables like a normal constructor.  Then it registers
421    an interest in all the node types it knows how to parse.  It does this
422    by calling AddCallback, which is a method of its parent.  It passes in
423    a token representing the node type (see trpg_io.h) and an object that
424    is capable of parsing the given type.
425
426    The objects we pass in here are called helpers.  They parse specific
427    objects and add them to the user defined scene graph.  Examples include
428    trpgReadGeometryHelper, trpgReadGroupHelper, trpgReadAttachHelper,
429    trpgReadBillboardHelper, trpgReadLodHelper, trpgReadModelRefHelper,
430    trpgReadTileHeaderHelper.  These are all derived from trpgr_Callback.
431    You should not use any of these yourself. Instead look at these classes
432    as examples of how to implement your own subclass of trpgSceneParser.
433    */
434trpgSceneGraphParser::trpgSceneGraphParser()
435{
436    top = currTop = NULL;
437
438    // Register the readers
439    AddCallback(TRPG_GEOMETRY,new trpgReadGeometryHelper(this));
440    AddCallback(TRPG_GROUP,new trpgReadGroupHelper(this));
441    AddCallback(TRPG_ATTACH,new trpgReadAttachHelper(this));
442   AddCallback(TRPG_CHILDREF,new trpgReadChildRefHelper(this));
443    AddCallback(TRPG_BILLBOARD,new trpgReadBillboardHelper(this));
444    AddCallback(TRPG_LOD,new trpgReadLodHelper(this));
445//    AddCallback(TRPG_TRANSFORM,new trpgReadTransformHelper(this));
446    AddCallback(TRPG_MODELREF,new trpgReadModelRefHelper(this));
447//    AddCallback(TRPG_LAYER,new trpgReadLayerHelper(this));
448    AddCallback(TRPGTILEHEADER,new trpgReadTileHeaderHelper(this));
449}
450
451// Get Current Top node
452trpgReadGroupBase *trpgSceneGraphParser::GetCurrTop()
453{
454    if (!currTop)
455        return NULL;
456    if (currTop->isGroupType())
457        return (trpgReadGroupBase *)currTop;
458
459    return NULL;
460}
461
462// Return a pointer to the tile header record
463trpgReadTileHeader *trpgSceneGraphParser::GetTileHeaderRef()
464{
465    return &tileHead;
466}
467
468// Parse Scene
469// Parse a buffer and return the resulting scene graph
470trpgReadNode *trpgSceneGraphParser::ParseScene(trpgReadBuffer &buf,GroupMap &inGmap)
471{
472    gmap = &inGmap;
473    trpgTileHeader *data = tileHead.GetData();
474    data->Reset();
475
476    // Always put a group up top, since there might be more than
477    //  one node at the top level in the file.
478    top = currTop = new trpgReadGroup();
479
480    // All the setup for tokens is handled in the constructor
481    // Just call parse
482    if (!Parse(buf)) {
483        // Failed to parse correctly.  Give up.
484        delete top;
485        return NULL;
486    }
487
488    return top;
489}
490
491// Start Children
492// This is called when the parser hits a push.
493// We'll want to make the node it's handing us the "top" node
494bool trpgSceneGraphParser::StartChildren(void *in_node)
495{
496    trpgReadNode *node = (trpgReadNode *)in_node;
497
498    if (!node || !node->isGroupType()) {
499        // Looks like there's a push in the wrong place
500        // Make the current "top" NULL.
501        // This will drop all node until we pop back above
502        currTop = NULL;
503    } else {
504        // This node is our new "top"
505        currTop = node;
506    }
507
508    return true;
509}
510
511/* This is called whent he parser hits a pop.
512   We'll want to look on the parent list (in trpgSceneParser)
513    for the parent above the current one.
514   If there isn't one, we'll just stick things in our top group.
515   */
516bool trpgSceneGraphParser::EndChildren(void* /*in_node*/)
517{
518    // We don't need it here, but this is the node we just
519    //  finished putting children under.  If you need to close
520    //  it out in some way, do that here
521    //trpgReadNode *node = (trpgReadNode *)in_node;
522
523    // Get the parent above the current one
524    int pos = parents.size()-2;
525    if (pos < 0)
526        // Nothing above the current one.  Fall back on our top group
527        currTop = top;
528    else
529        currTop = (trpgReadNode *)parents[pos];
530
531    return true;
532}
533
534// Return group map (for use by helpers)
535trpgSceneGraphParser::GroupMap *trpgSceneGraphParser::GetGroupMap()
536{
537    return gmap;
538}
539
540/*  ***********
541    Test functions
542    ***********
543    */
544
545// Test all the tiles in an archive
546bool trpgTestArchive(trpgr_Archive &archive)
547{
548    int numLod;
549    trpg2iPoint tileSize;
550    trpgSceneGraphParser parse;
551    trpgReadNode *scene;
552    trpgSceneGraphParser::GroupMap gmap;
553
554    if (!archive.isValid()) return false;
555
556    const trpgHeader *head = archive.GetHeader();
557    head->GetNumLods(numLod);
558
559    // Iterate over the lods
560    int nl,x,y;
561    trpgMemReadBuffer buf(archive.GetEndian());
562    trpg3dPoint ll,ur;
563    for (nl = 0;nl < numLod;nl++) {
564        head->GetLodSize(nl,tileSize);
565        // Iterate over the tiles within those
566        for (x = 0; x < tileSize.x; x++)
567            for (y = 0; y < tileSize.y; y++) {
568                archive.trpgGetTileMBR(x,y,nl,ll,ur);
569                if (archive.ReadTile(x,y,nl,buf)) {
570                    // Parse it
571                    scene = parse.ParseScene(buf,gmap);
572                    if (scene)
573                        delete scene;
574                }
575            }
576    }
577
578    return true;
579}
Note: See TracBrowser for help on using the browser.