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 SoGLModelMatrixElement Inventor/elements/SoGLModelMatrixElement.h
35 \brief The SoGLModelMatrixElement class is yet to be documented.
36
37 \ingroup elements
38
39 FIXME: write doc.
40 */
41
42 #include <Inventor/elements/SoGLModelMatrixElement.h>
43 #include <Inventor/elements/SoGLViewingMatrixElement.h>
44 #include <Inventor/SbRotation.h>
45 #include <Inventor/SbVec3f.h>
46
47 #ifdef HAVE_CONFIG_H
48 #include <config.h>
49 #endif // HAVE_CONFIG_H
50
51 #include <Inventor/system/gl.h>
52 #include <Inventor/C/tidbits.h>
53
54 #if COIN_DEBUG
55 #include <Inventor/errors/SoDebugError.h>
56 #endif // COIN_DEBUG
57
58 SO_ELEMENT_SOURCE(SoGLModelMatrixElement);
59
60 static int COIN_HANDLE_STACK_OVERFLOW = 0;
61
62 /*!
63 This static method initializes static data for the
64 SoGLModelMatrixElement class.
65 */
66
67 void
initClass(void)68 SoGLModelMatrixElement::initClass(void)
69 {
70 SO_ELEMENT_INIT_CLASS(SoGLModelMatrixElement, inherited);
71
72 const char * env = coin_getenv("COIN_HANDLE_STACK_OVERFLOW");
73 if (env && atoi(env) > 0) COIN_HANDLE_STACK_OVERFLOW = 1;
74 else COIN_HANDLE_STACK_OVERFLOW = 0;
75 }
76
77 /*!
78 The destructor.
79 */
80
~SoGLModelMatrixElement(void)81 SoGLModelMatrixElement::~SoGLModelMatrixElement(void)
82 {
83 }
84
85 //! FIXME: write doc.
86
87 void
init(SoState * stateptr)88 SoGLModelMatrixElement::init(SoState * stateptr)
89 {
90 this->state = stateptr;
91 this->viewEltNodeId = 0;
92 this->stackoverflow = FALSE;
93 inherited::init(stateptr);
94 }
95
96 //! FIXME: write doc.
97
98 void
push(SoState * stateptr)99 SoGLModelMatrixElement::push(SoState * stateptr)
100 {
101 SoGLModelMatrixElement * prev = (SoGLModelMatrixElement*)
102 this->getNextInStack();
103
104 // the stackoverflow test makes it possible to have scene graphs
105 // with virtually unlimited depth and with transformations inside
106 // each separator. If a GL_STACK_OVERFLOW error is encountered,
107 // a glPopMatrix() will not be called in the pop() method, but
108 // the GL matrix will be read from SoModelMatrixElement instead.
109 // pederb, 2000-12-20
110 this->stackoverflow = prev->stackoverflow;
111 this->state = prev->state;
112 this->viewEltNodeId = prev->viewEltNodeId;
113
114 if (COIN_HANDLE_STACK_OVERFLOW > 0) {
115 if (!this->stackoverflow) {
116 glPushMatrix();
117 if (glGetError() == GL_STACK_OVERFLOW) {
118 this->stackoverflow = TRUE;
119 }
120 }
121 }
122 else {
123 glPushMatrix();
124 }
125 inherited::push(stateptr);
126 }
127
128 //! FIXME: write doc.
129
130 void
pop(SoState * stateptr,const SoElement * prevTopElement)131 SoGLModelMatrixElement::pop(SoState * stateptr,
132 const SoElement * prevTopElement)
133 {
134 inherited::pop(stateptr, prevTopElement);
135
136 SoGLModelMatrixElement * prev = (SoGLModelMatrixElement*)
137 prevTopElement;
138
139 if (prev->stackoverflow) {
140 SbMatrix mat = SoGLViewingMatrixElement::getResetMatrix(this->state);
141 mat.multLeft(this->modelMatrix);
142 glLoadMatrixf(mat[0]);
143 }
144 else {
145 glPopMatrix();
146 }
147 }
148
149 //! FIXME: write doc.
150
151 void
makeEltIdentity()152 SoGLModelMatrixElement::makeEltIdentity()
153 {
154 SbMatrix mat = SoGLViewingMatrixElement::getResetMatrix(this->state);
155 glLoadMatrixf(mat[0]);
156 inherited::makeEltIdentity();
157 }
158
159 //! FIXME: write doc.
160
161 void
setElt(const SbMatrix & matrix)162 SoGLModelMatrixElement::setElt(const SbMatrix & matrix)
163 {
164 SbMatrix mat = SoGLViewingMatrixElement::getResetMatrix(this->state);
165 mat.multLeft(matrix);
166 glLoadMatrixf(mat[0]);
167 inherited::setElt(matrix);
168 }
169
170 //! FIXME: write doc.
171
172 void
multElt(const SbMatrix & matrix)173 SoGLModelMatrixElement::multElt(const SbMatrix &matrix)
174 {
175 glMultMatrixf(matrix[0]);
176 inherited::multElt(matrix);
177 }
178
179 //! FIXME: write doc.
180
181 void
translateEltBy(const SbVec3f & translation)182 SoGLModelMatrixElement::translateEltBy(const SbVec3f &translation)
183 {
184 glTranslatef(translation[0], translation[1], translation[2]);
185 inherited::translateEltBy(translation);
186 }
187
188 //! FIXME: write doc.
189
190 void
rotateEltBy(const SbRotation & rotation)191 SoGLModelMatrixElement::rotateEltBy(const SbRotation &rotation)
192 {
193 SbVec3f axis;
194 float angle;
195 rotation.getValue(axis, angle);
196 glRotatef(angle*180.0f/float(M_PI), axis[0], axis[1], axis[2]);
197 inherited::rotateEltBy(rotation);
198 }
199
200 //! FIXME: write doc.
201
202 void
scaleEltBy(const SbVec3f & scaleFactor)203 SoGLModelMatrixElement::scaleEltBy(const SbVec3f &scaleFactor)
204 {
205 glScalef(scaleFactor[0], scaleFactor[1], scaleFactor[2]);
206 inherited::scaleEltBy(scaleFactor);
207 }
208
209 //! FIXME: write doc.
210
211 SbMatrix
pushMatrixElt()212 SoGLModelMatrixElement::pushMatrixElt()
213 {
214 this->viewEltNodeId = SoGLViewingMatrixElement::getNodeId(this->state);
215 glPushMatrix();
216 return inherited::pushMatrixElt();
217 }
218
219 //! FIXME: write doc.
220
221 void
popMatrixElt(const SbMatrix & matrix)222 SoGLModelMatrixElement::popMatrixElt(const SbMatrix &matrix)
223 {
224 glPopMatrix();
225 if (this->viewEltNodeId != SoGLViewingMatrixElement::getNodeId(this->state)) {
226 this->setElt(matrix);
227 }
228 inherited::popMatrixElt(matrix);
229 }
230