AnnPlayerBody.cpp
Go to the documentation of this file.
1 // This is an open source non-commercial project. Dear PVS-Studio, please check it.
2 // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
3 
4 #include "AnnPlayerBody.hpp"
5 #include "AnnEngine.hpp"
6 #include "AnnLogger.hpp"
7 #include "AnnGetter.hpp"
8 
9 using namespace Annwvyn;
10 
13 
15  eyeHeight{ 1.59f },
16  walkSpeed{ 3 },
17  runFactor{ 3 },
18  turnSpeed{ 0.15f },
19  mass{ 80 },
20  FeetPosition{ 0, 0, 10 },
21  RoomBase{ FeetPosition },
22  HeadOrientation{ AnnQuaternion::IDENTITY },
23  Shape{ nullptr },
24  Body{ nullptr }
25 
26 {}
27 
29 {
30  AnnDebug() << "Creating player object";
31  locked = false;
32  run = false;
33 
34  walking[forward] = false;
35  walking[backward] = false;
36  walking[left] = false;
37  walking[right] = false;
38 
39  analogWalk = 0;
40  analogStraff = 0;
41  analogRotate = 0;
42 
43  standing = true;
44  updateTime = 0;
45  physics = false;
46 
47  setActuator<AnnDefaultPlayerActuator>();
48 
49  ignorePhysics = false;
50 
51  mouseSensitivity = 3;
52  contactWithGround = false;
53  RoomReferenceNode = nullptr;
55 
56  mode = UNKNOWN;
57 }
58 
60 {
61  actuator = std::move(act);
62 }
63 
65 {
66  return locked;
67 }
68 
70 {
71  physicsParams.FeetPosition = Position;
72 }
73 
75 {
76  physicsParams.Orientation = Orientation;
77 }
78 
80 {
81  Ogre::Euler e;
82  e.fromQuaternion(static_cast<Ogre::Quaternion>(Orientation));
84 }
85 
87 {
88  physicsParams.HeadOrientation = Orientation;
89 }
90 
91 void AnnPlayerBody::setEyesHeight(float eyeHeight)
92 {
93  if(!isLocked())
94  physicsParams.eyeHeight = eyeHeight;
95 }
96 
98 {
99  if(!isLocked())
100  physicsParams.walkSpeed = walk;
101 }
102 
104 {
105  if(!isLocked())
107 }
108 
109 void AnnPlayerBody::setMass(float mass)
110 {
111  physicsParams.mass = mass;
112 }
113 
114 void AnnPlayerBody::setShape(btCollisionShape* Shape)
115 {
116  if(!isLocked())
117  physicsParams.Shape = Shape;
118  physics = true;
119 }
120 
121 void AnnPlayerBody::setBody(btRigidBody* Body)
122 {
123  physicsParams.Body = Body;
124  physics = true;
125 }
126 
128 {
129  locked = true;
130 }
131 
133 {
134  locked = false;
135 }
136 
138 {
139  return physicsParams.walkSpeed;
140 }
141 
143 {
144  return physicsParams.eyeHeight;
145 }
146 
148 {
149  return getEyesHeight() * AnnVect3::UNIT_Y;
150 }
151 
153 {
154  return physicsParams.turnSpeed;
155 }
156 
158 {
159  return physicsParams.mass;
160 }
161 
162 btRigidBody* AnnPlayerBody::getBody() const
163 {
164  return physicsParams.Body;
165 }
166 
167 btCollisionShape* AnnPlayerBody::getShape() const
168 {
169  return physicsParams.Shape;
170 }
171 
173 {
175 }
176 
178 {
179  return physicsParams.Orientation;
180 }
181 
182 void AnnPlayerBody::applyRelativeBodyYaw(Ogre::Radian angle)
183 {
184  if(mode == STANDING)
186  else if(mode == ROOMSCALE)
187  {
188  //Projection of the headset world position on the ground plane. we are turning around this point.
189  AnnVect3 basePoint{
190  AnnGetVRRenderer()->trackedHeadPose.position.x,
192  AnnGetVRRenderer()->trackedHeadPose.position.z
193  };
194 
196  AnnVect3 displacement = physicsParams.RoomBase - basePoint;
197  physicsParams.RoomBase -= displacement;
198 
199  AnnQuaternion rotation(angle, AnnVect3::UNIT_Y);
200  displacement = rotation * displacement;
201  physicsParams.RoomBase += displacement;
202 
204  }
205 }
206 
208 {
209  relValue = int(relValue * mouseSensitivity);
210  applyRelativeBodyYaw(Ogre::Radian(-float(relValue) * getTurnSpeed() * updateTime));
211 }
212 
214 {
215  AnnVect3 translation(AnnVect3::ZERO);
216  if(walking[forward])
217  translation.z -= 1;
218  if(walking[backward])
219  translation.z += 1;
220  if(walking[left])
221  translation.x -= 1;
222  if(walking[right])
223  translation.x += 1;
224 
225  return translation.normalisedCopy();
226 }
227 
229 {
230  AnnVect3 translate(AnnVect3::ZERO);
231 
232  translate.x = analogStraff;
233  translate.z = analogWalk;
234 
235  return translate;
236 }
237 
239 {
240  //7 is the value that was more or less feeling good for me.
241  auto value = -7 * analogRotate * getTurnSpeed() * updateTime;
242  applyRelativeBodyYaw(Ogre::Radian(value));
243 }
244 
246 {
247  return physicsParams.runFactor;
248 }
249 
251 {
252  if(!hasPhysics()) return;
253  AnnDebug("Reset player's physics");
254 
255  //Remove the player's rigid-body from the world
256  AnnGetPhysicsEngine()->getWorld()->removeRigidBody(getBody());
257 
258  //We don't need that body anymore...
259  delete getBody();
260 
261  //prevent memory access to unallocated address
262  setBody(nullptr);
263 
264  //Put everything back in order
266  AnnGetPhysicsEngine()->createPlayerPhysicalVirtualBody(AnnGetEngine()->getPlayerPovNode());
267  AnnGetPhysicsEngine()->addPlayerPhysicalBodyToDynamicsWorld();
268 }
269 
270 void AnnPlayerBody::teleport(AnnVect3 position, AnnRadian orientation)
271 {
272  setPosition(position);
273  setOrientation(Ogre::Euler(orientation));
275 }
276 
278 {
279  teleport(position, this->getOrientation().getYaw());
280 }
281 
282 void AnnPlayerBody::engineUpdate(float deltaTime)
283 {
284  static AnnVect3 roomTranslation;
285  updateTime = deltaTime;
286  switch(mode)
287  {
288  case STANDING:
289  if(ignorePhysics) return;
290 
291  if(getBody())
292  {
293  applyAnalogYaw();
294  getBody()->activate();
295  }
296 
297  //Tell the actuator to "act" on the player
298  actuator->actuate(deltaTime);
299 
300  //get back position data from physics engine
301  if(getBody())
302  {
303  setPosition(AnnVect3(getBody()->getCenterOfMassPosition()) - AnnQuaternion(getBody()->getCenterOfMassTransform().getRotation()) * AnnVect3(0, getEyesHeight() / 2, 0));
304  }
305  break;
306 
307  case ROOMSCALE:
308  if(ignorePhysics) return;
309  applyAnalogYaw();
310 
312  roomTranslateQuatReference = AnnQuaternion{ AnnGetVRRenderer()->trackedHeadPose.orientation.getYaw(), AnnVect3::UNIT_Y };
313 
314  roomTranslation = updateTime * getWalkSpeed() *
315  //(physicsParams.Orientation.toQuaternion() *
317 
318  if(roomTranslation == AnnVect3::ZERO)
319  needNewRoomTranslateReference = true; //New base will be calculated at next frame
320  else
321  {
323  physicsParams.RoomBase += roomTranslation;
324  }
325 
327 
328  break;
329 
330  default: break;
331  }
332 }
333 
335 {
336  return physics;
337 }
338 
340 {
341  mode = playerMode;
342 }
343 
344 void AnnPlayerBody::setRoomRefNode(Ogre::SceneNode* node)
345 {
346  RoomReferenceNode = node;
347 }
348 
349 void AnnPlayerBody::reground(float YvalueForGround)
350 {
351  if(mode != ROOMSCALE) return;
352  physicsParams.FeetPosition.y = YvalueForGround;
353 
354  AnnDebug() << "Re-grounding to Y=" << YvalueForGround;
355 }
356 
358 {
359  reground(pointOnGround.y);
360 }
361 
362 void AnnPlayerBody::regroundOnPhysicsBody(float length, AnnVect3 preoffset)
363 {
364  if(mode != ROOMSCALE) return;
365  AnnVect3 rayOrigin{ physicsParams.FeetPosition + preoffset };
366  AnnVect3 rayEndPoint{ rayOrigin + length * AnnVect3::NEGATIVE_UNIT_Y };
367 
368  btCollisionWorld::ClosestRayResultCallback rayGroundingCallback(rayOrigin.getBtVector(),
369  rayEndPoint.getBtVector());
370 
371  AnnGetPhysicsEngine()->getWorld()->rayTest(rayOrigin.getBtVector(),
372  rayEndPoint.getBtVector(),
373  rayGroundingCallback);
374 
375  if(rayGroundingCallback.hasHit())
376  reground(rayGroundingCallback.m_hitPointWorld);
377 }
378 
380 {
382 }
383 
385 {
386  if(mode != ROOMSCALE) return;
387  if(physicsParams.Body)
388  {
389  btTransform transform;
390  auto pose = AnnGetVRRenderer()->trackedHeadPose;
391  transform.setOrigin(pose.position.getBtVector());
392  transform.setRotation(pose.orientation.getBtQuaternion());
393  physicsParams.Body->setAngularVelocity(btVector3(0, 0, 0));
394  physicsParams.Body->setLinearVelocity(btVector3(0, 0, 0));
395  physicsParams.Body->setWorldTransform(transform);
396  physicsParams.Body->activate(true);
397  }
398 }
bool contactWithGround
If there is contact with ground.
Ogre::Euler getOrientation() const
Get body orientation (Euler vector)
float getMass() const
Get mass in Kg.
bool isLocked() const
Permit to know if parameters are locked.
AnnEngine * AnnGetEngine()
Get the current instance of AnnEngine.
Definition: AnnGetter.cpp:10
void setShape(btCollisionShape *Shape)
void teleport(AnnVect3 position, AnnRadian orientation)
Teleport the player to the given location, and get it facing the given direction. ...
void reground(float YvalueForGround)
Put the reference point for the roomscale VR at Y altitude.
Ogre::SceneNode * RoomReferenceNode
Room reference node.
PhysicalParameters()
Constructor that handle the default body parameters.
void setBody(btRigidBody *Body)
PhysicalParameters physicsParams
Object that keep body parameters (= legacy structure)
void _hintRoomscaleUpdateTranslationReference()
Advanced : Set the flag that will update the translation reference vector from the head pose "view" d...
AnnVect3 getPosition() const
Get position vector.
void applyAnalogYaw()
Apply yaw from analog value.
void lockParameters()
Prevent modification of physical parameter.
float getWalkSpeed() const
Get walk-speed in meter/seconds.
Euler & yaw(Radian y)
Apply a relative yaw.
Definition: euler.h:155
AnnVect3 getAnalogTranslation() const
Get the translation from analog joystick value.
btRigidBody * getBody() const
Get rigid body.
A 3D Vector.
Definition: AnnVect3.hpp:16
void setWalkSpeed(float walkSpeed)
void setEyesHeight(float eyeHeight)
void setOrientation(Ogre::Euler Orientation)
bool run
Running state.
Namespace containing the totality of Annwvyn components.
Definition: AnnGetter.cpp:8
bool locked
The famous boolean that permit to prevent YOU for breaking my work! :D.
AnnOgreVRRendererPtr AnnGetVRRenderer()
Get the VR renderer.
Definition: AnnGetter.cpp:20
class that represent the player
void regroundOnPhysicsBody(float lenght=1000, AnnVect3 preoffset=AnnVect3::ZERO)
Shoot a ray form the player to relative -Y. If it hits a rigidbody, call reground() on the impact pos...
AnnQuaternion roomTranslateQuatReference
Reference for the translation of the room.
float getRunFactor() const
Get the ratio between walking and running speed.
void engineUpdate(float time)
Engine update call for each frame.
void setPosition(AnnVect3 Position)
Create a ostream to the Ogre logger.
void applyRelativeBodyYaw(Ogre::Radian angle)
An angle in Radian.
Definition: AnnAngle.hpp:22
bool ignorePhysics
Turning that off bypass the physics code. Cool for menu scene or weird manipulation of the player obj...
static const AnnVect3 DEFAULT_STARTING_POS
bool hasPhysics() const
Return true if physics has been initialized once.
std::unique_ptr< AnnPlayerActuator > actuator
PlayerActuator to use.
Represent a Quaternion.
Open an output stream to the engine log.
Definition: AnnLogger.hpp:24
void setHeadOrientation(AnnQuaternion HeadOrientation)
void setMass(float mass)
T move(T... args)
void syncPalyerPov() const
Set the POV node to the AnnPlayerBody gameplay defined position/orientation of the player&#39;s body...
Definition: AnnEngine.cpp:412
bool walking[4]
Waling state. Forward Backward Left Right.
Main Annwvyn Engine class Initialize the renderer and all subsystem. Provide access to all of the eng...
AnnPlayerBody()
Construct the player object.
AnnPhysicsEnginePtr AnnGetPhysicsEngine()
Get the physics engine.
Definition: AnnGetter.cpp:13
float getTurnSpeed() const
Get turn-speed in rad/seconds.
void setActuator(std::unique_ptr< AnnPlayerActuator > &&actuator)
Set the player actuator object.
float getEyesHeight() const
Get the distance between foot-plane and eyes in meters.
bool physics
Player body physics enabled.
void applyMouseRelativeRotation(int relValue)
btCollisionShape * getShape() const
Get Shape.
void syncToTrackedPose() const
Set the player body&#39;s pose to match what is tracked by the VR system, and cancel all velocities...
void setMode(AnnPlayerMode playerMode)
Set the player mode between standing and roomscale;.
bool needNewRoomTranslateReference
If true, will extract the yaw angle from the last head pose, and store it in roomTranslateQuatReferen...
void unlockParameters()
Give back the right to modify some parameters.
float updateTime
time length of the frame
bool standing
Boolean false if the player can get orientation transformation from.
Class for Euler rotations.
Definition: euler.h:25
AnnVect3 getTranslation()
Get the translation vector (normalized) from the walking state.
static const Ogre::Euler DEFAULT_STARTING_ORIENT
AnnVect3 getEyeTranslation() const
Get a vector that correspond to the translation between the feet point and the eyes.
void setTurnSpeed(float turnSpeed)
void setRoomRefNode(Ogre::SceneNode *node)
Register the room reference node.