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