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 SoUnits SoUnits.h Inventor/nodes/SoUnits.h
35 \brief The SoUnits class is a node for setting unit types.
36
37 \ingroup nodes
38
39 Even though Coin doesn't care what units you are using in your scene
40 graph \e per \e se, there's an advantage to using SoUnits nodes: you
41 have a way to split your scene graph into different "conceptual"
42 parts.
43
44 When encountering SoUnit nodes, the traversal actions methods makes
45 sure the following geometry is scaled accordingly.
46
47 <b>FILE FORMAT/DEFAULTS:</b>
48 \code
49 Units {
50 units METERS
51 }
52 \endcode
53 */
54
55 // *************************************************************************
56
57 #include <Inventor/nodes/SoUnits.h>
58
59 #include <Inventor/actions/SoGetBoundingBoxAction.h>
60 #include <Inventor/actions/SoGLRenderAction.h>
61 #include <Inventor/actions/SoPickAction.h>
62 #include <Inventor/actions/SoCallbackAction.h>
63 #include <Inventor/actions/SoGetMatrixAction.h>
64 #include <Inventor/actions/SoGetPrimitiveCountAction.h>
65
66 #include <Inventor/elements/SoModelMatrixElement.h>
67 #include <Inventor/elements/SoUnitsElement.h>
68
69 #include "nodes/SoSubNodeP.h"
70
71 // *************************************************************************
72
73 /*!
74 \enum SoUnits::Units
75
76 Enumerates the available unit settings.
77 */
78
79
80 /*!
81 \var SoSFEnum SoUnits::units
82
83 The units which will be used for nodes following this node in the
84 traversal (until the next SoUnit node, if any). Default value of the
85 field is SoUnits::METERS.
86 */
87
88
89 // *************************************************************************
90
91 static const float factors[] = {
92 1.0f, // METERS
93 0.01f, // CENTIMETERS
94 0.001f, // MILLIMETERS
95 0.000001f, // MICROMETERS
96 0.000001f, // MICRONS
97 0.000000001f, // NANOMETERS
98 0.0000000001f, // ANGSTROMS
99 1000.0f, // KILOMETERS
100 0.3048f, // FEET
101 0.0254f, // INCHES
102 3.52777737e-4f, // POINTS
103 0.9144f, // YARDS
104 1609.3f, // MILES
105 1852.0f, // NAUTICAL
106 };
107
108 // *************************************************************************
109
110 SO_NODE_SOURCE(SoUnits);
111
112 /*!
113 Constructor.
114 */
SoUnits(void)115 SoUnits::SoUnits(void)
116 {
117 SO_NODE_INTERNAL_CONSTRUCTOR(SoUnits);
118
119 SO_NODE_ADD_FIELD(units, (SoUnits::METERS));
120
121 SO_NODE_DEFINE_ENUM_VALUE(Units, METERS);
122 SO_NODE_DEFINE_ENUM_VALUE(Units, CENTIMETERS);
123 SO_NODE_DEFINE_ENUM_VALUE(Units, MILLIMETERS);
124 SO_NODE_DEFINE_ENUM_VALUE(Units, MICROMETERS);
125 SO_NODE_DEFINE_ENUM_VALUE(Units, MICRONS);
126 SO_NODE_DEFINE_ENUM_VALUE(Units, NANOMETERS);
127 SO_NODE_DEFINE_ENUM_VALUE(Units, ANGSTROMS);
128 SO_NODE_DEFINE_ENUM_VALUE(Units, KILOMETERS);
129 SO_NODE_DEFINE_ENUM_VALUE(Units, FEET);
130 SO_NODE_DEFINE_ENUM_VALUE(Units, INCHES);
131 SO_NODE_DEFINE_ENUM_VALUE(Units, POINTS);
132 SO_NODE_DEFINE_ENUM_VALUE(Units, YARDS);
133 SO_NODE_DEFINE_ENUM_VALUE(Units, MILES);
134 SO_NODE_DEFINE_ENUM_VALUE(Units, NAUTICAL_MILES);
135 SO_NODE_SET_SF_ENUM_TYPE(units, Units);
136 }
137
138 /*!
139 Destructor.
140 */
~SoUnits()141 SoUnits::~SoUnits()
142 {
143 }
144
145 // Doc from superclass.
146 void
initClass(void)147 SoUnits::initClass(void)
148 {
149 SO_NODE_INTERNAL_INIT_CLASS(SoUnits, SO_FROM_INVENTOR_1);
150
151 SO_ENABLE(SoGetBoundingBoxAction, SoUnitsElement);
152 SO_ENABLE(SoGetMatrixAction, SoUnitsElement);
153 SO_ENABLE(SoGLRenderAction, SoUnitsElement);
154 SO_ENABLE(SoPickAction, SoUnitsElement);
155 SO_ENABLE(SoCallbackAction, SoUnitsElement);
156 SO_ENABLE(SoGetPrimitiveCountAction, SoUnitsElement);
157 }
158
159 // Doc from superclass.
160 void
getBoundingBox(SoGetBoundingBoxAction * action)161 SoUnits::getBoundingBox(SoGetBoundingBoxAction * action)
162 {
163 SoUnits::doAction((SoAction*)action);
164 }
165
166 // Doc from superclass.
167 void
GLRender(SoGLRenderAction * action)168 SoUnits::GLRender(SoGLRenderAction * action)
169 {
170 SoUnits::doAction((SoAction*)action);
171 }
172
173 // Doc from superclass.
174 void
doAction(SoAction * action)175 SoUnits::doAction(SoAction * action)
176 {
177 if (this->units.isIgnored()) return;
178 SoState * state = action->getState();
179
180 SoUnitsElement::Units currentunit = SoUnitsElement::get(state);
181
182 if (currentunit != (SoUnitsElement::Units)units.getValue()) {
183 SoUnitsElement::set(state,
184 (SoUnitsElement::Units)units.getValue());
185
186 float scale = factors[units.getValue()] / factors[currentunit];
187 SoModelMatrixElement::scaleBy(state, this,
188 SbVec3f(scale, scale, scale));
189 }
190 }
191
192 // Doc from superclass.
193 void
callback(SoCallbackAction * action)194 SoUnits::callback(SoCallbackAction * action)
195 {
196 SoUnits::doAction((SoAction *)action);
197 }
198
199 // Doc from superclass.
200 void
getMatrix(SoGetMatrixAction * action)201 SoUnits::getMatrix(SoGetMatrixAction * action)
202 {
203 if (this->units.isIgnored()) return;
204
205 SoState * state = action->getState();
206 SoUnitsElement::Units currentunit = SoUnitsElement::get(state);
207 if (currentunit != (SoUnitsElement::Units) this->units.getValue()) {
208 SoUnitsElement::set(state,
209 (SoUnitsElement::Units)units.getValue());
210
211 float scale = factors[(int)this->units.getValue()] / factors[(int) currentunit];
212 float inv = 1.0f / scale;
213
214 SbMatrix m;
215 m.setScale(SbVec3f(scale, scale, scale));
216 action->getMatrix().multLeft(m);
217 m.setScale(SbVec3f(inv, inv, inv));
218 action->getInverse().multRight(m);
219 }
220 }
221
222 // Doc from superclass.
223 void
pick(SoPickAction * action)224 SoUnits::pick(SoPickAction * action)
225 {
226 SoUnits::doAction((SoAction *)action);
227 }
228
229 // Doc from superclass.
230 void
getPrimitiveCount(SoGetPrimitiveCountAction * action)231 SoUnits::getPrimitiveCount(SoGetPrimitiveCountAction * action)
232 {
233 SoUnits::doAction((SoAction *)action);
234 }
235