ThingEntity.cpp

Go to the documentation of this file.
00001 /*
00002 SagaEngine library
00003 Copyright (c) 2002-2006 Skalden Studio AS
00004 
00005 This software is provided 'as-is', without any express or implied 
00006 warranty. In no event will the authors be held liable for any 
00007 damages arising from the use of this software.
00008 
00009 Permission is granted to distribute the library under the terms of the 
00010 Q Public License version 1.0. Be sure to read and understand the license
00011 before using the library. It should be included here, or you may read it
00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl
00013 
00014 The original version of this library can be located at:
00015 http://www.sagaengine.com/
00016 
00017 Rune Myrland
00018 rune@skalden.com
00019 */
00020 
00021 
00022 #include "ThingEntity.hpp"
00023 #include "ThingMOInfo.hpp"
00024 #include "all.hpp"
00025 #include "O3dPre.hpp"
00026 #include "../config/o3d_config.hpp"
00027 #include "../schema/O3dSchema.hpp"
00028 #include "o3d/schema/O3dSchema.hpp"
00029 #include "o3d/thing/all.hpp"
00030 #include "EntityUtil.hpp"
00031 #include "util/math/ScaleT.hpp"
00032 #include <OgreSceneManager.h>
00033 #include <OgreEntity.h>
00034 #include <OgreAnimation.h>
00035 #include <OgreSkeleton.h>
00036 #include <OgreSkeletonInstance.h>
00037 
00038 
00039 using namespace se_core;
00040 
00041 
00042 namespace se_ogre {
00043     ThingEntity
00044     ::ThingEntity(se_core::PosComponent& thing, const ThingMOInfo& info, const ThingMOFactory& factory)
00045         : ThingMO(thing, info, factory), entity_(0) {
00046 
00047         // Create a unique entity name
00048         char name[128];
00049         static int pool = 1000;
00050         //sprintf(name, "%d-%s", thing_.id(), thing_.name());
00051         sprintf(name, "%d-%s", ++pool, thing_.name());
00052 
00053         // Create entity
00054         Ogre::MovableObject* mo = O3dSchema::sceneManager->createMovableObject(name, Ogre::EntityFactory::FACTORY_TYPE_NAME, &info_.params_);
00055         node_->attachObject(mo);
00056         entity_ = static_cast<Ogre::Entity*>(mo);
00057         entity_->setNormaliseNormals(true);
00058         entity_->setCastShadows(info.isShadowCaster_);
00059         if(entity_->hasSkeleton()) {
00060             entity_->getSkeleton()->setBlendMode(Ogre::ANIMBLEND_CUMULATIVE);
00061         }
00062 
00063         // Get and set animation associated with this thing
00064         for(int i = 0; i < info_.channelCount(); ++i) {
00065             const short animId = thing_.pos().anim(i).movementMode();
00066             prevAnim_[i] = -1;
00067             state_[i] = 0;
00068             setAnimation(i, thing_.pos().anim(i));
00069         }
00070 
00071         // Get default material, if one
00072         const char* material = info_.defaultMaterial_.get();
00073         /*
00074         // Check if this movement mode has a special material
00075         if(a && !a->material_.isEmpty()) {
00076             const char* material = a->material_.get();
00077         }
00078         */
00079         // If material is defined (default or special), set it
00080         if(material) {
00081             setMaterial(material);
00082         }
00083 
00084         hasAnimation_ = true;
00085     }
00086 
00087 
00088     ThingEntity
00089     ::~ThingEntity() {
00090         if(O3dSchema::sceneManager)
00091             O3dSchema::sceneManager->destroyMovableObject(entity_);
00092         entity_ = 0;
00093     }
00094 
00095 
00096     void ThingEntity
00097     ::setAnimation(int channel, const se_core::Anim& anim) {
00098         const short animId = anim.movementMode();
00099         if(prevAnim_[channel] != animId) {
00100             prevAnim_[channel] = animId;
00101 
00102             if(state_[channel]) {
00103                 //state_[channel]->setEnabled(false);
00104                 state_[channel] = 0;
00105             }
00106             O3dAnimation* a = info_.animation(channel, animId);
00107             if(a && !a->name_.isEmpty()) {
00108                 // Set the animation state
00109                 AssertFatal(entity_->hasSkeleton() || entity_->hasVertexAnimation(), "Can't find skeleton or vertex animation for " << thing_.owner()->name());
00110                 AssertFatal(entity_->getAllAnimationStates()->hasAnimationState(a->name_.get()),
00111                         "Couldn't set up animation " << a->name_.get() << " for " << thing_.owner()->name());
00112                 state_[channel] = entity_->getAnimationState(a->name_.get());
00113 
00114                 // Enable looping
00115                 state_[channel]->setLoop(a->doLoop_);
00116 
00117                 // The anim speed of the mesh animation,
00118                 // multiplied by the anim speed of the things anim channel
00119                 float s = a->speed_;
00120                 if(s > 0) {
00121                     s = 1 / s;
00122                 }
00123                 speed_[channel] = s;
00124             }
00125         }
00126 
00127     }
00128 
00129 
00130     void ThingEntity
00131     ::setMaterial(const char* material) {
00132         entity_->setMaterialName(material);
00133     }
00134 
00135 
00136     void ThingEntity
00137     ::animate(long when, float stepDelta, float timeSinceLastFrame) {
00138         // Reset movement state, so that starting state is known
00139         for(int i = 0; i < info_.channelCount(); ++i) {
00140             if(state_[i]) {
00141                 state_[i]->setEnabled(false);
00142                 state_[i]->setWeight(0);
00143                 state_[i]->setTimePosition(0);
00144             }
00145         }
00146 
00147         for(int i = 0; i < info_.channelCount(); ++i) {
00148             const Anim& a = thing_.pos().anim(i);
00149             // Check if movement mode (and thus animation) has changed (ie walk to stand, etc)
00150             setAnimation(i, a);
00151 
00152             // Add passed time and update weight of animation
00153             if(state_[i]) {
00154                 const Anim& na = thing_.nextPos().anim(i);
00155 
00156                 float pos = ScaleT::toFloat(a.pos());
00157                 if(a.movementMode() == na.movementMode()) {
00158                     pos += stepDelta * (na.pos() - a.pos());
00159                 }
00160                 pos *= state_[i]->getLength() * speed_[i];
00161                 // If same state are in more channels, interpolate between their positions
00162                 if(a.weight() > 0) {
00163                     if(state_[i]->getEnabled()) {
00164                         // Using the same animation twice at once
00165                         //float cw = state_[i]->getWeight();
00166                         state_[i]->setWeight(1);
00167                         // Interpolate between the position of this use
00168                         // and the other use
00169                         float w = a.weight(); // / (a.weight() + cw);
00170                         float cp = fmod(state_[i]->getTimePosition(), state_[i]->getLength());
00171                         state_[i]->setTimePosition(cp + w * (fmod(pos, state_[i]->getLength()) - cp));
00172                     }
00173                     //Assert(!state_[i]->getEnabled() && "Using the same animation twice at once");
00174                     else {
00175                         state_[i]->setTimePosition(pos);
00176                         float w = a.weight();
00177                         if(a.movementMode() == na.movementMode()) {
00178                             w += stepDelta * (na.weight() - a.weight());
00179                         }
00180                         state_[i]->setWeight(w);
00181                         state_[i]->setEnabled(true);
00182                     }
00183                     //LogDetail(thing_.name() << ": " << state_[i]->getAnimationName().c_str() << ": " << w << " - " << stepDelta);
00184                 }
00185             }
00186         }
00187 
00188         /*
00189         // Get default material, if one
00190         const char* material = info_.defaultMaterial_.get();
00191 
00192         // Check if this movement mode has a special material
00193         if(a && !a->material_.isEmpty()) {
00194             const char* material = a->material_.get();
00195         }
00196         // If material is defined (default or special), set it
00197         if(material) {
00198         setMaterial(material);
00199         }
00200         */
00201     }
00202 
00203 
00204 }

Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:09 2007 by Doxygen version 1.3.9.1.

SourceForge.net Logo