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 // Note: the class documentation for the basic primitive shapes
34 // SoSphere, SoCylinder, SoCone and SoCube have many common, or at
35 // least close to common, paragraphs. If you make any changes, check
36 // those other shapes too, to see if your updates / fixes should be
37 // migrated. <mortene@sim.no>.
38 /*!
39 \class SoCube SoCube.h Inventor/nodes/SoCube.h
40 \brief The SoCube class is for rendering cubes.
41
42 \ingroup nodes
43
44 Insert a cube shape into the scenegraph. The cube is rendered with
45 the current material, texture and drawstyle settings (if any,
46 otherwise the default settings are used).
47
48 (Strictly speaking, as you can have different width, height and
49 depth values for the "cube", instances of this class actually
50 represents \e boxes.)
51
52 The SoCube node class is provided as a convenient abstraction for
53 the application programmer to use "complex" shapes of this type
54 without having to do the calculation and book-keeping of the polygon
55 sides and other low-level programming herself.
56
57 <b>FILE FORMAT/DEFAULTS:</b>
58 \code
59 Cube {
60 width 2
61 height 2
62 depth 2
63 }
64 \endcode
65
66 \sa SoCylinder, SoSphere, SoCone
67 */
68
69 #include <Inventor/nodes/SoCube.h>
70 #include "coindefs.h"
71
72 #include <Inventor/SbPlane.h>
73 #include <Inventor/SoPickedPoint.h>
74 #include <Inventor/actions/SoGLRenderAction.h>
75 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
76 #include <Inventor/actions/SoRayPickAction.h>
77 #include <Inventor/bundles/SoMaterialBundle.h>
78 #include <Inventor/details/SoCubeDetail.h>
79 #include <Inventor/elements/SoDrawStyleElement.h>
80 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
81 #include <Inventor/elements/SoMaterialBindingElement.h>
82 #include <Inventor/elements/SoMultiTextureCoordinateElement.h>
83 #include <Inventor/misc/SoState.h>
84
85 #include "nodes/SoSubNodeP.h"
86 #include "rendering/SoGL.h"
87 #include "misc/SoGenerate.h"
88 #include "misc/SoPick.h"
89
90 /*!
91 \var SoSFFloat SoCube::width
92 X axis dimension of cube, defaults to 2.0.
93 */
94 /*!
95 \var SoSFFloat SoCube::height
96 Y axis dimension of cube, defaults to 2.0.
97 */
98 /*!
99 \var SoSFFloat SoCube::depth
100 Z axis dimension of cube, defaults to 2.0.
101 */
102
103
104 // *************************************************************************
105
106 SO_NODE_SOURCE(SoCube);
107
108 /*!
109 Constructor.
110 */
SoCube(void)111 SoCube::SoCube(void)
112 {
113 SO_NODE_INTERNAL_CONSTRUCTOR(SoCube);
114
115 SO_NODE_ADD_FIELD(width, (2.0f));
116 SO_NODE_ADD_FIELD(height, (2.0f));
117 SO_NODE_ADD_FIELD(depth, (2.0f));
118 }
119
120 /*!
121 Destructor.
122 */
~SoCube()123 SoCube::~SoCube()
124 {
125 }
126
127 // Doc in parent.
128 void
initClass(void)129 SoCube::initClass(void)
130 {
131 SO_NODE_INTERNAL_INIT_CLASS(SoCube, SO_FROM_INVENTOR_1|SoNode::VRML1);
132 }
133
134 // Doc in parent.
135 void
GLRender(SoGLRenderAction * action)136 SoCube::GLRender(SoGLRenderAction * action)
137 {
138 if (!this->shouldGLRender(action)) return;
139 SoState * state = action->getState();
140
141 SoMaterialBindingElement::Binding binding =
142 SoMaterialBindingElement::get(state);
143
144 SbBool materialPerPart =
145 (binding == SoMaterialBindingElement::PER_PART ||
146 binding == SoMaterialBindingElement::PER_PART_INDEXED ||
147 binding == SoMaterialBindingElement::PER_FACE ||
148 binding == SoMaterialBindingElement::PER_FACE_INDEXED);
149
150 SbBool doTextures = FALSE;
151 SbBool do3DTextures = FALSE;
152 if (SoGLMultiTextureEnabledElement::get(state, 0)) {
153 doTextures = TRUE;
154 if (SoGLMultiTextureEnabledElement::getMode(state,0) ==
155 SoMultiTextureEnabledElement::TEXTURE3D) {
156 do3DTextures = TRUE;
157 }
158 }
159
160 SoMaterialBundle mb(action);
161 mb.sendFirst();
162
163 SbBool sendNormals = !mb.isColorOnly() ||
164 (SoMultiTextureCoordinateElement::getType(state) == SoMultiTextureCoordinateElement::FUNCTION);
165
166 unsigned int flags = 0;
167 if (materialPerPart) flags |= SOGL_MATERIAL_PER_PART;
168 if (doTextures) {
169 switch (SoMultiTextureEnabledElement::getMode(state, 0)) {
170 default:
171 flags |= SOGL_NEED_TEXCOORDS;
172 break;
173 case SoMultiTextureEnabledElement::CUBEMAP:
174 flags |= SOGL_NEED_3DTEXCOORDS;
175 break;
176 }
177 }
178 else if (do3DTextures) flags |= SOGL_NEED_3DTEXCOORDS;
179 if (sendNormals) flags |= SOGL_NEED_NORMALS;
180
181 sogl_render_cube(width.getValue(),
182 height.getValue(),
183 depth.getValue(),
184 &mb,
185 flags, state);
186 }
187
188 // Doc in parent.
189 void
generatePrimitives(SoAction * action)190 SoCube::generatePrimitives(SoAction * action)
191 {
192 SoMaterialBindingElement::Binding binding =
193 SoMaterialBindingElement::get(action->getState());
194
195 SbBool materialPerPart =
196 (binding == SoMaterialBindingElement::PER_PART ||
197 binding == SoMaterialBindingElement::PER_PART_INDEXED ||
198 binding == SoMaterialBindingElement::PER_FACE ||
199 binding == SoMaterialBindingElement::PER_FACE_INDEXED);
200
201 unsigned int flags = 0;
202 if (materialPerPart) flags |= SOGEN_MATERIAL_PER_PART;
203 sogen_generate_cube(this->width.getValue(),
204 this->height.getValue(),
205 this->depth.getValue(),
206 flags,
207 this,
208 action);
209 }
210
211 // Doc in parent.
212 void
computeBBox(SoAction * COIN_UNUSED_ARG (action),SbBox3f & box,SbVec3f & center)213 SoCube::computeBBox(SoAction * COIN_UNUSED_ARG(action), SbBox3f & box, SbVec3f & center)
214 {
215 center.setValue(0.0f, 0.0f, 0.0f);
216 float w, h, d;
217 this->getHalfSize(w, h, d);
218
219 // Allow negative values.
220 if (w < 0.0f) w = -w;
221 if (h < 0.0f) h = -h;
222 if (d < 0.0f) d = -d;
223
224 box.setBounds(-w, -h, -d, w, h, d);
225 }
226
227 // Doc in parent.
228 void
rayPick(SoRayPickAction * action)229 SoCube::rayPick(SoRayPickAction * action)
230 {
231 if (!shouldRayPick(action)) return;
232
233 SoMaterialBindingElement::Binding binding =
234 SoMaterialBindingElement::get(action->getState());
235
236 SbBool materialPerPart =
237 (binding == SoMaterialBindingElement::PER_PART ||
238 binding == SoMaterialBindingElement::PER_PART_INDEXED);
239
240 sopick_pick_cube(this->width.getValue(),
241 this->height.getValue(),
242 this->depth.getValue(),
243 materialPerPart ? SOPICK_MATERIAL_PER_PART : 0,
244 this, action);
245 }
246
247 // Convenience function for finding half the size of the box.
248 void
getHalfSize(float & w,float & h,float & d)249 SoCube::getHalfSize(float & w, float & h, float & d)
250 {
251 w = (this->width.isIgnored() ? 1.0f :
252 this->width.getValue() * 0.5f);
253 h = (this->height.isIgnored() ? 1.0f :
254 this->height.getValue() * 0.5f);
255 d = (this->depth.isIgnored() ? 1.0f :
256 this->depth.getValue() * 0.5f);
257 }
258
259 // Doc from parent.
260 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)261 SoCube::getPrimitiveCount(SoGetPrimitiveCountAction * action)
262 {
263 if (!this->shouldPrimitiveCount(action)) return;
264
265 action->addNumTriangles(12);
266 }
267