Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/ColladaPlugin/src/OgreColladaScene.cpp @ 21

Last change on this file since 21 was 21, checked in by nicolasc, 17 years ago

added ogreode and Colladaplugin

File size: 20.1 KB
Line 
1/**
2 * This source file is part of OgreColladaPlugin
3 * an addon for OGRE (Object-oriented Graphics Rendering Engine)
4 * For the latest info, see http://www.ogre3d.org/
5 *
6 * This program is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by the Free Software
8 * Foundation; either version 2 of the License, or (at your option) any later
9 * version.
10
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14
15 * You should have received a copy of the GNU Lesser General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
18 * http://www.gnu.org/copyleft/lesser.txt.
19 *
20 * @author      Philipp Hartl
21 * @see         README
22 */
23
24#include "OgreColladaScene.h"
25#include "OgreColladaDocument.h"
26#include "OgreColladaGeometry.h"
27#include "OgreColladaLibrary.h"
28#include "OgreColladaSyntax.h"
29#include "OgreColladaUtils.h"
30
31#include "OgreStringVector.h"
32#include "OgreAxisAlignedBox.h"
33#include "OgreStringConverter.h"
34#include "OgreSceneManager.h"
35
36
37namespace Ogre
38{
39        //-------------------------------------------------------------------------
40        ColladaBoundingBox::ColladaBoundingBox(ColladaSceneNode *p) : ColladaNodeElement(p) 
41        { 
42                mMin = Vector3::ZERO;
43                mMax = Vector3::ZERO;
44        }
45
46        //-------------------------------------------------------------------------
47        ColladaBoundingBox::ColladaBoundingBox(const Vector3 &min, const Vector3 &max)
48                : ColladaNodeElement(NULL), mMin(min), mMax(max) { }
49
50        //-------------------------------------------------------------------------
51        ColladaBoundingBox::~ColladaBoundingBox(void) { }
52
53        //-------------------------------------------------------------------------
54        void ColladaBoundingBox::doImport(xmlNode *node)
55        { 
56                if (node == NULL) return;
57
58                for (xmlNode *c = node->children; c != NULL; c = c->next)
59                {
60                        if (c->type != XML_ELEMENT_NODE) continue;
61                        String tagname = (const char *)c->name;
62
63                        // <min>
64                        if (tagname == CS_ELM_MIN)
65                        {
66                                // fill up minimum vector
67                                mMin = StringConverter::parseVector3(ColladaUtils::getContentDirect(c));
68                        }
69                        // <max>
70                        else if (tagname == CS_ELM_MAX)
71                        {
72                                // fill up maximum vector
73                                mMax = StringConverter::parseVector3(ColladaUtils::getContentDirect(c));
74                        }
75                        // unknown or unsupported
76                        else
77                        {
78                                LogManager::getSingleton().logMessage("ColladaBoundingBox::doImport - unknown child: " + tagname);
79                        }
80                }
81        }
82
83        //-------------------------------------------------------------------------
84        AxisAlignedBox ColladaBoundingBox::getAABB(void) const
85        {
86                return AxisAlignedBox(mMin, mMax);
87        }
88
89        //-------------------------------------------------------------------------
90        float ColladaBoundingBox::getRadius(void) const
91        {
92                Vector3 dist = mMax - (mMax + mMin) * 0.5;
93                return dist.length();
94        }
95
96        //-------------------------------------------------------------------------
97        String ColladaBoundingBox::toString(void) const
98        {
99                return "min: " + StringConverter::toString(mMin) + " max: " + StringConverter::toString(mMax);
100        }
101
102        //-------------------------------------------------------------------------
103        // ColladaScene
104        //-------------------------------------------------------------------------
105
106        //-------------------------------------------------------------------------
107        ColladaSceneNode::ColladaSceneNode(ColladaDocument *doc, xmlNode *node) : ColladaEntity(doc, node)
108        { 
109                mType = NODE;
110                mBB   = NULL;
111                mParent = NULL;
112                mEntity = NULL;
113        }
114
115        //-------------------------------------------------------------------------
116        ColladaSceneNode::~ColladaSceneNode(void) 
117        {
118                for (ColladaSceneNodePtrVector::iterator it = mChilds.begin(); it != mChilds.end(); ++it)
119                {
120                        OGRE_DELETE(*it);
121                }
122                mChilds.clear();
123                mParent = NULL;
124                mEntity = NULL;         // the entities will be cleared by the library container
125
126                for (ColladaTransformPtrVector::iterator jt = mTransforms.begin(); jt != mTransforms.end(); ++jt)
127                {
128                        OGRE_DELETE(*jt);
129                }
130                mTransforms.clear();
131
132                OGRE_DELETE(mBB);
133        }
134
135        //-------------------------------------------------------------------------
136        void ColladaSceneNode::attachEntityToOgreSceneNode(SceneNode *ogrenode) const
137        {
138                if (mEntity == NULL || ogrenode == NULL) return;
139
140                if (mEntity->getEntityType() == GEOMETRY ||
141                        mEntity->getEntityType() == LIGHT ||
142                        mEntity->getEntityType() == CAMERA)
143                {
144                        // the geometry need some special data
145                        if (mEntity->getEntityType() == GEOMETRY)
146                        {
147                                ColladaGeometry *geo = static_cast<ColladaGeometry *>(mEntity);
148                                geo->setEntityName(mId);        // a unique name for the ogre entity, should not be NULL!
149                                // geo->setBoundingBox(mBB);    // a bounding box, can be NULL
150                        }
151
152                        // create an ogre entity
153                        MovableObject *mo = mEntity->getOgreInstance();
154                        if (mo != NULL) ogrenode->attachObject(mo);
155                }
156        }
157
158        //-------------------------------------------------------------------------
159        void ColladaSceneNode::attachTransformsToOgreSceneNode(SceneNode *ogrenode) const
160        {
161                if (ogrenode == NULL || mTransforms.empty()) return;
162
163                for (ColladaTransformPtrVector::const_iterator it = mTransforms.begin(); it != mTransforms.end(); ++it)
164                {
165                        if ((*it)->getType() == ColladaTransform::ROTATE)
166                        {
167                                // rotation has local affects
168                                ColladaTRotate *r = static_cast<ColladaTRotate *>(*it);
169                Quaternion rot(Degree(r->getAngle()), r->getAxis());
170                mDoc->correctAxis(rot);
171                                ogrenode->rotate(rot);
172                        }
173                        else if ((*it)->getType() == ColladaTransform::SCALE)
174                        {
175                                ogrenode->scale(static_cast<ColladaTScale *>(*it)->getScale());
176                        }
177                        else if ((*it)->getType() == ColladaTransform::TRANSLATE)
178                        {
179                                // translation is relative to parent
180                ogrenode->translate(static_cast<ColladaTTranslate *>(*it)->getTranslate());
181                        }
182                }
183
184        // correct transforms for ogre axis
185        Vector3 pos = ogrenode->getPosition();
186        mDoc->correctAxis(pos);
187        ogrenode->setPosition(pos);
188        }
189
190        //-------------------------------------------------------------------------
191        void ColladaSceneNode::createOgreInstance(SceneNode *ogrenode) const
192        {
193                if (ogrenode == NULL) ogrenode = mDoc->getSceneManager()->getRootSceneNode();
194
195                if (mType == NODE)
196                {
197                        // transforms
198                        attachTransformsToOgreSceneNode(ogrenode);
199
200                        // boundingbox
201
202                        // entity
203                        attachEntityToOgreSceneNode(ogrenode);
204                }
205
206                for (ColladaSceneNodePtrVector::const_iterator it = mChilds.begin(); it != mChilds.end(); ++it)
207                {
208                        // the new child will be automatically attached to the scene graph
209                        (*it)->createOgreInstance(ogrenode->createChildSceneNode((*it)->mId));
210                }
211        }
212
213        //-------------------------------------------------------------------------
214        bool ColladaSceneNode::doImport(void)
215        {
216                if (mLoaded) return mStatus;
217                else mLoaded = true;
218
219                // get unique identifier of scene
220                initialise();
221
222                // if the xmlNode is a <node> there could be a type attribute [JOINT or NODE] (last is default)
223                String type = ColladaUtils::getProperty(mNode, CS_ATR_TYPE);
224                if (!type.empty())
225                {
226                        if (type == CS_VAL_NODE_TYPE_JOINT) mType = JOINT;
227                }
228
229                // walk through child elements, the order is important
230        for (xmlNode *child = mNode->children; child != NULL; child = child->next)
231                {
232                        // we are interested on element nodes only
233                        if (child->type != XML_ELEMENT_NODE) continue;
234
235                        String tagname = (const char *)child->name;
236
237                        // look for <extra>
238                        if (tagname == CS_ELM_EXTRA) 
239                        {
240                                importExtra(child);
241                        }
242                        // look for <boundingbox>
243                        else if (tagname == CS_ELM_BOUNDINGBOX) 
244                        {
245                                mBB = new ColladaBoundingBox(this);
246                                mBB->doImport(child);
247                        }
248                        // look for <node> (build up subtree)
249                        else if (tagname == CS_ELM_NODE) 
250                        {
251                                ColladaSceneNode *snode = new ColladaSceneNode(mDoc, child);
252                                if (!snode->doImport()) return false;
253                                // each node should be unique
254                                snode->mParent = this;
255                                mChilds.push_back(snode);
256                        }
257                        // look for <instance> and link entity
258                        else if (tagname == CS_ELM_INSTANCE) 
259                        {
260                                importInstance(child);
261                        }
262                        // look for transformations <lookat>, <matrix> ... <translate>
263                        else if (tagname == CS_ELM_LOOKAT || 
264                                tagname == CS_ELM_MATRIX ||
265                                tagname == CS_ELM_PERSPECTIVE || 
266                                tagname == CS_ELM_ROTATE ||
267                                tagname == CS_ELM_SCALE || 
268                                tagname == CS_ELM_SKEW ||
269                                tagname == CS_ELM_TRANSLATE)
270                        {
271                                ColladaTransform *t;
272                                if (tagname == CS_ELM_LOOKAT) t = new ColladaTLookAt(this);
273                                else if (tagname == CS_ELM_MATRIX) t = new ColladaTMatrix(this);
274                                else if (tagname == CS_ELM_PERSPECTIVE) t = new ColladaTPerspective(this);
275                                else if (tagname == CS_ELM_ROTATE) t = new ColladaTRotate(this);
276                                else if (tagname == CS_ELM_SCALE) t = new ColladaTScale(this);
277                                else if (tagname == CS_ELM_SKEW) t = new ColladaTSkew(this);
278                                else if (tagname == CS_ELM_TRANSLATE) t = new ColladaTTranslate(this);
279                                else t = NULL;
280
281                                if (t != NULL)
282                                {
283                                        t->doImport(child);
284                                        mTransforms.push_back(t);
285                                }
286                        }
287                        else
288                        {
289                                LogManager::getSingleton().logMessage("ColladaSceneNode::doImport - unknown child: " + tagname + " of " + mId);
290                        }
291                }
292
293                mStatus = true;
294                return mStatus;
295        }
296
297        //-------------------------------------------------------------------------
298        ColladaSceneNode *ColladaSceneNode::getNode(const String &id)
299        {
300                if (this->mId == id) return this;
301
302                ColladaSceneNode *tmp = NULL;
303                for (ColladaSceneNodePtrVector::const_iterator it = mChilds.begin(); it != mChilds.end(); ++it)
304                {
305                        tmp = (*it)->getNode(id);
306                        if (tmp != NULL) break;
307                }
308                return tmp;
309        }
310
311        //-------------------------------------------------------------------------
312        void ColladaSceneNode::importExtra(xmlNode *node)
313        {
314                // not yet implemented
315                // scene extra information
316        }
317
318        //-------------------------------------------------------------------------
319        void ColladaSceneNode::importInstance(xmlNode *node)
320        {
321                String url = ColladaUtils::getProperty(node, CS_ATR_URL);
322                if (url.empty())
323                {
324                        LogManager::getSingleton().logMessage("ColladaSceneNode::importInstance - no instance url is given!");
325                        return;
326                }
327
328                // local reference
329                if (url.find("#") == 0)
330                {
331                        // we do not need the # sign
332                        url.erase(0,1);
333
334                        // we do not know where the instance belongs to, so let library to find out
335                        mEntity = mDoc->getLibrary()->importInstance(url);
336                        if (mEntity == NULL)
337                        {
338                                LogManager::getSingleton().logMessage("ColladaSceneNode::importInstance - creating instance of " + url + " failed");
339                        }
340                }
341                // external reference
342                else
343                {
344                        // not yet implemented !!
345                        LogManager::getSingleton().logMessage("ColladaSceneNode::importInstance - external references are currently not implemented!");
346                }
347        }
348
349        //-------------------------------------------------------------------------
350        // ColladaTransform(s)
351        //-------------------------------------------------------------------------
352
353        //-------------------------------------------------------------------------
354        ColladaTLookAt::ColladaTLookAt(ColladaSceneNode *p) : ColladaTransform(p)
355        {
356                mMatrix = Matrix3::IDENTITY;
357        }
358
359        //-------------------------------------------------------------------------
360        ColladaTLookAt::~ColladaTLookAt(void) { }
361
362        //-------------------------------------------------------------------------
363        void ColladaTLookAt::doImport(xmlNode *node)
364        {
365                if (node == NULL) return;
366
367                String content = ColladaUtils::getContentDirect(node);
368                if (content.empty()) return;
369
370                StringVector lines = StringUtil::split(content,"\r\n");
371                if (lines.size() != 3) return;
372
373                uint i = 0;
374                for (StringVector::iterator it = lines.begin(); it != lines.end(); ++it)
375                {
376                        uint j = 0;
377                        StringUtil::trim(*it);
378                        StringVector line = StringUtil::split(*it," ");
379                        if (line.size() != 3) break;
380                       
381                        for (StringVector::iterator jt = line.begin(); jt != line.end(); ++jt)
382                        {
383                                mMatrix[i][j] = StringConverter::parseReal(*jt);
384                                j++;
385                        }
386                        i++;
387                }
388        }
389
390        //-------------------------------------------------------------------------
391        Matrix3 ColladaTLookAt::getMatrix3(void) const
392        {
393                return mMatrix;
394        }
395
396        //-------------------------------------------------------------------------
397        Matrix4 ColladaTLookAt::getMatrix4(void) const
398        {
399                return Matrix4(getMatrix3());
400        }
401
402        //-------------------------------------------------------------------------
403        Vector3 ColladaTLookAt::getEye(void) const
404        {
405                return Vector3(mMatrix[0][0], mMatrix[0][1], mMatrix[0][2]);
406        }
407
408        //-------------------------------------------------------------------------
409        Vector3 ColladaTLookAt::getTarget(void) const
410        {
411                return Vector3(mMatrix[1][0], mMatrix[1][1], mMatrix[1][2]);
412        }
413
414        //-------------------------------------------------------------------------
415        Vector3 ColladaTLookAt::getUp(void) const
416        {
417                return Vector3(mMatrix[1][0], mMatrix[1][1], mMatrix[1][2]);
418        }
419
420        //-------------------------------------------------------------------------
421        // ColladaTMatrix
422        //-------------------------------------------------------------------------
423
424        //-------------------------------------------------------------------------
425        ColladaTMatrix::ColladaTMatrix(ColladaSceneNode *p) : ColladaTransform(p)
426        {
427                mMatrix = Matrix4::IDENTITY;
428        }
429
430        //-------------------------------------------------------------------------
431        ColladaTMatrix::~ColladaTMatrix(void) { }
432
433        //-------------------------------------------------------------------------
434        void ColladaTMatrix::doImport(xmlNode *node)
435        {
436                if (node == NULL) return;
437
438                String content = ColladaUtils::getContentDirect(node);
439                if (content.empty()) return;
440
441                StringVector lines = StringUtil::split(content,"\r\n");
442                if (lines.size() != 4) return;
443
444                uint i = 0;
445                for (StringVector::iterator it = lines.begin(); it != lines.end(); ++it)
446                {
447                        uint j = 0;
448                        StringUtil::trim(*it);
449                        StringVector line = StringUtil::split(*it," ");
450                        if (line.size() != 4) break;
451                       
452                        for (StringVector::iterator jt = line.begin(); jt != line.end(); ++jt)
453                        {
454                                mMatrix[i][j] = StringConverter::parseReal(*jt);
455                                j++;
456                        }
457                        i++;
458                }
459        }
460       
461        //-------------------------------------------------------------------------
462        Matrix4 ColladaTMatrix::getMatrix4(void) const
463        {
464                return mMatrix;
465        }
466
467        //-------------------------------------------------------------------------
468        // ColladaTPerspective
469        //-------------------------------------------------------------------------
470
471        //-------------------------------------------------------------------------
472        ColladaTPerspective::ColladaTPerspective(ColladaSceneNode *p) : ColladaTransform(p)
473        {
474                mFOV = 90;
475        }
476
477        //-------------------------------------------------------------------------
478        ColladaTPerspective::~ColladaTPerspective(void) { }
479
480        //-------------------------------------------------------------------------
481        void ColladaTPerspective::doImport(xmlNode *node)
482        {
483                if (node == NULL) return;
484
485                String content = ColladaUtils::getContentDirect(node);
486                if (content.empty()) return;
487
488                mFOV = StringConverter::parseReal(content);
489        }
490
491        //-------------------------------------------------------------------------
492        Matrix4 ColladaTPerspective::getMatrix4(void) const
493        {
494                return Matrix4::IDENTITY;
495        }
496
497        //-------------------------------------------------------------------------
498        // ColladaTRotate
499        //-------------------------------------------------------------------------
500
501        //-------------------------------------------------------------------------
502        ColladaTRotate::ColladaTRotate(ColladaSceneNode *p) : ColladaTransform(p)
503        {
504                mAxis = Vector3::ZERO;
505                mAngle = 0;
506        }
507
508        //-------------------------------------------------------------------------
509        ColladaTRotate::~ColladaTRotate(void) { }
510
511        //-------------------------------------------------------------------------
512        void ColladaTRotate::doImport(xmlNode *node)
513        {
514                if (node == NULL) return;
515
516                String content = ColladaUtils::getContentDirect(node);
517                if (content.empty()) return;
518
519                StringVector line = StringUtil::split(content," ");
520                if (line.size() != 4) return;
521
522                mAxis.x = StringConverter::parseReal(line.at(0));
523                mAxis.y = StringConverter::parseReal(line.at(1));
524                mAxis.z = StringConverter::parseReal(line.at(2));
525                mAngle  = StringConverter::parseReal(line.at(3));
526        }
527
528        //-------------------------------------------------------------------------
529        Matrix3 ColladaTRotate::getMatrix3(void) const
530        {
531                Matrix3 m = Matrix3::IDENTITY;
532                m.FromAxisAngle(mAxis, Radian(Math::DegreesToRadians(mAngle)));
533                return m;
534        }
535
536        //-------------------------------------------------------------------------
537        Matrix4 ColladaTRotate::getMatrix4(void) const
538        {
539                return Matrix4(getMatrix3());
540        }
541
542        //-------------------------------------------------------------------------
543        // ColladaTScale
544        //-------------------------------------------------------------------------
545
546        //-------------------------------------------------------------------------
547        ColladaTScale::ColladaTScale(ColladaSceneNode *p) : ColladaTransform(p)
548        {
549                mScale = Vector3::ZERO;
550        }
551
552        //-------------------------------------------------------------------------
553        ColladaTScale::~ColladaTScale(void) { }
554
555        //-------------------------------------------------------------------------
556        void ColladaTScale::doImport(xmlNode *node)
557        {
558                if (node == NULL) return;
559
560                String content = ColladaUtils::getContentDirect(node);
561                if (content.empty()) return;
562
563        mScale = StringConverter::parseVector3(content);
564        }
565
566        //-------------------------------------------------------------------------
567        Matrix3 ColladaTScale::getMatrix3(void) const
568        {
569                Matrix3 m = Matrix3::IDENTITY;
570               
571                m[0][0] = mScale.x;
572                m[1][1] = mScale.y;
573                m[2][2] = mScale.z;
574
575                return m;               
576        }
577
578        //-------------------------------------------------------------------------
579        Matrix4 ColladaTScale::getMatrix4(void) const
580        {
581                Matrix4 m = Matrix4::IDENTITY;
582                m.setScale(mScale);                     
583                return m;
584        }
585
586        //-------------------------------------------------------------------------
587        // ColladaTSkew
588        //-------------------------------------------------------------------------
589
590        //-------------------------------------------------------------------------
591        ColladaTSkew::ColladaTSkew(ColladaSceneNode *p) : ColladaTransform(p)
592        {
593                mAngle = 0;
594                mRotation = Vector3::ZERO;
595                mTranslation = Vector3::ZERO;
596        }
597
598        //-------------------------------------------------------------------------
599        ColladaTSkew::~ColladaTSkew(void) { }
600
601        //-------------------------------------------------------------------------
602        void ColladaTSkew::doImport(xmlNode *node)
603        {
604                if (node == NULL) return;
605
606                String content = ColladaUtils::getContentDirect(node);
607                if (content.empty()) return;
608
609                StringVector line = StringUtil::split(content," ");
610                if (line.size() != 7) return;
611
612                mAngle = StringConverter::parseReal(line.at(0));
613
614                mRotation.x = StringConverter::parseReal(line.at(1));
615                mRotation.y = StringConverter::parseReal(line.at(2));
616                mRotation.z = StringConverter::parseReal(line.at(3));
617
618                mTranslation.x = StringConverter::parseReal(line.at(4));
619                mTranslation.y = StringConverter::parseReal(line.at(5));
620                mTranslation.z = StringConverter::parseReal(line.at(6));
621        }
622
623        //-------------------------------------------------------------------------
624        Matrix3 ColladaTSkew::getMatrix3(void) const
625        {
626                return Matrix3::IDENTITY;
627        }
628
629        //-------------------------------------------------------------------------
630        Matrix4 ColladaTSkew::getMatrix4(void) const
631        {
632                return Matrix4(getMatrix3());
633        }
634
635        //-------------------------------------------------------------------------
636        // ColladaTTranslate
637        //-------------------------------------------------------------------------
638
639        //-------------------------------------------------------------------------
640        ColladaTTranslate::ColladaTTranslate(ColladaSceneNode *p) : ColladaTransform(p)
641        {
642                mTranslate = Vector3::ZERO;
643        }
644
645        //-------------------------------------------------------------------------
646        ColladaTTranslate::~ColladaTTranslate(void) { }
647
648        //-------------------------------------------------------------------------
649        void ColladaTTranslate::doImport(xmlNode *node)
650        {
651                if (node == NULL) return;
652
653                String content = ColladaUtils::getContentDirect(node);
654                if (content.empty()) return;
655
656                mTranslate = StringConverter::parseVector3(content);
657        }
658
659        //-------------------------------------------------------------------------
660        Matrix4 ColladaTTranslate::getMatrix4(void) const
661        {
662                Matrix4 m = Matrix4::IDENTITY;
663                m.makeTrans(mTranslate);
664                return m;
665        }
666}
Note: See TracBrowser for help on using the repository browser.