1 | // |
---|
2 | // Lol Engine |
---|
3 | // |
---|
4 | // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> |
---|
5 | // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> |
---|
6 | // This program is free software; you can redistribute it and/or |
---|
7 | // modify it under the terms of the Do What The Fuck You Want To |
---|
8 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
9 | // http://sam.zoy.org/projects/COPYING.WTFPL for more details. |
---|
10 | // |
---|
11 | |
---|
12 | // |
---|
13 | // The BulletCharacterController class |
---|
14 | // ------------------ |
---|
15 | // This class is a equivalent of btKinematicCharacterController, but more useful for Lol. |
---|
16 | // |
---|
17 | |
---|
18 | #if !defined __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ |
---|
19 | #define __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ |
---|
20 | |
---|
21 | #ifdef HAVE_PHYS_USE_BULLET
|
---|
22 | #include "core.h"
|
---|
23 | #include "EasyPhysics.h"
|
---|
24 | //#include "BulletDynamics\Character\btCharacterControllerInterface.h" |
---|
25 | #endif
|
---|
26 |
|
---|
27 | #define USE_LOL_CTRLR_CHARAC |
---|
28 | |
---|
29 | namespace lol |
---|
30 | { |
---|
31 | |
---|
32 | namespace phys |
---|
33 | { |
---|
34 | |
---|
35 | #ifdef USE_LOL_CTRLR_CHARAC |
---|
36 | #ifdef HAVE_PHYS_USE_BULLET |
---|
37 | |
---|
38 | ///BulletKinematicCharacterController is an object that supports a sliding motion in a world. |
---|
39 | ///It uses a ghost object and convex sweep test to test for upcoming collisions. This is combined with discrete collision detection to recover from penetrations. |
---|
40 | ///Interaction between btKinematicCharacterController and dynamic rigid bodies needs to be explicity implemented by the user. |
---|
41 | class BulletKinematicCharacterController : public btActionInterface |
---|
42 | { |
---|
43 | public: |
---|
44 | BulletKinematicCharacterController(btPairCachingGhostObject* NewGhostObject, btConvexShape* NewConvexShape, float NewStepHeight, int NewUpAxis=1) |
---|
45 | { |
---|
46 | m_convex_shape = NewConvexShape; |
---|
47 | m_up_axis = NewUpAxis; |
---|
48 | m_ghost_object = NewGhostObject; |
---|
49 | m_step_height = NewStepHeight; |
---|
50 | |
---|
51 | m_added_margin = 0.02f; |
---|
52 | m_walk_direction = vec3(.0f, .0f, .0f); |
---|
53 | m_do_gobject_sweep_test = true; |
---|
54 | m_turn_angle = .0f; |
---|
55 | m_use_walk_direction = false; // Should remove walk direction, this doesn't work correctly. |
---|
56 | m_velocity_time_interval = .0f; |
---|
57 | m_vertical_velocity = .0f; |
---|
58 | m_vertical_offset = .0f; |
---|
59 | m_gravity = 9.8f * 3.f; // 3G acceleration. |
---|
60 | m_fall_speed = 55.f; // Terminal velocity of a sky diver in m/s. |
---|
61 | m_jump_speed = 10.f; // ? |
---|
62 | m_was_on_ground = false; |
---|
63 | m_was_jumping = false; |
---|
64 | SetMaxSlope(45.f); |
---|
65 | } |
---|
66 | ~BulletKinematicCharacterController() { } |
---|
67 | |
---|
68 | protected: |
---|
69 | |
---|
70 | static vec3* GetUpAxisDirections() |
---|
71 | { |
---|
72 | static vec3 sUpAxisDirection[3] = { vec3(1.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec3(0.0f, 0.0f, 1.0f) }; |
---|
73 | |
---|
74 | return sUpAxisDirection; |
---|
75 | } |
---|
76 | |
---|
77 | //-------------------------- |
---|
78 | //CONVENIENCE FUNCTIONS |
---|
79 | //-- |
---|
80 | |
---|
81 | //Returns the reflection Direction of a ray going 'Direction' hitting a surface with Normal 'Normal' from: http://www-cs-students.stanford.edu/~adityagp/final/node3.html |
---|
82 | vec3 GetReflectedDir(const vec3& Direction, const vec3& Normal) |
---|
83 | { |
---|
84 | return Direction - (2.f * dot(Direction, Normal) * Normal); |
---|
85 | } |
---|
86 | //Returns the portion of 'direction' that is parallel to 'normal' |
---|
87 | vec3 ProjectDirOnNorm(const vec3& Direction, const vec3& Normal) |
---|
88 | { |
---|
89 | return Normal * dot(Direction, Normal); |
---|
90 | } |
---|
91 | //Returns the portion of 'Direction' that is perpindicular to 'Normal' |
---|
92 | vec3 ProjectDirOnNormPerpindicular(const vec3& Direction, const vec3& Normal) |
---|
93 | { |
---|
94 | return Direction - ProjectDirOnNorm(Direction, Normal); |
---|
95 | } |
---|
96 | //Returns Ghost Object. -duh- |
---|
97 | btPairCachingGhostObject* GetGhostObject() |
---|
98 | { |
---|
99 | return m_ghost_object; |
---|
100 | } |
---|
101 | |
---|
102 | //"Real" war functions |
---|
103 | bool RecoverFromPenetration(btCollisionWorld* CollisionWorld); |
---|
104 | void UpdateTargetOnHit(const vec3& hit_normal, float TangentMag = .0f, float NormalMag = 1.f); |
---|
105 | void StepUp(btCollisionWorld* CollisionWorld); |
---|
106 | void StepForwardAndStrafe(btCollisionWorld* CollisionWorld, const vec3& MoveStep); |
---|
107 | void StepDown(btCollisionWorld* CollisionWorld, float DeltaTime); |
---|
108 | |
---|
109 | public: |
---|
110 | ///btActionInterface interface : KEEP IN camelCase |
---|
111 | virtual void updateAction(btCollisionWorld* CollisionWorld, float deltaTime) |
---|
112 | { |
---|
113 | PreStep(CollisionWorld); |
---|
114 | PlayerStep(CollisionWorld, deltaTime); |
---|
115 | } |
---|
116 | |
---|
117 | //not in the interface, but called above |
---|
118 | void PreStep(btCollisionWorld* CollisionWorld); |
---|
119 | void PlayerStep(btCollisionWorld* CollisionWorld, float DeltaTime); |
---|
120 | |
---|
121 | ///btActionInterface interface : KEEP IN camelCase |
---|
122 | void debugDraw(btIDebugDraw* debugDrawer) { } |
---|
123 | |
---|
124 | void SetUpAxis(int NewAxis) |
---|
125 | { |
---|
126 | if (NewAxis < 0) |
---|
127 | NewAxis = 0; |
---|
128 | if (NewAxis > 2) |
---|
129 | NewAxis = 2; |
---|
130 | m_up_axis = NewAxis; |
---|
131 | } |
---|
132 | |
---|
133 | //!!!!!! SHOULD DITCH THAT !!!!!! |
---|
134 | //This should probably be called setPositionIncrementPerSimulatorStep. |
---|
135 | //This is neither a Direction nor a velocity, but the amount to |
---|
136 | //increment the position each simulation iteration, regardless |
---|
137 | //of DeltaTime. |
---|
138 | //This call will Reset any velocity set by SetVelocityForTimeInterval(). |
---|
139 | virtual void SetWalkDirection(const vec3& walkDirection) |
---|
140 | { |
---|
141 | m_use_walk_direction = true; |
---|
142 | m_walk_direction = walkDirection; |
---|
143 | m_normalized_direction = normalize(m_walk_direction); |
---|
144 | } |
---|
145 | |
---|
146 | //Caller provides a velocity with which the character should MoveStep for |
---|
147 | //the given time period. After the time period, velocity is Reset |
---|
148 | //to zero. |
---|
149 | //This call will Reset any walk Direction set by SetWalkDirection(). |
---|
150 | //Negative time intervals will result in no motion. |
---|
151 | virtual void SetVelocityForTimeInterval(const vec3& velocity, float timeInterval) |
---|
152 | { |
---|
153 | m_use_walk_direction = false; |
---|
154 | m_walk_direction = velocity; |
---|
155 | m_normalized_direction = normalize(m_walk_direction); |
---|
156 | m_velocity_time_interval = timeInterval; |
---|
157 | } |
---|
158 | |
---|
159 | //Usefulness ? |
---|
160 | void Reset() { } |
---|
161 | void Warp(const vec3& NewOrigin) |
---|
162 | { |
---|
163 | btTransform NewTransform; |
---|
164 | NewTransform.setIdentity(); |
---|
165 | NewTransform.setOrigin(LOL2BTU_VEC3(NewOrigin)); |
---|
166 | m_ghost_object->setWorldTransform(NewTransform); |
---|
167 | } |
---|
168 | |
---|
169 | //External Setup |
---|
170 | //-- |
---|
171 | |
---|
172 | void SetFallSpeed(float NewFallSpeed) { m_fall_speed = NewFallSpeed; } |
---|
173 | void SetJumpSpeed(float NewJumpSpeed) { m_jump_speed = NewJumpSpeed; } |
---|
174 | void SetMaxJumpHeight(float NewMaxJumpHeight) { m_max_jump_height = NewMaxJumpHeight; } |
---|
175 | |
---|
176 | //Jump logic will go in EasyCC |
---|
177 | bool CanJump() const { return OnGround(); } |
---|
178 | void Jump(); |
---|
179 | |
---|
180 | //NewGravity functions |
---|
181 | void SetGravity(float NewGravity) { m_gravity = NewGravity; } |
---|
182 | float GetGravity() const { return m_gravity; } |
---|
183 | |
---|
184 | //The max slope determines the maximum angle that the controller can walk up. |
---|
185 | //The slope angle is measured in radians. |
---|
186 | void SetMaxSlope(float NewSlopeRadians) { m_max_slope_radians = NewSlopeRadians; m_max_slope_cosine = lol::cos(NewSlopeRadians); } |
---|
187 | float GetMaxSlope() const { return m_max_slope_radians; } |
---|
188 | |
---|
189 | void SetUseGhostSweepTest(bool UseGObjectSweepTest) { m_do_gobject_sweep_test = UseGObjectSweepTest; } |
---|
190 | |
---|
191 | bool OnGround() const { return m_vertical_velocity == .0f && m_vertical_offset == .0f; } |
---|
192 | |
---|
193 | private: |
---|
194 | |
---|
195 | btPairCachingGhostObject* m_ghost_object; |
---|
196 | btConvexShape* m_convex_shape; //is also in m_ghost_object, but it needs to be convex, so we store it here to avoid upcast |
---|
197 | |
---|
198 | //keep track of the contact manifolds |
---|
199 | btManifoldArray m_manifold_array; |
---|
200 | |
---|
201 | float m_half_height; |
---|
202 | float m_velocity_time_interval; |
---|
203 | float m_vertical_velocity; |
---|
204 | float m_vertical_offset; |
---|
205 | float m_fall_speed; |
---|
206 | float m_jump_speed; |
---|
207 | float m_max_jump_height; |
---|
208 | float m_max_slope_radians; // Slope angle that is set (used for returning the exact value) |
---|
209 | float m_max_slope_cosine; // Cosine equivalent of m_max_slope_radians (calculated once when set, for optimization) |
---|
210 | float m_gravity; |
---|
211 | float m_turn_angle; |
---|
212 | float m_step_height; |
---|
213 | float m_added_margin;//@todo: remove this and fix the code |
---|
214 | |
---|
215 | ///this is the desired walk Direction, set by the user |
---|
216 | vec3 m_walk_direction; |
---|
217 | vec3 m_normalized_direction; |
---|
218 | |
---|
219 | //some internal variables |
---|
220 | vec3 m_current_position; |
---|
221 | float m_current_step_offset; |
---|
222 | vec3 m_target_position; |
---|
223 | |
---|
224 | vec3 m_touching_normal; |
---|
225 | bool m_touching_contact; |
---|
226 | |
---|
227 | bool m_was_on_ground; |
---|
228 | bool m_was_jumping; |
---|
229 | bool m_do_gobject_sweep_test; |
---|
230 | bool m_use_walk_direction; |
---|
231 | int m_up_axis; |
---|
232 | }; |
---|
233 | |
---|
234 | #endif // HAVE_PHYS_USE_BULLET |
---|
235 | #endif // USE_LOL_CTRLR_CHARAC |
---|
236 | |
---|
237 | } /* namespace phys */ |
---|
238 | |
---|
239 | } /* namespace lol */ |
---|
240 | |
---|
241 | #endif /* __BULLETCHARACTERCONTROLLER_BULLETCHARACTERCONTROLLER_H__ */ |
---|
242 | |
---|