source: osgVisual/src/object/visual_object.cpp @ 31

Last change on this file since 31 was 31, checked in by Torben Dannhauer, 14 years ago

Adding first version of osgVisual!!

File size: 12.1 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
2 *
3 * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
9 * You have to aquire licenses for all used proprietary modules.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * OpenSceneGraph Public License for more details.
15*/
16
17#include <visual_object.h>
18
19using namespace osgVisual;
20
21visual_object::visual_object( osg::CoordinateSystemNode* sceneRoot_, std::string nodeName_)
22{
23        // Add this node to Scenegraph
24        sceneRoot_->addChild( this );
25
26        // Set Nodename for further identification
27        this->setName( nodeName_ );
28
29        // Set callback.
30        /** \todo: welcher update ist der richtige? voraussichtlich event.) */
31        //this->setUpdateCallback( new visual_objectPositionCallback() );
32        this->setEventCallback( new visual_objectPositionCallback() );
33
34        // Init Position and Attitude
35        lat = 0;
36        lon = 0;
37        alt = 0;
38
39        azimuthAngle_psi = 0;
40        pitchAngle_theta = 0;
41        bankAngle_phi = 0;
42
43        geometry_offset_rotation.makeRotate( 0.0, 1.0, 1.0, 1.0 );
44
45        // Init Scale
46        scaleX = 1.0;
47        scaleY = 1.0;
48        scaleZ = 1.0;
49
50        // Init cameraOffset
51        cameraTranslationOffset.makeTranslate( osg::Vec3d(0.0, 0.0, 0.0) );     // Trans: (y, x, -z_down)
52        cameraRotationOffset.makeRotate( osg::DegreesToRadians( 90.0 ), osg::Vec3(1, 0, 0) );   // Rot: (-y, +x , -z)
53
54        // Geometrynode hinzufügen
55        geometry = new osg::Group();
56        this->addChild( geometry );
57
58        // Labelnode hinzufügen
59        labels = new osg::Geode();
60        this->addChild( labels ); 
61}
62
63visual_object::~visual_object()
64{
65
66}
67
68void visual_object::setNewPositionAttitude( double lat_, double lon_, double alt_, double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
69{
70        lat = lat_;
71        lon = lon_;
72        alt = alt_;
73
74        azimuthAngle_psi = azimuthAngle_psi_;
75        pitchAngle_theta = pitchAngle_theta_;
76        bankAngle_phi = bankAngle_phi_;
77}
78
79void visual_object::setNewPosition( double lat_, double lon_, double alt_ )
80{
81        lat = lat_;
82        lon = lon_;
83        alt = alt_;
84}
85
86void visual_object::setNewAttitude( double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
87{
88        azimuthAngle_psi = azimuthAngle_psi_;
89        pitchAngle_theta = pitchAngle_theta_;
90        bankAngle_phi = bankAngle_phi_;
91}
92
93void visual_object::setGeometryOffset( double rotX_, double rotY_, double rotZ_ )
94{
95        geometry_offset_rotation.makeRotate( rotX_, osg::Vec3f(1.0, 0.0, 0.0), 
96                                                rotY_, osg::Vec3f(0.0, 1.0, 0.0),
97                                                rotZ_, osg::Vec3f(0.0, 0.0, 1.0) );
98}
99
100void visual_object::setScale( double scale_ )
101{
102        scaleX = scale_;
103        scaleY = scale_;
104        scaleZ = scale_;
105}
106
107void visual_object::setScale( double scaleX_, double scaleY_, double scaleZ_ )
108{
109        scaleX = scaleX_;
110        scaleY = scaleY_;
111        scaleZ = scaleZ_;
112}
113
114bool visual_object::loadGeometry(std::string filename_)
115{
116        // Check if file exists
117        if( !osgDB::fileExists(filename_) )
118        {
119                OSG_NOTIFY(osg::FATAL) << "Error: Model not loaded. File '" << filename_ << "' does not exist." << std::endl;
120        }
121
122        osg::ref_ptr<osg::Node> tmpModel = osgDB::readNodeFile( filename_ );
123       
124        if( tmpModel.valid() )
125        {
126                // remove old geometry
127                geometry->removeChildren(0, geometry->getNumChildren());
128
129                // add new geometry
130                geometry->addChild( tmpModel.get() );
131                return true;
132        }
133        else
134        {
135                std::cout <<": No model loaded: " << filename_ << std::endl;
136        return false;
137    }
138}
139
140bool visual_object::setGeometry(osg::Node* geometry_)
141{
142        // remove old geometry
143        geometry->removeChildren(0, geometry->getNumChildren());
144
145        // add new geometry
146        geometry->addChild( geometry_ );
147
148        return true;
149}
150
151void visual_object::unsetGeometry()
152{
153        // remove old geometry
154        geometry->removeChildren(0, geometry->getNumChildren());
155}
156
157void visual_object::addUpdater( object_updater* updater_ )
158{
159        if ( updater.valid() )
160                updater->addUpdater( updater_ );
161        else
162                updater = updater_;
163}
164
165void visual_object::clearAllUpdater()
166{
167        // release only first updater. Because smartpointer: Will be deleted if not referenced.
168        if ( updater.valid() )
169                updater = NULL;
170}
171
172std::vector<object_updater*> visual_object::getUpdaterList()
173{
174        // iterate through updater and add all pointer.
175        std::vector<object_updater*> updaterList;
176        osg::ref_ptr<object_updater> tmpUpdater = updater;
177
178        while (tmpUpdater.valid())
179        {
180                updaterList.push_back( tmpUpdater );
181                tmpUpdater = tmpUpdater->getPointer();
182        }
183
184        // return list
185        return updaterList;
186}
187
188void visual_object::visual_objectPositionCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
189{
190        visual_object* object = dynamic_cast<visual_object*>(node);
191        if ( !object )
192        {
193                OSG_NOTIFY(osg::FATAL) << "ERROR : No object found. Unable to apply this callback!" << std::endl;
194                return;
195        }
196
197        // execute preUpdater to get new data of this object.
198        if ( object->updater.valid() )
199                object->updater->preUpdate(object);
200   
201        // Nodepath from this node to absolute parent (if no endnode specified)
202        osg::NodePath nodePath = nv->getNodePath();
203
204        // If Nodepath != empty, then mt = last element of node path
205        osg::MatrixTransform* mt = nodePath.empty() ? 0 : dynamic_cast<osg::MatrixTransform*>(nodePath.back());
206        if (mt)
207        {
208                osg::CoordinateSystemNode* csn = 0;
209
210                // find coordinate system node from our parental chain: traverse chain and try to convert every node to a csn.
211                unsigned int i;
212                for(i=0; i<nodePath.size() && csn==0; ++i)      // "&& csn" means: exit loop if csn found
213                {
214                        csn = dynamic_cast<osg::CoordinateSystemNode*>(nodePath[i]);    // dynamic_cast returns 0 if dynamic_cast fails.
215                }
216       
217                // Wenn csn gefunden:
218                if (csn)
219                {
220                        // Ellipsoidmodel erfragen
221                        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
222                        if (ellipsoid)
223                        {
224                                osg::Matrix inheritedMatrix;
225
226                                // durch den _restlichen_ Nodepath durchgehen und alle anfallenden Transformationen durchführen.
227                                for(i+=1; i<nodePath.size()-1; ++i)
228                                {
229                                        osg::Transform* transform = nodePath[i]->asTransform(); // Versuchen, den Node zu einer Transformation zu konvertieren
230                   
231                                        // wenn Node wirklich Trafo, dann die Tranformationsmatrix von Nodekoordinaten nach Global auf inheritedMatrix draufschlagen.
232                                        if (transform) transform->computeLocalToWorldMatrix(inheritedMatrix, nv);
233                                }
234               
235                                osg::Matrixd matrix(inheritedMatrix);
236
237                                // Set position
238                                ellipsoid->computeLocalToWorldTransformFromLatLongHeight(object->lat, object->lon, object->alt, matrix);
239
240                                // Set Upvector for position
241                                double X,Y,Z;
242                                util::calculateXYZAtWGS84Coordinate(object->lat, object->lon, object->alt, csn, X, Y, Z );
243                                object->upVector = ellipsoid->computeLocalUpVector(X,Y,Z);
244
245                                // Set scale
246                                osg::Matrixd scaleMatrix;
247                                scaleMatrix.makeScale( object->scaleX, object->scaleY, object->scaleZ );
248                                matrix.preMult( scaleMatrix );
249
250                                // Set rotation
251                                // rotation von links ranmultiplizieren, entspricht: matrix = rotation * matrix. Da rotation ein Quat ist, wäre die direkte Multiplikation nur über Umwege machbar.
252                                // Rotate Object to Attitude.
253                                osg::Matrixd rotationMatrix;
254                                // Move Model by Azimuth
255                                rotationMatrix.makeRotate( -object->azimuthAngle_psi, osg::Vec3d(0.0, 0.0, 1.0) );
256                                matrix.preMult(rotationMatrix); 
257                                // Move Model by Pitch
258                                rotationMatrix.makeRotate( object->pitchAngle_theta, osg::Vec3d(1.0, 0.0, 0.0) );
259                                matrix.preMult(rotationMatrix);
260                                // Move Model by Bank
261                                rotationMatrix.makeRotate( object->bankAngle_phi, osg::Vec3d(0.0, 1.0, 0.0) );
262                                matrix.preMult(rotationMatrix);
263
264                                // Also update camera matrix (without geometry offset, because camera is interested in the objects matrix, not in the model's matrix.)
265                                object->cameraMatrix = matrix;
266                                /** \todo : Clean up camera matrix management: try to solve it with a single matrix. (each frame two matrix mults less) */
267                                // dont know, why this rotation is necessary - maybe manipulator and node MatrixTransform interpret a matrix in different way?
268                                object->cameraMatrix.preMult( object->cameraTranslationOffset );
269                                object->cameraMatrix.preMult( object->cameraRotationOffset );
270                                                       
271
272                                // Set geometry correction
273                                matrix.preMultRotate( object->geometry_offset_rotation );
274
275                                // Set matrix as cumulated object matrix
276                                mt->setMatrix(matrix);
277                        }
278                }       
279        }
280     
281        // Call any nested callbacks.
282        traverse(node,nv);
283
284        // If SLAVE: execute postUpdater to pass new data of this object to dataIO.
285        if( visual_dataIO::getInstance()->isSlave() )
286        {
287                if ( object->updater.valid() )
288                        object->updater->postUpdate(object);
289        }
290
291}   // Callbackfunction [ Operater() ] END
292
293void visual_object::setCameraOffsetTranslation( double x_, double y_, double z_)
294{
295        cameraTranslationOffset.makeTranslate( osg::Vec3d(x_, y_, z_) );        // Trans: (rechts davon, longitudinal, vertikal)
296}
297
298void visual_object::setCameraOffset(double x_, double y_, double z_, double rotX_, double rotY_, double rotZ_)
299{
300        setCameraOffsetTranslation( x_, y_, z_);
301        setCameraOffsetRotation( rotX_, rotY_, rotZ_);
302}
303
304void visual_object::setCameraOffsetRotation(double rotX_, double rotY_, double rotZ_)
305{
306        osg::Matrix tmp;
307        cameraRotationOffset.makeRotate( osg::DegreesToRadians( 90.0 ), osg::Vec3(1, 0, 0) );
308        tmp.makeRotate( -rotZ_, osg::Vec3d(0.0, 1.0, 0.0) );
309        cameraRotationOffset.preMult(tmp);
310        tmp.makeRotate( rotY_, osg::Vec3d(1.0, 0.0, 0.0) );     
311        cameraRotationOffset.preMult(tmp);
312        tmp.makeRotate( -rotX_, osg::Vec3d(0.0, 0.0, 1.0) );   
313        cameraRotationOffset.preMult(tmp);
314}
315
316void visual_object::clearLabels()
317{
318        labels->removeDrawables(0, labels->getNumDrawables());
319}
320
321void visual_object::addLabel(std::string idString_, std::string label_, osg::Vec4 color_, osg::Vec3 offset_)
322{
323        osg::ref_ptr<osgText::Text> text = new osgText::Text();
324
325        text->setName(idString_);
326        text->setText(label_);
327        text->setColor(color_);
328        text->setFont("fonts/arial.ttf");
329        text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
330        text->setAutoRotateToScreen(true);
331        text->setPosition(offset_);
332
333        text->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
334        labels->addDrawable( text );
335}
336
337bool visual_object::removeLabel(std::string idString_)
338{
339        osg::Node* labelToRemove = util::findNamedNode(idString_, this);
340
341        if(labelToRemove)
342        {
343                removeChild( labelToRemove );
344                return true;
345        }
346        else
347                return false;
348}
349
350bool visual_object::updateLabelText(std::string idString_, std::string label_)
351{
352        osg::Node* labelToUpdate = util::findNamedNode(idString_, this);
353
354        if(labelToUpdate)
355        {
356                osgText::Text* text = dynamic_cast<osgText::Text*>(labelToUpdate);
357                if(text)
358                {
359                        text->setText(label_);
360                        return true;
361                }
362                return false;
363        }
364        return false;
365}
366
367osgText::Text* visual_object::getLabel(std::string idString_)
368{
369        osg::Node* labelToFind = util::findNamedNode(idString_, this);
370
371        if(labelToFind)
372        {
373                osgText::Text* text = dynamic_cast<osgText::Text*>(labelToFind);
374                if(text)
375                        return text;
376        }
377        return NULL;
378
379}
380
381bool visual_object::setDrawLabelAsOverlay(std::string idString_, bool drawAsOverlay)
382{
383        osg::Node* labelToFind = util::findNamedNode(idString_, this);
384
385        if(labelToFind)
386        {
387                if (drawAsOverlay)
388                        labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
389                else
390                        labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);
391                return true;
392        }
393        else 
394                return false;
395}
396
397bool visual_object::getDrawLabelAsOverlay(std::string idString_)
398{
399        osg::Node* labelToFind = util::findNamedNode(idString_, this);
400
401        if(labelToFind)
402        {
403                if(labelToFind->getOrCreateStateSet()->getMode(GL_DEPTH_TEST) == osg::StateAttribute::OFF)
404                        return false;
405                else 
406                        return true;
407        }
408        return false;
409}
Note: See TracBrowser for help on using the repository browser.