1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SoBoundingBoxCache Inventor/caches/SoBoundingBoxCache.h
35   \brief The SoBoundingBoxCache class is used to cache bounding boxes.
36 
37   \ingroup caches
38 */
39 
40 // *************************************************************************
41 
42 #include <Inventor/caches/SoBoundingBoxCache.h>
43 #include <Inventor/elements/SoCacheElement.h>
44 #include <Inventor/errors/SoDebugError.h>
45 
46 #include "tidbitsp.h"
47 
48 // *************************************************************************
49 
50 class SoBoundingBoxCacheP {
51 public:
52   SbXfBox3f bbox;
53   SbBox3f localbbox;
54   SbVec3f centerpoint;
55   unsigned int centerset : 1;
56   unsigned int linesorpoints : 1;
57 };
58 
59 #define PRIVATE(p) ((p)->pimpl)
60 
61 // *************************************************************************
62 
63 /*!
64   Constructor with \a state being the current state.
65 */
SoBoundingBoxCache(SoState * state)66 SoBoundingBoxCache::SoBoundingBoxCache(SoState *state)
67   : SoCache(state)
68 {
69   PRIVATE(this) = new SoBoundingBoxCacheP;
70   PRIVATE(this)->centerset = 0;
71   PRIVATE(this)->linesorpoints = 0;
72 
73 #if COIN_DEBUG
74   if (coin_debug_caching_level() > 0) {
75     SoDebugError::postInfo("SoBoundingBoxCache::SoBoundingBoxCache",
76                            "Cache created: %p", this);
77 
78   }
79 #endif // debug
80 }
81 
82 /*!
83   Destructor.
84 */
~SoBoundingBoxCache()85 SoBoundingBoxCache::~SoBoundingBoxCache()
86 {
87 #if COIN_DEBUG
88   if (coin_debug_caching_level() > 0) {
89     SoDebugError::postInfo("SoBoundingBoxCache::~SoBoundingBoxCache",
90                            "Cache destructed: %p", this);
91   }
92 #endif // debug
93 
94   delete PRIVATE(this);
95 }
96 
97 /*!
98   Sets the data for this cache. \a boundingBox is the node's bounding
99   box, \a centerSet and \a centerPoints specifies the center of the
100   geometry inside \a boundingBox.
101 */
102 void
set(const SbXfBox3f & boundingbox,SbBool centerset,const SbVec3f & centerpoint)103 SoBoundingBoxCache::set(const SbXfBox3f & boundingbox,
104                         SbBool centerset,
105                         const SbVec3f & centerpoint)
106 {
107   PRIVATE(this)->bbox = boundingbox;
108   PRIVATE(this)->localbbox = boundingbox.project();
109   PRIVATE(this)->centerset = centerset ? 1 : 0;
110   if (centerset) { PRIVATE(this)->centerpoint = centerpoint; }
111 }
112 
113 /*!
114   Returns the bounding box for this cache.
115 */
116 const SbXfBox3f &
getBox(void) const117 SoBoundingBoxCache::getBox(void) const
118 {
119   return PRIVATE(this)->bbox;
120 }
121 
122 /*!
123   Returns the projected bounding box for this cache.
124 */
125 const SbBox3f &
getProjectedBox(void) const126 SoBoundingBoxCache::getProjectedBox(void) const
127 {
128   return PRIVATE(this)->localbbox;
129 }
130 
131 /*!
132   Returns whether the center of the bounding box was set in the
133   SoBoundingBoxCache::set() method.
134 
135   \sa SoBoundingBoxCache::getCenter()
136 */
137 SbBool
isCenterSet(void) const138 SoBoundingBoxCache::isCenterSet(void) const
139 {
140   return PRIVATE(this)->centerset == 1;
141 }
142 
143 /*!
144   Returns the center of the bounding box. Should only be used if
145   SoBoundingBoxCache::isCenterSet() returns \c TRUE.
146 */
147 const SbVec3f &
getCenter(void) const148 SoBoundingBoxCache::getCenter(void) const
149 {
150   return PRIVATE(this)->centerpoint;
151 }
152 
153 /*!
154   Sets the flag returned from SoBoundingBoxCache::hasLinesOrPoints()
155   to \c TRUE for all open bounding box caches.
156 
157   The reason bounding box caches keep a lines-or-points flag is to
158   make it known to client code if the shape(s) they contain have any
159   of these primitives -- or are rendered with these primitives. The
160   reason this is important to know for the client code is because it
161   might need to add an "epsilon" slack value to the calculated
162   bounding box to account for smoothing / anti-aliasing effects in the
163   renderer, so lines and points graphics is not accidently clipped by
164   near and far clipping planes, for instance.
165 
166   This method is a static method on the class. It will upon invocation
167   scan through the state stack and set the flag for all open
168   SoBoundingBoxCache elements. It has been made to work like this so
169   it can easily be invoked on all current bounding box cache instances
170   from the SoShape-type nodes using lines and / or point primitives.
171 
172   \sa hasLinesOrPoints()
173 */
174 void
setHasLinesOrPoints(SoState * state)175 SoBoundingBoxCache::setHasLinesOrPoints(SoState * state)
176 {
177   SoCacheElement * elem = static_cast<SoCacheElement *>(
178     state->getElementNoPush(SoCacheElement::getClassStackIndex())
179     );
180 
181   while (elem) {
182     SoBoundingBoxCache * cache = static_cast<SoBoundingBoxCache *>(elem->getCache());
183     if (cache) { PRIVATE(cache)->linesorpoints = TRUE; }
184     elem = elem->getNextCacheElement();
185   }
186 }
187 
188 /*!
189   Return \c TRUE if the hasLinesOrPoints flag has been set.
190 
191   \sa setHasLinesOrPoints()
192 */
193 SbBool
hasLinesOrPoints(void) const194 SoBoundingBoxCache::hasLinesOrPoints(void) const
195 {
196   return PRIVATE(this)->linesorpoints == 1;
197 }
198 
199 #undef PRIVATE
200