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 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif // HAVE_CONFIG_H
36 
37 #ifdef HAVE_VRML97
38 
39 /*!
40   \class SoVRMLGeometry SoVRMLGeometry.h Inventor/VRMLnodes/SoVRMLGeometry.h
41   \brief The SoVRMLGeometry class is a superclass for VRML shapes.
42 */
43 
44 #include <Inventor/VRMLnodes/SoVRMLGeometry.h>
45 
46 #include <Inventor/VRMLnodes/SoVRMLParent.h>
47 #include <Inventor/VRMLnodes/SoVRMLMacros.h>
48 #include <Inventor/elements/SoGLShapeHintsElement.h>
49 #include <Inventor/elements/SoOverrideElement.h>
50 #include <Inventor/fields/SoSFNode.h>
51 #include <Inventor/misc/SoChildList.h>
52 #include <Inventor/actions/SoSearchAction.h>
53 #ifdef HAVE_THREADS
54 #include <Inventor/threads/SbMutex.h>
55 #endif // HAVE_THREADS
56 
57 #include "nodes/SoSubNodeP.h"
58 
59 // *************************************************************************
60 
61 class SoVRMLGeometryP {
62 public:
63   SoChildList * childlist;
64   SbBool childlistvalid;
65 
66 #ifdef COIN_THREADSAFE
67   SbMutex childlistmutex;
lockChildList(void)68   void lockChildList(void) { this->childlistmutex.lock(); }
unlockChildList(void)69   void unlockChildList(void) { this->childlistmutex.unlock(); }
70 #else // !COIN_THREADSAFE
lockChildList(void)71   void lockChildList(void) { }
unlockChildList(void)72   void unlockChildList(void) { }
73 #endif // !COIN_THREADSAFE
74 };
75 
76 #define PRIVATE(thisp) ((thisp)->pimpl)
77 
78 // *************************************************************************
79 
80 SO_NODE_ABSTRACT_SOURCE(SoVRMLGeometry);
81 
82 // *************************************************************************
83 
84 // Doc in parent
85 void
initClass(void)86 SoVRMLGeometry::initClass(void)
87 {
88   SO_NODE_INTERNAL_INIT_ABSTRACT_CLASS(SoVRMLGeometry, SO_VRML97_NODE_TYPE);
89 }
90 
91 /*!
92   Constructor.
93 */
SoVRMLGeometry(void)94 SoVRMLGeometry::SoVRMLGeometry(void)
95 {
96   PRIVATE(this) = new SoVRMLGeometryP;
97   // supply a NULL-pointer as parent, since notifications will be
98   // handled by the fields that actually contain the node(s)
99   PRIVATE(this)->childlist = new SoChildList(NULL);
100   PRIVATE(this)->childlistvalid = FALSE;
101   SO_VRMLNODE_INTERNAL_CONSTRUCTOR(SoVRMLGeometry);
102 }
103 
104 /*!
105   Destructor.
106 */
~SoVRMLGeometry()107 SoVRMLGeometry::~SoVRMLGeometry()
108 {
109   delete PRIVATE(this)->childlist;
110   delete PRIVATE(this);
111 }
112 
113 // Doc in parent
114 SbBool
shouldGLRender(SoGLRenderAction * action)115 SoVRMLGeometry::shouldGLRender(SoGLRenderAction * action)
116 {
117   return inherited::shouldGLRender(action);
118 }
119 
120 /*!
121   Convenience method that updates the shape hints element.
122 */
123 void
setupShapeHints(SoState * state,const SbBool ccw,const SbBool solid)124 SoVRMLGeometry::setupShapeHints(SoState * state, const SbBool ccw, const SbBool solid)
125 {
126   if (!(SoOverrideElement::getFlags(state) & SoOverrideElement::SHAPE_HINTS)) {
127     SoShapeHintsElement::set(state, this,
128                              ccw ? SoShapeHintsElement::COUNTERCLOCKWISE : SoShapeHintsElement::CLOCKWISE,
129                              solid ? SoShapeHintsElement::SOLID : SoShapeHintsElement::UNKNOWN_SHAPE_TYPE,
130                              SoShapeHintsElement::FACE_TYPE_AS_IS);
131   }
132 }
133 
134 // Doc in parent
135 SoChildList *
getChildren(void) const136 SoVRMLGeometry::getChildren(void) const
137 {
138   if (!PRIVATE(this)->childlistvalid) {
139     // this is not 100% thread safe. The assumption is that no nodes
140     // will be added or removed while a scene graph is being
141     // traversed. For Coin, this is an ok assumption.
142     PRIVATE(this)->lockChildList();
143     // test again after we've locked
144     if (!PRIVATE(this)->childlistvalid) {
145       SoVRMLGeometry * thisp = (SoVRMLGeometry*) this;
146       SoVRMLParent::updateChildList(thisp, *(PRIVATE(thisp)->childlist));
147       PRIVATE(thisp)->childlistvalid = TRUE;
148     }
149     PRIVATE(this)->unlockChildList();
150   }
151   return PRIVATE(this)->childlist;
152 }
153 
154 // Doc in parent
155 void
search(SoSearchAction * action)156 SoVRMLGeometry::search(SoSearchAction * action)
157 {
158   SoNode::search(action);
159   if (action->isFound() || this->getChildren() == NULL) return;
160 
161   int numindices;
162   const int * indices;
163   if (action->getPathCode(numindices, indices) == SoAction::IN_PATH) {
164     this->getChildren()->traverseInPath(action, numindices, indices);
165   }
166   else {
167     this->getChildren()->traverse(action); // traverse all children
168   }
169 }
170 
171 // Doc in parent
172 void
notify(SoNotList * list)173 SoVRMLGeometry::notify(SoNotList * list)
174 {
175   SoField * f = list->getLastField();
176   if (f && f->getTypeId() == SoSFNode::getClassTypeId()) {
177     PRIVATE(this)->childlistvalid = FALSE;
178   }
179   inherited::notify(list);
180 }
181 
182 // Doc in parent
183 void
copyContents(const SoFieldContainer * from,SbBool copyConn)184 SoVRMLGeometry::copyContents(const SoFieldContainer * from,
185                              SbBool copyConn)
186 {
187   inherited::copyContents(from, copyConn);
188   PRIVATE(this)->childlistvalid = FALSE;
189   PRIVATE(this)->childlist->truncate(0);
190 }
191 
192 #undef PRIVATE
193 
194 #endif // HAVE_VRML97
195