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