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.