1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
50 #include "OSGBillboard.h"
51 #include "OSGIntersectAction.h"
52 #include "OSGRenderAction.h"
53 #include "OSGCamera.h"
55 #include "OSGQuaternion.h"
56 #include "OSGMatrix.h"
60 // Documentation for this class is emited in the
61 // OSGBillboardBase.cpp file.
62 // To modify it, please change the .fcd file (OSGBillboard.fcd) and
63 // regenerate the base file.
65 /*----------------------- constructors & destructors ----------------------*/
69 Billboard::Billboard(void) :
77 Billboard::Billboard(const Billboard
&source
) :
79 _camTransform(source
._camTransform
)
85 Billboard::~Billboard(void)
89 /*----------------------------- class specific ----------------------------*/
91 //! initialize the static features of the class, e.g. action callbacks
93 void Billboard::initMethod(InitPhase ePhase
)
95 Inherited::initMethod(ePhase
);
97 if(ePhase
== TypeObject::SystemPost
)
99 IntersectAction::registerEnterDefault(
101 reinterpret_cast<Action::Callback
>(&Billboard::intersectEnter
));
103 IntersectAction::registerLeaveDefault(
105 reinterpret_cast<Action::Callback
>(&Billboard::intersectLeave
));
108 RenderAction::registerEnterDefault(
109 Billboard::getClassType(),
110 reinterpret_cast<Action::Callback
>(&Billboard::renderEnter
));
112 RenderAction::registerLeaveDefault(
113 Billboard::getClassType(),
114 reinterpret_cast<Action::Callback
>(&Billboard::renderLeave
));
118 //! react to field changes
120 void Billboard::changed(ConstFieldMaskArg whichField
,
124 Inherited::changed(whichField
, origin
, details
);
127 //! output the instance for debug purposes
129 void Billboard::dump( UInt32 uiIndent
,
130 const BitVector bvFlags
) const
132 Inherited::dump(uiIndent
, bvFlags
);
136 /*------------------------- volume update -------------------------------*/
138 void Billboard::adjustVolume( Volume
& volume
)
140 Inherited::adjustVolume(volume
);
142 // enlarge the volume to adjust for rotations
143 // keep the center, but make it a cube big enough to contain the
144 // billboard in all orientations
148 volume
.getBounds(min
, max
);
150 Vec3f dia
= max
- min
;
151 Pnt3f center
= min
+ dia
* .5;
152 Real32 extend
= dia
.maxValue();
154 dia
.setValues(extend
* Sqrt2
, extend
* Sqrt2
, extend
* Sqrt2
);
156 volume
.extendBy( center
- dia
);
157 volume
.extendBy( center
+ dia
);
160 void Billboard::accumulateMatrix(Matrix
&result
)
162 result
.mult(_camTransform
);
165 void Billboard::calcMatrix(const Matrix
&camToWorld
,
166 const Matrix
&mToWorld
,
169 Pnt3f
eyepos(0.f
, 0.f
, 0.f
);
170 Pnt3f
objpos(0.f
, 0.f
, 0.f
);
173 Vec3f
n(0.f
, 0.f
, 1.f
);
177 mResult
.invertFrom(mToWorld
);
181 if(getAxisOfRotation() == Vec3f::Null
)
183 if(_sfFocusOnCamera
.getValue() == true)
189 camToWorld
.mult(eyepos
, eyepos
);
190 mToWorld
.mult(objpos
, objpos
);
192 vDir
= eyepos
- objpos
;
194 vUp
.setValue (camToWorld
[0]);
196 vUp
= vDir
.cross(vUp
);
203 vX
= vUp
.cross(vDir
);
220 if(_sfAlignToScreen
.getValue() == false)
222 Vec3f
u (0.f
, 1.f
, 0.f
);
226 camToWorld
.mult(eyepos
, eyepos
);
227 mToWorld
.mult(objpos
, objpos
);
229 vDir
= eyepos
- objpos
;
231 // vDir.setValue(camToWorld[2]);
233 vUp
.setValue (camToWorld
[1]);
235 Quaternion
qN(n
, vDir
);
241 q1
.setValue(uW
, vUp
);
247 Vec3f
u (0.f
, 1.f
, 0.f
);
251 vDir
.setValue(camToWorld
[2]);
253 vUp
.setValue (camToWorld
[1]);
255 Quaternion
qN(n
, vDir
);
261 q1
.setValue(uW
, vUp
);
273 camToWorld
.mult(eyepos
, eyepos
);
274 mToWorld
.mult(objpos
, objpos
);
276 mToWorld
.mult(getAxisOfRotation(), wUp
);
278 vDir
= eyepos
- objpos
;
281 tDir
= wUp
.cross(s
);
283 n
= getAxisOfRotation();
287 n
-= n
.dot(getAxisOfRotation())*getAxisOfRotation();
289 q1
.setValue(n
, tDir
);
291 // clamp angle to [min; max]
295 if(getMinAngle() <= getMaxAngle())
297 q1
.getValueAsAxisRad(axis
, angle
);
299 if(angle
< getMinAngle())
300 angle
= getMinAngle();
302 if(angle
> getMaxAngle())
303 angle
= getMaxAngle();
305 q1
.setValueAsAxisRad(axis
, angle
);
312 mTrans
[3][0] = mToWorld
[3][0];
313 mTrans
[3][1] = mToWorld
[3][1];
314 mTrans
[3][2] = mToWorld
[3][2];
316 mMat
.setTransform(q1
);
318 mResult
.mult(mTrans
);
321 mTrans
[3][0] = -mToWorld
[3][0];
322 mTrans
[3][1] = -mToWorld
[3][1];
323 mTrans
[3][2] = -mToWorld
[3][2];
325 mResult
.mult(mTrans
);
326 mResult
.mult(mToWorld
);
328 _camTransform
= mResult
;
332 /*-------------------------------------------------------------------------*/
335 Action::ResultE
Billboard::intersectEnter(Action
*action
)
337 IntersectAction
*ia
= dynamic_cast<IntersectAction
*>(action
);
338 Matrix
m(_camTransform
);
345 m
.multFull(ia
->getLine().getPosition (), pos
);
346 m
.mult (ia
->getLine().getDirection(), dir
);
348 ia
->setLine(Line(pos
, dir
), ia
->getMaxDist());
349 ia
->scale(dir
.length());
351 return Action::Continue
;
354 Action::ResultE
Billboard::intersectLeave(Action
*action
)
356 IntersectAction
*ia
= dynamic_cast<IntersectAction
*>(action
);
357 Matrix
m(_camTransform
);
362 m
.multFull(ia
->getLine().getPosition (), pos
);
363 m
.mult (ia
->getLine().getDirection(), dir
);
365 ia
->setLine(Line(pos
, dir
), ia
->getMaxDist());
366 ia
->scale(dir
.length());
368 return Action::Continue
;
371 /*-------------------------------------------------------------------------*/
374 Action::ResultE
Billboard::renderEnter(Action
*action
)
376 RenderAction
*pAction
=
377 dynamic_cast<RenderAction
*>(action
);
380 Matrix cam_to_world
=
381 pAction
->getActivePartition()->getVPCameraToWorld();
383 this->calcMatrix(cam_to_world
, pAction
->topMatrix(), mMat
);
385 pAction
->pushMatrix(mMat
);
387 // !!! can't use visibles, as ToWorld gives garbage leading to wrong culling
388 // pAction->selectVisibles();
390 return Action::Continue
;
393 Action::ResultE
Billboard::renderLeave(Action
*action
)
395 RenderAction
*pAction
=
396 dynamic_cast<RenderAction
*>(action
);
398 pAction
->popMatrix();
400 return Action::Continue
;