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

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