Pos.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 "Pos.hpp"
00023 #include "Anim.hpp"
00024 #include "PosComponent.hpp"
00025 #include "../area/Area.hpp"
00026 #include "../sim.hpp"
00027 #include "../schema/SimSchema.hpp"
00028 #include "util/math/util_math.hpp"
00029 #include "util/math/all.hpp"
00030 #include <cstdio>
00031 #include <cstring>
00032 
00033 
00034 namespace se_core {
00035 
00036     Pos
00037     ::Pos() : area_(0)
00038             , parent_(0)
00039             , index_(-1)
00040             , isGrounded_(true)
00041     {
00042         anim(0).setWeight(1);
00043         local_.setIdentity();
00044         world_.setIdentity();
00045     }
00046 
00047 
00048     short Pos
00049     ::terrainStyle() const {
00050         if(!hasArea())
00051             return TS_VOID;
00052         const Area::Ptr a(area());
00053         return a->terrainStyle(this->localCoor(), index());
00054     }
00055 
00056     long Pos
00057     ::touchedTerrain() const {
00058         if(!hasArea())
00059             return TSM_VOID;
00060         const Area::Ptr a(area());
00061         return a->touchedTerrain(this->localCoor(), radius());
00062     }
00063 
00064 
00065     bool Pos
00066     ::isKeyFramePath(const Pos& other) const {
00067         // Check that both positions are inside an area
00068         if(!hasArea() || !other.hasArea())
00069             return false;
00070 
00071 
00072         // Normal success case. Eliminate quickly.
00073         if(area_ == other.area_)
00074             return true;
00075 
00076         // Are pages not neighbours?
00077         const Area::Ptr a(area());
00078         const Area::Ptr oth(other.area_);
00079         if(!(a->isNeighbour(*(oth))))
00080             return false;
00081 
00082         // All negative cases eliminated
00083         return true;
00084     }
00085 
00086     /*
00087     coor_world_t Pos
00088     ::pageDistanceSquared(const Pos& p) const {
00089         // Value returned if no legal path exists
00090         // TODO: Should perhaps be negative
00091         static const coor_world_t NO_PATH = -1;
00092 
00093         if(!hasArea() || !p.hasArea()) {
00094             // return error distance
00095             return NO_PATH;
00096         }
00097         if(!isKeyFramePath(p)) {
00098             // return error distance
00099             return NO_PATH;
00100         }
00101         coor_world_t fromX = (coor_world_t)p.area()->pagePosX()
00102             + (coor_world_t)p.localCoor().x_;
00103         coor_world_t toX = (coor_world_t)area()->pagePosX()
00104             + (coor_world_t)localCoor().x_;
00105 
00106         coor_world_t fromZ = ((coor_world_t)p.area()->pagePosZ()
00107                 + (coor_world_t)p.localCoor().z_);
00108         coor_world_t toZ = ((coor_world_t)area()->pagePosZ()
00109                 + (coor_world_t)localCoor().z_);
00110 
00111         coor_world_t xDist = fromX - toX;
00112         coor_world_t zDist = fromZ - toZ;
00113 
00114         //long xDist = (p.x_) - (x_);
00115         //long zDist = (p.z_) - (z_);
00116 
00117         coor_world_t xDistSquared = xDist * xDist;
00118         coor_world_t zDistSquared = zDist * zDist;
00119         coor_world_t distSquared = xDistSquared + zDistSquared;
00120 
00121 
00122 #       ifdef SE_FIXED_POINT
00123         // Overflowing distances are clamped down
00124         // to this legal distance
00125         static const coor_world_t OVERFLOWED = -2;
00126 
00127         // Prevent overflow
00128         if(xDist > 0x7fff || xDist < -0x7fff || zDist > 0x7fff || zDist < -0x7fff)
00129             // Return greatest legal distance
00130             return OVERFLOWED;
00131 
00132         // May overflow on adding xDistSquared and yDistSquared
00133         if(distSquared < 0)
00134             return OVERFLOWED;
00135 #       endif
00136 
00137         return distSquared;
00138     }
00139     */
00140 
00141 
00142     void Pos
00143     ::setPos(const Pos& original) {
00144         local_.setViewPoint(original.local_);
00145         world_.setViewPoint(original.world_);
00146         area_ = original.area_;
00147         parent_ = original.parent_;
00148         index_ = original.index_;
00149         isGrounded_ = original.isGrounded_;
00150         bounds_ = original.bounds_;
00151         for(int i = 0; i < MAX_ANIMS; ++i)
00152             anim_[i] = original.anim_[i];
00153     }
00154 
00155 
00156     void Pos
00157     ::swapAnims(int a, int b) {
00158         Anim tmp(anim_[a]);
00159         anim_[a] = anim_[b];
00160         anim_[b] = tmp;
00161     }
00162 
00163     void Pos
00164     ::setXZ(const Pos& original) {
00165         // Revert coordinates in xz plane. (Can still fall.)
00166         localCoor().x_ = original.localCoor().x_;
00167         localCoor().z_ = original.localCoor().z_;
00168         worldCoor().x_ = original.worldCoor().x_;
00169         worldCoor().z_ = original.worldCoor().z_;
00170         area_ = original.area_;
00171     }
00172 
00173 
00174     void Pos
00175     ::resetParent(bool doKeepWorldCoor) {
00176         parent_ = area_;
00177 
00178         if(doKeepWorldCoor) {
00179             local_.setViewPoint(world_);
00180         }
00181         else {
00182             world_.setViewPoint(local_);
00183         }
00184     }
00185 
00186 
00187     bool Pos
00188     ::didParentMove() const {
00189         return parent_ != 0 && parent_->didMove();
00190     }
00191 
00192 
00193     void Pos
00194     ::setParent(PosComponent& p, bool doKeepWorldCoor) {
00195         parent_ = &p;
00196         if(doKeepWorldCoor) {
00197             local_.setViewPoint(world_);
00198             local_.sub(p.nextPos().world_);
00199         }
00200     }
00201 
00202 
00203     void Pos
00204     ::setArea(PosComponent& area, bool doKeepWorldCoor) {
00205         //LogDetail(area.name());
00206         if(parent_ == area_) {
00207             // Area is the root parent node
00208             setParent(area, doKeepWorldCoor);
00209             //parent_ = &area;
00210         }
00211         area_ = &area;
00212         updateIndex();
00213     }
00214 
00215 
00216     void Pos
00217     ::setArea(PosComponent& area, const ViewPoint& vp, bool isLocalViewPoint) {
00218         if(parent_ == area_) {
00219             // Area is the root parent node
00220             parent_ = &area;
00221         }
00222         area_ = &area;
00223         if(isLocalViewPoint) {
00224             local_.setViewPoint(vp);
00225             updateWorldViewPoint();
00226         }
00227         else {
00228             world_.setViewPoint(vp);
00229             updateLocalViewPoint();
00230         }
00231         updateIndex();
00232     }
00233 
00234 
00235     bool Pos
00236     ::hasArea(Composite& area) const {
00237         return area_ != 0 && area_->owner() == &area; 
00238     }
00239 
00240 
00241     bool Pos
00242     ::hasArea(Component& area) const {
00243         return area_ != 0 && area_->owner() == area.owner(); 
00244     }
00245 
00246 
00247     PosComponent* Pos
00248     ::updateArea() {
00249         // Entered new area?
00250         Area::Ptr next(area_);
00251         if(!next->isLegalWorldCoor(worldCoor())) {
00252             Area* a = next->neighbour(worldCoor());
00253             if(a) {
00254                 // Change area, keep world viewpoint
00255                 setArea(*PosComponent::get(*a), true);
00256                 next = a;
00257                 // Cannot use old index as hint for index in new area
00258                 setNoIndex();
00259             }
00260         }
00261 
00262         // Calc navigation mesh triangle id
00263         short newIndex = next->index(worldCoor(), index());
00264         setIndex(newIndex);
00265         return area_;
00266     }
00267 
00268 
00269     void Pos
00270     ::updateIndex() {
00271         Area::Ptr next(area_);
00272         short newIndex = next->index(worldCoor(), -1);
00273         setIndex(newIndex);
00274     }
00275 
00276 
00277     void Pos
00278     ::resetArea() {
00279         if(parent_ == area_) {
00280             parent_ = 0;
00281         }
00282         area_ = 0;
00283     }
00284 
00285 
00286     void Pos
00287     ::updateWorldViewPoint() {
00288         world_.setViewPoint(local_);
00289         if(hasParent()) {
00290             // Parent should already have updated their worldViewPoint
00291             world_.add( parent()->nextPos().world_ );
00292         }
00293     }
00294 
00295 
00296     void Pos
00297     ::areaCoor(const PosComponent& a, Point3& dest) const {
00298         dest.set( world_.coor_ );
00299         Assert(a.nextPos().worldFace().isIdentity());
00300         dest.sub( a.nextPos().world_.coor_ );
00301     }
00302 
00303 
00304     void Pos
00305     ::areaFace(const PosComponent& a, Euler3& dest) const {
00306         dest.set( world_.face_ );
00307         Assert(a.nextPos().worldFace().isIdentity());
00308         dest.sub( a.nextPos().world_.face_ );
00309     }
00310 
00311 
00312     void Pos
00313     ::areaViewPoint(const PosComponent& a, ViewPoint& dest) const {
00314         dest.setViewPoint(world_);
00315         dest.sub( a.nextPos().world_ );
00316     }
00317 
00318     void Pos
00319     ::updateLocalViewPoint() {
00320         local_.setViewPoint(world_);
00321         if(hasParent()) {
00322             // Parent should already have updated their worldViewPoint
00323             local_.sub( parent()->nextPos().world_ );
00324         }
00325     }
00326 
00327 
00328     bool Pos
00329     ::isInsideCollisionRange(const Pos& p) const {
00330         coor_double_t collisionRange = p.radius() + radius();
00331         return collisionRange * collisionRange >= worldCoor().distanceSquared(p.worldCoor());
00332     }
00333 
00334 
00335     bool Pos
00336     ::isInsideCollisionRangeLinf(const Pos& p) const {
00337         coor_t collisionRange = p.radius() + radius();
00338         return worldCoor().xzDistanceLinf(p.worldCoor()) <= collisionRange;
00339     }
00340 
00341 
00342     bool Pos
00343     ::hasInFront(const Point3& coor) const {
00344         // TODO:
00345         LogFatal("TODO:");
00346         return false; // (xzFaceAwayAngle(coor) < (BrayT::DEG180 >> 1));
00347     }
00348 
00349 
00350     void Pos
00351     ::updateY() {
00352         if(isGrounded() && area_) {
00353             const Area::Ptr a(area());
00354             localCoor().y_ = a->groundHeight(localCoor(), index_);
00355         }
00356     }
00357 
00358 }

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

SourceForge.net Logo