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 SoMaterialBinding SoMaterialBinding.h Inventor/nodes/SoMaterialBinding.h
35   \brief The SoMaterialBinding class is a node for setting up how materials are mapped to shapes.
36 
37   \ingroup nodes
38 
39   The material binding specified in nodes of this type decides how the
40   material values of SoMaterial nodes are mapped on the builtin
41   geometry shape nodes.
42 
43   The exact meaning of a binding depends on what particular shape type
44   a material or a set of materials are applied to.
45 
46   Here is a very simple usage example:
47 
48   \verbatim
49   #Inventor V2.1 ascii
50 
51   Separator {
52      Coordinate3 {
53         point [ 0 0 0, 1 0 0, 1 1 0 ]
54      }
55 
56      Material {
57         diffuseColor [ 1 0 0, 1 1 0, 0 0 1 ]
58      }
59 
60      MaterialBinding {
61         value PER_VERTEX_INDEXED
62      }
63 
64      IndexedFaceSet {
65         coordIndex [ 0, 1, 2, -1 ]
66         materialIndex [ 0, 1, 0 ]
67      }
68   }
69   \endverbatim
70 
71   With SoMaterialBinding::value set to \c PER_VERTEX_INDEXED above,
72   the material indices will be taken from the
73   SoIndexedFaceSet::materialIndex field when rendering.
74 
75   If SoMaterialBinding::value was set to \c PER_VERTEX_INDEXED as
76   above, and the SoIndexedFaceSet::materialIndex was undefined or
77   empty, indices would implicitly be taken from the
78   SoIndexedFaceSet::coordIndex field.
79 
80   If SoMaterialBinding::value is set to \c PER_VERTEX, colors will be
81   fetched in a monotonically increasing manner from the
82   SoMaterial::diffuseColor field, starting at index 0.
83 
84   <b>FILE FORMAT/DEFAULTS:</b>
85   \code
86     MaterialBinding {
87         value OVERALL
88     }
89   \endcode
90 
91   \sa SoMaterial
92 */
93 
94 // *************************************************************************
95 
96 #include <Inventor/actions/SoCallbackAction.h>
97 
98 #include <Inventor/actions/SoGLRenderAction.h>
99 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
100 #include <Inventor/actions/SoPickAction.h>
101 #include <Inventor/elements/SoMaterialBindingElement.h>
102 #include <Inventor/elements/SoOverrideElement.h>
103 
104 #include "nodes/SoSubNodeP.h"
105 
106 // *************************************************************************
107 
108 /*!
109   \enum SoMaterialBinding::Binding
110   Enumeration of available types of material binding.
111 */
112 /*!
113   \var SoMaterialBinding::Binding SoMaterialBinding::OVERALL
114   Apply the same material to the complete shape.
115 */
116 /*!
117   \var SoMaterialBinding::Binding SoMaterialBinding::PER_PART
118 
119   Get a new material from the pool of material values for each \e part
120   of the shape, where the definition of a \e part depends on the shape
121   type.
122 
123   Materials are fetched from index 0 and onwards, incrementing the
124   index into the material pool by 1 for each new part in the order
125   defined by the particular shape type.
126 
127   Important portability note: it was previously allowed with the SGI
128   Inventor library to supply too few colors versus the number of parts
129   of the subsequent shapes in the scene graph. Coloring would then
130   cycle through the available colors.
131 
132   Since SGI Open Inventor v2.1, this was disallowed, though -- enough
133   colors for all parts must be supplied, or behavior will be
134   unspecified (likely to cause a crash, in fact).  Note that the
135   &laquo;Inventor Mentor&raquo; book contains a description of the \e old, \e
136   invalid behavior in Chapter 5, section "Binding Nodes" (middle of
137   page 128 in the 10th printing).
138 */
139 /*!
140   \var SoMaterialBinding::Binding SoMaterialBinding::PER_PART_INDEXED
141 
142   Get a new material from the pool of material values for each \e part
143   of the shape, where the definition of a \e part depends on the shape
144   type.
145 
146   Materials are fetched by the index value settings of the shape.
147 */
148 /*!
149   \var SoMaterialBinding::Binding SoMaterialBinding::PER_FACE
150 
151   Get a new material from the pool of material values for each polygon
152   \e face of the shape.
153 
154   Materials are fetched from index 0 and onwards, incrementing the
155   index into the material pool by 1 for each new face of the shape
156   node.
157 
158   Note that individual faces after tessellation of complex shapes
159   (like SoCylinder nodes) are \e not considered to be separate
160   entities, and so this binding will be treated in the same manner as
161   SoMaterialBinding::PER_PART for those.
162 */
163 /*!
164   \var SoMaterialBinding::Binding SoMaterialBinding::PER_FACE_INDEXED
165 
166   Get a new material from the pool of material values for each polygon
167   \e face of the shape.
168 
169   Materials are fetched by the index value settings of the shape.
170 
171   Note that individual faces after tessellation of complex shapes
172   (like SoCylinder nodes) are \e not considered to be separate
173   entities, and so this binding will be treated in the same manner as
174   SoMaterialBinding::PER_PART_INDEXED for those.
175 */
176 /*!
177   \var SoMaterialBinding::Binding SoMaterialBinding::PER_VERTEX
178 
179   Get a new material from the pool of material values for each
180   polygon, line or point \e vertex of the shape.
181 
182   Materials are fetched from index 0 and onwards, incrementing the
183   index into the material pool by 1 for each new vertex of the shape
184   node.
185 */
186 /*!
187   \var SoMaterialBinding::Binding SoMaterialBinding::PER_VERTEX_INDEXED
188 
189   Get a new material from the pool of material values for each
190   polygon, line or point \e vertex of the shape.
191 
192   Materials are fetched by the index value settings of the shape.
193 */
194 
195 
196 
197 // Note: Inventor format files with SoMaterialBinding nodes with one
198 // of the two obsoleted values below will be updated upon import to
199 // contain the value for SoMaterialBinding::OVERALL. Ditto for calls
200 // to SoMaterialBinding::value.setValue([DEFAULT | NONE]).
201 //
202 // This happens automatically due to the way So[SM]FEnum fields are
203 // implemented.
204 //                 --mortene
205 
206 /*!
207   \var SoMaterialBinding::Binding SoMaterialBinding::DEFAULT
208   Obsolete. Don't use this value.
209 */
210 /*!
211   \var SoMaterialBinding::Binding SoMaterialBinding::NONE
212   Obsolete. Don't use this value.
213 */
214 
215 
216 /*!
217   \var SoSFEnum SoMaterialBinding::value
218 
219   The material binding to use for subsequent shape nodes in the scene
220   graph. The default binding is SoMaterialBinding::OVERALL.
221 */
222 
223 
224 // *************************************************************************
225 
226 SO_NODE_SOURCE(SoMaterialBinding);
227 
228 /*!
229   Constructor.
230 */
SoMaterialBinding(void)231 SoMaterialBinding::SoMaterialBinding(void)
232 {
233   SO_NODE_INTERNAL_CONSTRUCTOR(SoMaterialBinding);
234 
235   SO_NODE_ADD_FIELD(value, (OVERALL));
236 
237   SO_NODE_DEFINE_ENUM_VALUE(Binding, OVERALL);
238   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_PART);
239   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_PART_INDEXED);
240   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_FACE);
241   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_FACE_INDEXED);
242   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_VERTEX);
243   SO_NODE_DEFINE_ENUM_VALUE(Binding, PER_VERTEX_INDEXED);
244   SO_NODE_DEFINE_ENUM_VALUE(Binding, DEFAULT);
245   SO_NODE_DEFINE_ENUM_VALUE(Binding, NONE);
246 
247   SO_NODE_SET_SF_ENUM_TYPE(value, Binding);
248 }
249 
250 
251 /*!
252   Destructor.
253 */
~SoMaterialBinding()254 SoMaterialBinding::~SoMaterialBinding()
255 {
256 }
257 
258 // Doc from superclass.
259 void
initClass(void)260 SoMaterialBinding::initClass(void)
261 {
262   SO_NODE_INTERNAL_INIT_CLASS(SoMaterialBinding, SO_FROM_INVENTOR_1|SoNode::VRML1);
263 
264   SO_ENABLE(SoGLRenderAction, SoMaterialBindingElement);
265   SO_ENABLE(SoPickAction, SoMaterialBindingElement);
266   SO_ENABLE(SoCallbackAction, SoMaterialBindingElement);
267   SO_ENABLE(SoGetPrimitiveCountAction, SoMaterialBindingElement);
268 }
269 
270 // Doc from superclass.
271 void
GLRender(SoGLRenderAction * action)272 SoMaterialBinding::GLRender(SoGLRenderAction * action)
273 {
274   SoMaterialBinding::doAction(action);
275 }
276 
277 // Doc from superclass.
278 void
doAction(SoAction * action)279 SoMaterialBinding::doAction(SoAction * action)
280 {
281   if (!this->value.isIgnored()
282       && !SoOverrideElement::getMaterialBindingOverride(action->getState())) {
283     SoMaterialBindingElement::set(action->getState(),
284                                   (SoMaterialBindingElement::Binding)
285                                   this->value.getValue());
286     if (this->isOverride()) {
287       SoOverrideElement::setMaterialBindingOverride(action->getState(), this, TRUE);
288     }
289   }
290 }
291 
292 // Doc from superclass.
293 void
callback(SoCallbackAction * action)294 SoMaterialBinding::callback(SoCallbackAction * action)
295 {
296   SoMaterialBinding::doAction((SoAction *)action);
297 }
298 
299 // Doc from superclass.
300 void
pick(SoPickAction * action)301 SoMaterialBinding::pick(SoPickAction * action)
302 {
303   SoMaterialBinding::doAction(action);
304 }
305 
306 // Doc from superclass.
307 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)308 SoMaterialBinding::getPrimitiveCount(SoGetPrimitiveCountAction * action)
309 {
310   SoMaterialBinding::doAction(action);
311 }
312