PhDefault.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 "PhDefault.hpp"
00023 #include "../area/Area.hpp"
00024 #include "../stat/all.hpp"
00025 #include "util/math/all.hpp"
00026 
00027 
00028 namespace se_core {
00029     const PhDefault physicsDefault;
00030 
00031     const Vector3 PhDefault
00032     ::GRAVITY(0, -1.25f * COOR_STEP, 0);
00033 
00034     void PhDefault
00035     ::calcNext(const PhysicsComponent& physics
00036             , const Pos& pos
00037             , Pos& nextPos
00038             , const Move& move
00039             , Move& nextMove
00040             ) const {
00041 
00042         // Are physics meaningful at all?
00043         if(!pos.isKeyFramePath(nextPos)) {
00044             // If not skip it
00045             return;
00046         } 
00047 
00048         // Blend animations
00049         blendAnims(pos, nextPos);
00050 
00051         // Update forces
00052         updateForces( nextMove );
00053 
00054         // Friction
00055         applyFriction(nextMove);
00056 
00057         // Calc nextMove
00058         applyForces( pos, nextPos, move, nextMove);
00059 
00060         // Entered new area?
00061         //PosComponent* old = nextPos.area();
00062         nextPos.updateArea();
00063 
00064         // Check if blocked
00065         if(isBlocked(physics, pos, nextPos)) {
00066             // Revert back to original area if necessary
00067             blocked(physics, pos, nextPos, move, nextMove);
00068         }
00069 
00070         // Ground height at present position
00071         clampToGround(pos, nextPos, nextMove);
00072     }
00073 
00074 
00075     bool PhDefault
00076     ::isBlocked(const PhysicsComponent& physics, const Pos& pos, Pos& nextPos) const {
00077         if(!nextPos.hasIndex()) {
00078             return true;
00079         }
00080 
00081         /* Fails if y is below ground
00082         if(!nextPos.area()->nextPos().hasInside(nextPos.worldCoor())) {
00083             return true;
00084         }
00085         */
00086 
00087         short to = nextPos.terrainStyle();
00088         if(to == 0) {
00089             return true;
00090         }
00091 
00092         return false;
00093     }
00094 
00095 
00096     void PhDefault
00097     ::blocked(const PhysicsComponent& physics
00098             , const Pos& pos
00099             , Pos& nextPos
00100             , const Move& move
00101             , Move& nextMove
00102             ) const {
00103         /*
00104         // Bounce in wall
00105         const NavMeshArea* area = static_cast<const NavMeshArea*>(pos.area()->owner());
00106         bray_t slideYaw = area->wallAngle(pos, nextPos.worldCoor());
00107         bray_t d = nextMove.velocity_.yaw();
00108         coor_t speed = nextMove.velocity_.length();
00109 
00110         d = BrayT::sub(d, slideYaw);
00111         coor_t speedAfter = Trig::sinScale(speed, BrayT::abs(d));
00112         d = BrayT::sub(slideYaw, d);
00113 
00114         Vector3 v, accel;
00115         v.setForward(speedAfter, d);
00116         accel.sub(v, nextMove.velocity_);
00117 
00118         // Don't get stuck in corners
00119         if(physics.didMove()) {
00120             v.scale(nextMove.bounceMaintain_);
00121         }
00122         nextMove.velocity_.set(v);
00123         */
00124 
00125         revertXZ(pos, nextPos);
00126     }
00127 
00128 
00129     void PhDefault
00130     ::blendAnims(const Pos& pos
00131             , Pos& nextPos
00132             ) const {
00133 
00134         // Blend animations
00135         nextPos.anim(2).updatePos();
00136         nextPos.anim(3).updatePos();
00137         scale_t w = nextPos.anim(2).weight();
00138         if(w != 1) {
00139             w += 4 * SCALE_STEP;
00140             if(w > 1) w = 1;
00141             nextPos.anim(2).setWeight(w);
00142             nextPos.anim(3).setWeight(1 - w);
00143         }
00144 
00145         // Blend animations
00146         nextPos.anim(0).updatePos();
00147         nextPos.anim(1).updatePos();
00148         w = nextPos.anim(0).weight();
00149         if(w != 1) {
00150             w += 4 * SCALE_STEP;
00151             if(w > 1) w = 1;
00152             nextPos.anim(0).setWeight(w);
00153             nextPos.anim(1).setWeight(1 - w);
00154         }
00155 
00156     }
00157 
00158     void PhDefault
00159     ::revertXZ(const Pos& pos
00160             , Pos& nextPos
00161             ) const {
00162         PosComponent* old = const_cast<PosComponent*>(pos.area());
00163         if(nextPos.area() != old) {
00164             nextPos.setArea(*old, false);
00165         }
00166         // Revert coordinates in xz plane. (Can still fall.)
00167         nextPos.localCoor().x_ = pos.localCoor().x_;
00168         nextPos.localCoor().z_ = pos.localCoor().z_;
00169         nextPos.worldCoor().x_ = pos.worldCoor().x_;
00170         nextPos.worldCoor().z_ = pos.worldCoor().z_;
00171         // The previous index is valid again
00172         nextPos.index_ = pos.index_;
00173     }
00174 
00175 
00176     void PhDefault
00177     ::updateForces(Move& nextMove) const {
00178         // Update forces
00179         nextMove.velocity_.add( nextMove.force_ );
00180         nextMove.angularVelocity_.rotate( nextMove.torque_ );
00181     }
00182 
00183 
00184     void PhDefault
00185     ::applyFriction(Move& nextMove) const {
00186         // Apply friction
00187         nextMove.angularVelocity_.scale(1 - nextMove.angularFriction_);
00188 
00189         /* Friction increasion proportionally with speed.
00190         nextMove.velocity_.scale(nextMove.friction_);
00191 
00192         const coor_double_t threshold = CoorT::pow2(nextMove.threshold_);
00193         if(nextMove.velocity_.xzLengthSquared() < threshold) {
00194             nextMove.velocity_.x_ = 0;
00195             nextMove.velocity_.z_ = 0;
00196         }
00197         */
00198 
00199         if(nextMove.didBounce_) {
00200             nextMove.velocity_.scale(nextMove.bounceMaintain_);
00201         }
00202 
00203         // Linear friction
00204         if(!nextMove.velocity_.isZero() && nextMove.linearFriction_ != 0) {
00205             Vector3 friction(nextMove.velocity_);
00206             friction.y_ = 0;
00207             if(!friction.isZero()) {
00208                 friction.normalize();
00209                 friction.scale(-nextMove.linearFriction_);
00210             }
00211             if(friction.xzLengthSquared() < nextMove.velocity().xzLengthSquared()) {
00212                 nextMove.velocity_.add(friction);
00213             }
00214             else {
00215                 nextMove.velocity_.x_ = 0;
00216                 nextMove.velocity_.z_ = 0;
00217             }
00218         }
00219     }
00220 
00221 
00222     void PhDefault
00223     ::applyForces(const Pos& pos
00224             , Pos& nextPos
00225             , const Move& move
00226             , Move& nextMove
00227             ) const {
00228         // Apply forces
00229         nextPos.localCoor().add(nextMove.velocity_);
00230         nextPos.localFace().rotate( nextMove.angularVelocity_ );
00231 
00232         nextPos.updateWorldViewPoint();
00233     }
00234 
00235 
00236     void PhDefault
00237     ::clampToGround(const Pos& pos
00238             , Pos& nextPos
00239             , Move& nextMove
00240             ) const {
00241         // Ground height at present position
00242         Area::Ptr nextArea(nextPos.area());
00243         coor_t gh = nextArea->groundHeight(nextPos.localCoor(), nextPos.index());
00244         // If below ground, then make grounded
00245         nextPos.setGrounded(gh >= nextPos.localCoor().y_);
00246 
00247         // Clamp the character to the ground if grounded
00248         if(nextPos.isGrounded()) {
00249             nextPos.worldCoor().y_ = gh;
00250             nextMove.velocity_.y_ = 0;
00251         }
00252 
00253         nextPos.updateLocalViewPoint();
00254     }
00255 
00256 
00257 }

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