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 SoSphere SoSphere.h Inventor/nodes/SoSphere.h
40   \brief The SoSphere class is for rendering sphere shapes.
41 
42   \ingroup nodes
43 
44   Renders a sphere with the size given by the SoSphere::radius
45   field. The sphere is rendered with the current material, texture and
46   drawstyle settings (if any, otherwise the default settings are
47   used).
48 
49   The SoSphere node class is provided as a convenient abstraction for
50   the application programmer to use "complex" shapes of this type
51   without having to do the tessellation to polygons and other
52   low-level programming herself.
53 
54   A good trick for rendering ellipsoidal 3D shapes is to use an
55   SoSphere prefixed with an SoScale transformation to "flatten" it
56   along one or more of the principal axes. (Ie use for instance an
57   SoScale node with SoScale::scaleFactor equal to [1, 1, 0.1] to
58   flatten it along the Z direction.)
59 
60   A sphere is visualized by the underlying rendering system by first
61   tessellating the conceptual sphere into a set of polygons. To
62   control the trade-off between an as much as possible correct visual
63   appearance of the sphere versus fast rendering, use an SoComplexity
64   node to influence the number of polygons generated from the
65   tessellation process. (The higher the complexity value, the more
66   polygons will be generated, the more \e rounded the sphere will
67   look.) Set the SoComplexity::value field to what you believe would
68   be a good trade-off between correctness and speed for your
69   particular application.
70 
71   <b>FILE FORMAT/DEFAULTS:</b>
72   \code
73     Sphere {
74         radius 1
75     }
76   \endcode
77 
78   \sa SoCone, SoCylinder, SoCube
79 */
80 
81 #include <Inventor/nodes/SoSphere.h>
82 #include "coindefs.h"
83 
84 #include <Inventor/SbSphere.h>
85 #include <Inventor/SoPickedPoint.h>
86 #include <Inventor/actions/SoGLRenderAction.h>
87 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
88 #include <Inventor/actions/SoRayPickAction.h>
89 #include <Inventor/bundles/SoMaterialBundle.h>
90 #include <Inventor/elements/SoGLMultiTextureEnabledElement.h>
91 #include <Inventor/elements/SoMultiTextureCoordinateElement.h>
92 #include <Inventor/misc/SoState.h>
93 
94 #include "nodes/SoSubNodeP.h"
95 #include "rendering/SoGL.h"
96 #include "misc/SoGenerate.h"
97 #include "misc/SoPick.h"
98 
99 /*!
100   \var SoSFFloat SoSphere::radius
101 
102   Radius of sphere. Default value is 1.0.
103 */
104 
105 #define SPHERE_NUM_SLICES 30.0f
106 #define SPHERE_NUM_STACKS 30.0f
107 
108 // *************************************************************************
109 
110 SO_NODE_SOURCE(SoSphere);
111 
112 /*!
113   Constructor.
114 */
SoSphere(void)115 SoSphere::SoSphere(void)
116 {
117   SO_NODE_INTERNAL_CONSTRUCTOR(SoSphere);
118 
119   SO_NODE_ADD_FIELD(radius, (1.0f));
120 }
121 
122 /*!
123   Destructor.
124 */
~SoSphere()125 SoSphere::~SoSphere()
126 {
127 }
128 
129 // Documented in superclass.
130 void
initClass(void)131 SoSphere::initClass(void)
132 {
133   SO_NODE_INTERNAL_INIT_CLASS(SoSphere, SO_FROM_INVENTOR_1|SoNode::VRML1);
134 }
135 
136 // Documented in superclass.
137 void
GLRender(SoGLRenderAction * action)138 SoSphere::GLRender(SoGLRenderAction * action)
139 {
140   if (!this->shouldGLRender(action)) return;
141 
142   SoState * state = action->getState();
143 
144   SoMaterialBundle mb(action);
145   mb.sendFirst();
146 
147   SbBool doTextures = FALSE;
148   SbBool do3DTextures = FALSE;
149   if (SoGLMultiTextureEnabledElement::get(state, 0)) {
150     doTextures = TRUE;
151     if (SoGLMultiTextureEnabledElement::getMode(state,0) ==
152         SoMultiTextureEnabledElement::TEXTURE3D) {
153       do3DTextures = TRUE;
154     }
155   }
156 
157   SbBool sendNormals = !mb.isColorOnly() ||
158     (SoMultiTextureCoordinateElement::getType(state) == SoMultiTextureCoordinateElement::FUNCTION);
159 
160   float complexity = SbClamp(this->getComplexityValue(action), 0.0f, 1.0f);
161 
162   unsigned int flags = 0;
163   if (sendNormals) flags |= SOGL_NEED_NORMALS;
164   if (doTextures) flags |= SOGL_NEED_TEXCOORDS;
165   else if (do3DTextures) flags |= SOGL_NEED_3DTEXCOORDS;
166 
167   sogl_render_sphere(this->radius.getValue(),
168                      (int)(SPHERE_NUM_SLICES * complexity),
169                      (int)(SPHERE_NUM_STACKS * complexity),
170                      &mb,
171                      flags, state);
172 }
173 
174 // Documented in superclass.
175 void
computeBBox(SoAction * COIN_UNUSED_ARG (action),SbBox3f & box,SbVec3f & center)176 SoSphere::computeBBox(SoAction * COIN_UNUSED_ARG(action), SbBox3f & box, SbVec3f & center)
177 {
178   float r = this->radius.getValue();
179 
180   // Allow negative values.
181   if (r < 0.0f) r = -r;
182 
183   box.setBounds(SbVec3f(-r, -r, -r), SbVec3f(r, r, r));
184   center.setValue(0.0f, 0.0f, 0.0f);
185 }
186 
187 // Documented in superclass.
188 void
rayPick(SoRayPickAction * action)189 SoSphere::rayPick(SoRayPickAction *action)
190 {
191   if (!shouldRayPick(action)) return;
192 
193   sopick_pick_sphere(this->radius.getValue(),
194                      action);
195 }
196 
197 // Documented in superclass.
198 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)199 SoSphere::getPrimitiveCount(SoGetPrimitiveCountAction * action)
200 {
201   if (!this->shouldPrimitiveCount(action)) return;
202 
203   float complexity = this->getComplexityValue(action);
204   action->addNumTriangles((int)(complexity*2.0f*SPHERE_NUM_SLICES*(SPHERE_NUM_STACKS-1)));
205 }
206 
207 // Documented in superclass.
208 void
generatePrimitives(SoAction * action)209 SoSphere::generatePrimitives(SoAction * action)
210 {
211   float complexity = this->getComplexityValue(action);
212 
213   sogen_generate_sphere(this->radius.getValue(),
214                         (int)(SPHERE_NUM_SLICES * complexity),
215                         (int)(SPHERE_NUM_STACKS * complexity),
216                         this,
217                         action);
218 }
219 
220 #undef SPHERE_NUM_SLICES
221 #undef SPHERE_NUM_STACKS
222