source: osgVisual/trunk/src/object/visual_object.cpp @ 205

Last change on this file since 205 was 205, checked in by Torben Dannhauer, 13 years ago
File size: 14.0 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 factor
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
68visual_object* visual_object::createNodeFromXMLConfig(osg::CoordinateSystemNode* sceneRoot_, xmlNode* a_node)
69{
70        if(a_node == NULL)
71                return NULL;
72
73        OSG_NOTIFY( osg::ALWAYS ) << __FUNCTION__ << "Try to creating a new Model.." << std::endl;
74        //osg::ref<visual_object> object = new visual_object( root, nodeName);
75
76        std::string objectname="", filename="", label="";
77        bool dynamic = false;
78        double lat=0.0, lon=0.0, alt=0.0, rot_x=0.0, rot_y=0.0, rot_z=0.0;
79        double cam_trans_x=0.0, cam_trans_y=0.0, cam_trans_z=0.0, cam_rot_x=0.0, cam_rot_y=0.0, cam_rot_z=0.0;
80        double geometry_rot_x=0.0, geometry_rot_y=0.0, geometry_rot_z=0.0;
81        double geometry_scale_x=1.0, geometry_scale_y=1.0, geometry_scale_z=1.0;
82        osg::ref_ptr<osgVisual::object_updater> updater = NULL;
83
84        osgVisual::visual_object* object = new osgVisual::visual_object( sceneRoot_, objectname );
85        object->lat = lat;
86        object->lon = lon;
87        object->alt = alt;
88        object->azimuthAngle_psi = rot_x;
89        object->pitchAngle_theta = rot_y;
90        object->bankAngle_phi = rot_z;
91        if(label!="")
92                object->addLabel("XML_defined_label", label);
93        if(dynamic)
94        {
95                updater = new osgVisual::object_updater(object);
96        }
97        object->setCameraOffset( cam_trans_x, cam_trans_y, cam_trans_z, cam_rot_x, cam_rot_y, cam_rot_z);
98        if(filename!="")
99        {
100                object->loadGeometry( filename );
101                object->setGeometryOffset( geometry_rot_x, geometry_rot_y, geometry_rot_z );
102                object->setScale( geometry_scale_x, geometry_scale_y, geometry_scale_z ); 
103        }
104
105        if(updater.valid())
106                object->addUpdater( updater ); 
107
108        /*
109        - updater [optional]: Channels to use for position and attitude update
110
111        <updater>
112          <translation-slots>todo</translation-slots>
113        </updater>
114    */
115
116        OSG_NOTIFY( osg::ALWAYS ) << "Done." << std::endl;
117        return object;
118}
119
120void visual_object::setNewPositionAttitude( double lat_, double lon_, double alt_, double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
121{
122        lat = lat_;
123        lon = lon_;
124        alt = alt_;
125
126        azimuthAngle_psi = azimuthAngle_psi_;
127        pitchAngle_theta = pitchAngle_theta_;
128        bankAngle_phi = bankAngle_phi_;
129}
130
131void visual_object::setNewPosition( double lat_, double lon_, double alt_ )
132{
133        lat = lat_;
134        lon = lon_;
135        alt = alt_;
136}
137
138void visual_object::setNewAttitude( double azimuthAngle_psi_, double pitchAngle_theta_, double bankAngle_phi_ )
139{
140        azimuthAngle_psi = azimuthAngle_psi_;
141        pitchAngle_theta = pitchAngle_theta_;
142        bankAngle_phi = bankAngle_phi_;
143}
144
145void visual_object::setGeometryOffset( double rotX_, double rotY_, double rotZ_ )
146{
147        geometry_offset_rotation.makeRotate( rotX_, osg::Vec3f(1.0, 0.0, 0.0), 
148                                                rotY_, osg::Vec3f(0.0, 1.0, 0.0),
149                                                rotZ_, osg::Vec3f(0.0, 0.0, 1.0) );
150}
151
152void visual_object::setScale( double scale_ )
153{
154        scaleX = scale_;
155        scaleY = scale_;
156        scaleZ = scale_;
157}
158
159void visual_object::setScale( double scaleX_, double scaleY_, double scaleZ_ )
160{
161        scaleX = scaleX_;
162        scaleY = scaleY_;
163        scaleZ = scaleZ_;
164}
165
166bool visual_object::loadGeometry(std::string filename_)
167{
168        // Check if file exists
169        if( !osgDB::fileExists(filename_) )
170        {
171                OSG_NOTIFY(osg::FATAL) << "Error: Model not loaded. File '" << filename_ << "' does not exist." << std::endl;
172        }
173
174        osg::ref_ptr<osg::Node> tmpModel = osgDB::readNodeFile( filename_ );
175       
176        if( tmpModel.valid() )
177        {
178                // remove old geometry
179                geometry->removeChildren(0, geometry->getNumChildren());
180
181                // add new geometry
182                geometry->addChild( tmpModel.get() );
183                return true;
184        }
185        else
186        {
187                std::cout <<": No model loaded: " << filename_ << std::endl;
188        return false;
189    }
190}
191
192bool visual_object::setGeometry(osg::Node* geometry_)
193{
194        // remove old geometry
195        geometry->removeChildren(0, geometry->getNumChildren());
196
197        // add new geometry
198        geometry->addChild( geometry_ );
199
200        return true;
201}
202
203void visual_object::unsetGeometry()
204{
205        // remove old geometry
206        geometry->removeChildren(0, geometry->getNumChildren());
207}
208
209void visual_object::addUpdater( object_updater* updater_ )
210{
211        if ( updater.valid() )
212                updater->addUpdater( updater_ );
213        else
214                updater = updater_;
215}
216
217void visual_object::clearAllUpdater()
218{
219        // release only first updater. Because smartpointer: Will be deleted if not referenced.
220        if ( updater.valid() )
221                updater = NULL;
222}
223
224std::vector<object_updater*> visual_object::getUpdaterList()
225{
226        // iterate through updater and add all pointer.
227        std::vector<object_updater*> updaterList;
228        osg::ref_ptr<object_updater> tmpUpdater = updater;
229
230        while (tmpUpdater.valid())
231        {
232                updaterList.push_back( tmpUpdater );
233                tmpUpdater = tmpUpdater->getPointer();
234        }
235
236        // return list
237        return updaterList;
238}
239
240void visual_object::visual_objectPositionCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
241{
242        visual_object* object = dynamic_cast<visual_object*>(node);
243        if ( !object )
244        {
245                OSG_NOTIFY(osg::FATAL) << "ERROR : No object found. Unable to apply this callback!" << std::endl;
246                return;
247        }
248
249        // execute preUpdater to get new data of this object.
250        if ( object->updater.valid() )
251                object->updater->preUpdate(object);
252   
253        // Nodepath from this node to absolute parent (if no endnode specified)
254        osg::NodePath nodePath = nv->getNodePath();
255
256        // If Nodepath != empty, then mt = last element of node path
257        osg::MatrixTransform* mt = nodePath.empty() ? 0 : dynamic_cast<osg::MatrixTransform*>(nodePath.back());
258        if (mt)
259        {
260                osg::CoordinateSystemNode* csn = 0;
261
262                // find coordinate system node from our parental chain: traverse chain and try to convert every node to a csn.
263                unsigned int i;
264                for(i=0; i<nodePath.size() && csn==0; ++i)      // "&& csn" means: exit loop if csn found
265                {
266                        csn = dynamic_cast<osg::CoordinateSystemNode*>(nodePath[i]);    // dynamic_cast returns 0 if dynamic_cast fails.
267                }
268       
269                // Wenn csn gefunden:
270                if (csn)
271                {
272                        // Ellipsoidmodel erfragen
273                        osg::EllipsoidModel* ellipsoid = csn->getEllipsoidModel();
274                        if (ellipsoid)
275                        {
276                                osg::Matrix inheritedMatrix;
277
278                                // durch den _restlichen_ Nodepath durchgehen und alle anfallenden Transformationen durchführen.
279                                for(i+=1; i<nodePath.size()-1; ++i)
280                                {
281                                        osg::Transform* transform = nodePath[i]->asTransform(); // Versuchen, den Node zu einer Transformation zu konvertieren
282                   
283                                        // wenn Node wirklich Trafo, dann die Tranformationsmatrix von Nodekoordinaten nach Global auf inheritedMatrix draufschlagen.
284                                        if (transform) transform->computeLocalToWorldMatrix(inheritedMatrix, nv);
285                                }
286               
287                                osg::Matrixd matrix(inheritedMatrix);
288
289                                // Set position
290                                ellipsoid->computeLocalToWorldTransformFromLatLongHeight(object->lat, object->lon, object->alt, matrix);
291
292                                // Set Upvector for position
293                                double X,Y,Z;
294                                util::calculateXYZAtWGS84Coordinate(object->lat, object->lon, object->alt, csn, X, Y, Z );
295                                object->upVector = ellipsoid->computeLocalUpVector(X,Y,Z);
296
297                                // Set scale
298                                osg::Matrixd scaleMatrix;
299                                scaleMatrix.makeScale( object->scaleX, object->scaleY, object->scaleZ );
300                                matrix.preMult( scaleMatrix );
301
302                                // Set rotation
303                                // rotation von links ranmultiplizieren, entspricht: matrix = rotation * matrix. Da rotation ein Quat ist, wäre die direkte Multiplikation nur über Umwege machbar.
304                                // Rotate Object to Attitude.
305                                osg::Matrixd rotationMatrix;
306                                // Move Model by Azimuth
307                                rotationMatrix.makeRotate( -object->azimuthAngle_psi, osg::Vec3d(0.0, 0.0, 1.0) );
308                                matrix.preMult(rotationMatrix); 
309                                // Move Model by Pitch
310                                rotationMatrix.makeRotate( object->pitchAngle_theta, osg::Vec3d(1.0, 0.0, 0.0) );
311                                matrix.preMult(rotationMatrix);
312                                // Move Model by Bank
313                                rotationMatrix.makeRotate( object->bankAngle_phi, osg::Vec3d(0.0, 1.0, 0.0) );
314                                matrix.preMult(rotationMatrix);
315
316                                // Also update camera matrix (without geometry offset, because camera is interested in the objects matrix, not in the model's matrix.)
317                                object->cameraMatrix = matrix;
318                                /** \todo : Clean up camera matrix management: try to solve it with a single matrix. (each frame two matrix mults less) */
319                                // dont know, why this rotation is necessary - maybe manipulator and node MatrixTransform interpret a matrix in different way?
320                                object->cameraMatrix.preMult( object->cameraTranslationOffset );
321                                object->cameraMatrix.preMult( object->cameraRotationOffset );
322                                                       
323
324                                // Set geometry correction
325                                matrix.preMultRotate( object->geometry_offset_rotation );
326
327                                // Set cumulated object matrix as the matrix of this matrix transform
328                                mt->setMatrix(matrix);
329                        }
330                }       
331        }
332     
333        // Call any nested callbacks.
334        traverse(node,nv);
335
336        // If SLAVE: execute postUpdater to pass new data of this object to dataIO.
337        if( visual_dataIO::getInstance()->isSlave() )
338        {
339                if ( object->updater.valid() )
340                        object->updater->postUpdate(object);
341        }
342
343}   // Callbackfunction [ Operater() ] END
344
345void visual_object::setCameraOffsetTranslation( double x_, double y_, double z_)
346{
347        cameraTranslationOffset.makeTranslate( osg::Vec3d(x_, y_, z_) );        // Trans: (rechts davon, longitudinal, vertikal)
348}
349
350void visual_object::setCameraOffset(double x_, double y_, double z_, double rotX_, double rotY_, double rotZ_)
351{
352        setCameraOffsetTranslation( x_, y_, z_);
353        setCameraOffsetRotation( rotX_, rotY_, rotZ_);
354}
355
356void visual_object::setCameraOffsetRotation(double rotX_, double rotY_, double rotZ_)
357{
358        osg::Matrix tmp;
359        cameraRotationOffset.makeRotate( osg::DegreesToRadians( 90.0 ), osg::Vec3(1, 0, 0) );
360        tmp.makeRotate( -rotZ_, osg::Vec3d(0.0, 1.0, 0.0) );
361        cameraRotationOffset.preMult(tmp);
362        tmp.makeRotate( rotY_, osg::Vec3d(1.0, 0.0, 0.0) );     
363        cameraRotationOffset.preMult(tmp);
364        tmp.makeRotate( -rotX_, osg::Vec3d(0.0, 0.0, 1.0) );   
365        cameraRotationOffset.preMult(tmp);
366}
367
368void visual_object::clearLabels()
369{
370        labels->removeDrawables(0, labels->getNumDrawables());
371}
372
373void visual_object::addLabel(std::string idString_, std::string label_, osg::Vec4 color_, osg::Vec3 offset_)
374{
375        osg::ref_ptr<osgText::Text> text = new osgText::Text();
376
377        text->setName(idString_);
378        text->setText(label_);
379        text->setColor(color_);
380        text->setFont("fonts/arial.ttf");
381        text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS_WITH_MAXIMUM_SCREEN_SIZE_CAPPED_BY_FONT_HEIGHT);
382        text->setAutoRotateToScreen(true);
383        text->setPosition(offset_);
384
385        text->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
386        labels->addDrawable( text );
387}
388
389bool visual_object::removeLabel(std::string idString_)
390{
391        osg::Node* labelToRemove = util::findNamedNode(idString_, this);
392
393        if(labelToRemove)
394        {
395                removeChild( labelToRemove );
396                return true;
397        }
398        else
399                return false;
400}
401
402bool visual_object::updateLabelText(std::string idString_, std::string label_)
403{
404        osg::Node* labelToUpdate = util::findNamedNode(idString_, this);
405
406        if(labelToUpdate)
407        {
408                osgText::Text* text = dynamic_cast<osgText::Text*>(labelToUpdate);
409                if(text)
410                {
411                        text->setText(label_);
412                        return true;
413                }
414                return false;
415        }
416        return false;
417}
418
419osgText::Text* visual_object::getLabel(std::string idString_)
420{
421        osg::Node* labelToFind = util::findNamedNode(idString_, this);
422
423        if(labelToFind)
424        {
425                osgText::Text* text = dynamic_cast<osgText::Text*>(labelToFind);
426                if(text)
427                        return text;
428        }
429        return NULL;
430
431}
432
433bool visual_object::setDrawLabelAsOverlay(std::string idString_, bool drawAsOverlay)
434{
435        osg::Node* labelToFind = util::findNamedNode(idString_, this);
436
437        if(labelToFind)
438        {
439                if (drawAsOverlay)
440                        labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
441                else
442                        labelToFind->getOrCreateStateSet()->setMode(GL_DEPTH_TEST,osg::StateAttribute::ON);
443                return true;
444        }
445        else 
446                return false;
447}
448
449bool visual_object::getDrawLabelAsOverlay(std::string idString_)
450{
451        osg::Node* labelToFind = util::findNamedNode(idString_, this);
452
453        if(labelToFind)
454        {
455                if(labelToFind->getOrCreateStateSet()->getMode(GL_DEPTH_TEST) == osg::StateAttribute::OFF)
456                        return false;
457                else 
458                        return true;
459        }
460        return false;
461}
Note: See TracBrowser for help on using the repository browser.