Add animation smoothing
This commit is contained in:
parent
e3d0b3219f
commit
03b703d454
5 changed files with 326 additions and 182 deletions
170
racing.h
170
racing.h
|
@ -5,16 +5,16 @@
|
|||
#ifndef _LCR_RACING_H
|
||||
#define _LCR_RACING_H
|
||||
|
||||
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
||||
typedef int32_t LCR_GameUnit; ///< abstract game unit
|
||||
|
||||
#define LCR_GAME_UNIT 1024 ///< length of map square in LCR_GameUnits
|
||||
#define LCR_GAME_UNIT 1024 ///< length of map square in LCR_GameUnits
|
||||
|
||||
#define LCR_RACING_INPUT_FORW 0x01
|
||||
#define LCR_RACING_INPUT_RIGHT 0x02
|
||||
#define LCR_RACING_INPUT_BACK 0x04
|
||||
#define LCR_RACING_INPUT_LEFT 0x08
|
||||
|
||||
#define LCR_PHYSICS_UNIT 1024 ///< length of map square for physics engine
|
||||
#define LCR_PHYSICS_UNIT 512 ///< length of map square for physics engine
|
||||
|
||||
#include "map.h"
|
||||
#include "tinyphysicsengine.h"
|
||||
|
@ -22,15 +22,35 @@ typedef int32_t LCR_GameUnit; ///< abstract game unit
|
|||
#define LCR_CAR_JOINTS 5
|
||||
#define LCR_CAR_CONNECTIONS 10
|
||||
|
||||
#define LCR_CAR_FORWARD_FRICTION (TPE_F / 14)
|
||||
#define LCR_CAR_TURN_FRICTION (3 * TPE_F / 4)
|
||||
#define LCR_CAR_ELASTICITY (TPE_F / 100)
|
||||
|
||||
struct
|
||||
{
|
||||
TPE_World physicsWorld;
|
||||
TPE_Body carBody;
|
||||
TPE_Joint carJoints[LCR_CAR_JOINTS];
|
||||
TPE_Connection carConnections[LCR_CAR_CONNECTIONS];
|
||||
uint8_t wheelCollisions; /**< In individual bits records for each car wheel
|
||||
whether it's currently touching the ground.
|
||||
Lower bits record current collisions, higher
|
||||
bits the previous state (for averaging). */
|
||||
|
||||
|
||||
TPE_Vec3 carPositions[2]; ///* Current and previous position.
|
||||
|
||||
} LCR_racing;
|
||||
|
||||
TPE_Vec3 LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
||||
TPE_Vec3 _LCR_TPE_vec3DividePlain(TPE_Vec3 v, TPE_Unit d)
|
||||
{
|
||||
v.x /= d;
|
||||
v.y /= d;
|
||||
v.z /= d;
|
||||
return v;
|
||||
}
|
||||
|
||||
TPE_Vec3 _LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
||||
{
|
||||
return TPE_envAABoxInside(point,TPE_vec3(0,0,0),TPE_vec3(
|
||||
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS,
|
||||
|
@ -38,6 +58,31 @@ TPE_Vec3 LCR_racingEnvironmentFunction(TPE_Vec3 point, TPE_Unit maxDist)
|
|||
LCR_PHYSICS_UNIT * LCR_MAP_SIZE_BLOCKS));
|
||||
}
|
||||
|
||||
uint8_t _LCR_racingCollisionHandler(uint16_t b1, uint16_t j1, uint16_t b2,
|
||||
uint16_t j2, TPE_Vec3 p)
|
||||
{
|
||||
// check which wheels are touching the ground.
|
||||
|
||||
if (j1 < 4) // wheel joint?
|
||||
LCR_racing.wheelCollisions |= 0x01 << j1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes new run.
|
||||
*/
|
||||
void LCR_racingRestart(void)
|
||||
{
|
||||
LCR_racing.wheelCollisions = 0;
|
||||
TPE_bodyDeactivate(&(LCR_racing.carBody));
|
||||
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
Initializes the racing module, only call once.
|
||||
*/
|
||||
void LCR_racingInit(void)
|
||||
{
|
||||
LCR_log("initializing racing engine");
|
||||
|
@ -49,42 +94,57 @@ void LCR_racingInit(void)
|
|||
(LCR_PHYSICS_UNIT * 3) / 4,
|
||||
LCR_PHYSICS_UNIT / 8);
|
||||
|
||||
LCR_racing.carJoints[4].position.y += LCR_PHYSICS_UNIT / 8;
|
||||
LCR_racing.carJoints[4].position.y += LCR_PHYSICS_UNIT / 6;
|
||||
LCR_racing.carJoints[4].sizeDivided *= 3;
|
||||
LCR_racing.carJoints[4].sizeDivided /= 2;
|
||||
|
||||
TPE_bodyInit(&(LCR_racing.carBody),
|
||||
LCR_racing.carJoints,LCR_CAR_JOINTS,
|
||||
LCR_racing.carConnections,LCR_CAR_CONNECTIONS,
|
||||
TPE_FRACTIONS_PER_UNIT);
|
||||
TPE_F);
|
||||
|
||||
LCR_racing.carBody.friction = LCR_CAR_FORWARD_FRICTION;
|
||||
LCR_racing.carBody.elasticity = LCR_CAR_ELASTICITY;
|
||||
|
||||
TPE_worldInit(&(LCR_racing.physicsWorld),
|
||||
&(LCR_racing.carBody),1,LCR_racingEnvironmentFunction);
|
||||
&(LCR_racing.carBody),1,_LCR_racingEnvironmentFunction);
|
||||
|
||||
TPE_bodyDeactivate(&(LCR_racing.carBody));
|
||||
LCR_racing.physicsWorld.collisionCallback = _LCR_racingCollisionHandler;
|
||||
|
||||
LCR_racingRestart();
|
||||
}
|
||||
|
||||
void LCR_racingGetCarTransform(LCR_GameUnit position[3],
|
||||
LCR_GameUnit rotation[3])
|
||||
LCR_GameUnit rotation[3], LCR_GameUnit interpolationParam)
|
||||
{
|
||||
#define AVERAGE(c) \
|
||||
(((((LCR_racing.carBody.joints[0].position.c + \
|
||||
LCR_racing.carBody.joints[1].position.c + \
|
||||
LCR_racing.carBody.joints[2].position.c + \
|
||||
LCR_racing.carBody.joints[3].position.c) / 4) + \
|
||||
LCR_racing.carBody.joints[4].position.c) / 2) * \
|
||||
LCR_GAME_UNIT) / LCR_PHYSICS_UNIT
|
||||
|
||||
position[0] = AVERAGE(x);
|
||||
position[1] = AVERAGE(y);
|
||||
position[2] = AVERAGE(z);
|
||||
#undef AVERAGE
|
||||
#if LCR_SETTING_SMOOTH_ANIMATIONS
|
||||
TPE_Vec3 v = TPE_vec3Plus(
|
||||
LCR_racing.carPositions[1],
|
||||
_LCR_TPE_vec3DividePlain(
|
||||
TPE_vec3TimesPlain(
|
||||
TPE_vec3Minus(
|
||||
LCR_racing.carPositions[0],LCR_racing.carPositions[1]),
|
||||
interpolationParam),LCR_GAME_UNIT));
|
||||
|
||||
TPE_Vec3 rot = TPE_bodyGetRotation(&(LCR_racing.carBody),0,2,1);
|
||||
position[0] = v.x;
|
||||
position[1] = v.y;
|
||||
position[2] = v.z;
|
||||
#else
|
||||
TPE_Vec3 v;
|
||||
|
||||
rotation[0] = (rot.x * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
|
||||
rotation[1] = (rot.y * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
|
||||
rotation[2] = (rot.z * LCR_GAME_UNIT) / TPE_FRACTIONS_PER_UNIT;
|
||||
position[0] = LCR_racing.carPositions[0].x;
|
||||
position[1] = LCR_racing.carPositions[0].y;
|
||||
position[2] = LCR_racing.carPositions[0].z;
|
||||
#endif
|
||||
|
||||
v = TPE_bodyGetRotation(&(LCR_racing.carBody),0,2,1);
|
||||
|
||||
rotation[0] = (v.x * LCR_GAME_UNIT) / TPE_F;
|
||||
rotation[1] = (v.y * LCR_GAME_UNIT) / TPE_F;
|
||||
rotation[2] = (v.z * LCR_GAME_UNIT) / TPE_F;
|
||||
|
||||
// TODO: also smooth out rotation?
|
||||
}
|
||||
|
||||
void _LCR_drawPhysicsDebugPixel(uint16_t x, uint16_t y, uint8_t color)
|
||||
|
@ -100,18 +160,24 @@ void _LCR_drawPhysicsDebugPixel(uint16_t x, uint16_t y, uint8_t color)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: input
|
||||
int LCR_racingCarWheelTouchesGround(int wheel)
|
||||
{
|
||||
return ((LCR_racing.wheelCollisions & (LCR_racing.wheelCollisions >> 4))
|
||||
>> wheel) & 0x01;
|
||||
}
|
||||
|
||||
void LCR_racingStep(unsigned int input)
|
||||
{
|
||||
TPE_Vec3 carForw, carRight, carUp;
|
||||
TPE_Vec3 vel = TPE_vec3(0,0,0);
|
||||
|
||||
if (input)
|
||||
{
|
||||
if (input & LCR_RACING_INPUT_FORW)
|
||||
vel.z = LCR_PHYSICS_UNIT / 32;
|
||||
vel.y = LCR_PHYSICS_UNIT / 8;
|
||||
|
||||
if (input & LCR_RACING_INPUT_BACK)
|
||||
vel.y = LCR_PHYSICS_UNIT / 32;
|
||||
vel.z = LCR_PHYSICS_UNIT / 32;
|
||||
|
||||
if (input & LCR_RACING_INPUT_RIGHT)
|
||||
vel.x = LCR_PHYSICS_UNIT / 32;
|
||||
|
@ -123,10 +189,52 @@ void LCR_racingStep(unsigned int input)
|
|||
}
|
||||
|
||||
TPE_bodyApplyGravity(&(LCR_racing.carBody),
|
||||
TPE_FRACTIONS_PER_UNIT / 32
|
||||
TPE_F / 32
|
||||
);
|
||||
|
||||
LCR_racing.wheelCollisions <<= 4;
|
||||
TPE_worldStep(&(LCR_racing.physicsWorld));
|
||||
|
||||
carForw = TPE_vec3Normalized(TPE_vec3Plus(
|
||||
TPE_vec3Minus(LCR_racing.carBody.joints[2].position,
|
||||
LCR_racing.carBody.joints[0].position),
|
||||
TPE_vec3Minus(LCR_racing.carBody.joints[3].position,
|
||||
LCR_racing.carBody.joints[1].position)));
|
||||
|
||||
carRight = TPE_vec3Normalized(TPE_vec3Plus(
|
||||
TPE_vec3Minus(LCR_racing.carBody.joints[1].position,
|
||||
LCR_racing.carBody.joints[0].position),
|
||||
TPE_vec3Minus(LCR_racing.carBody.joints[3].position,
|
||||
LCR_racing.carBody.joints[2].position)));
|
||||
|
||||
carUp = TPE_vec3Cross(carForw,carRight);
|
||||
|
||||
if (TPE_vec3Dot(carUp,TPE_vec3Minus(LCR_racing.carBody.joints[4].position,
|
||||
LCR_racing.carBody.joints[0].position)) < 0)
|
||||
{
|
||||
/* if the car falls on its roof the center joint may flip to the other
|
||||
side, here we fix it */
|
||||
|
||||
// LCR_log("car flipped over, fixing");
|
||||
|
||||
LCR_racing.carBody.joints[4].position = TPE_vec3Plus(TPE_vec3Times(carUp,
|
||||
LCR_GAME_UNIT / 4),LCR_racing.carBody.joints[4].position);
|
||||
}
|
||||
|
||||
LCR_racing.carPositions[1] = LCR_racing.carPositions[0];
|
||||
|
||||
#define AVERAGE(c) \
|
||||
(((((LCR_racing.carBody.joints[0].position.c + \
|
||||
LCR_racing.carBody.joints[1].position.c + \
|
||||
LCR_racing.carBody.joints[2].position.c + \
|
||||
LCR_racing.carBody.joints[3].position.c) / 4) + \
|
||||
LCR_racing.carBody.joints[4].position.c) / 2) * \
|
||||
LCR_GAME_UNIT) / LCR_PHYSICS_UNIT
|
||||
|
||||
LCR_racing.carPositions[0].x = AVERAGE(x);
|
||||
LCR_racing.carPositions[0].y = AVERAGE(y);
|
||||
LCR_racing.carPositions[0].z = AVERAGE(z);
|
||||
#undef AVERAGE
|
||||
}
|
||||
|
||||
void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
||||
|
@ -138,13 +246,13 @@ void LCR_physicsDebugDraw(LCR_GameUnit camPos[3], LCR_GameUnit camRot[2],
|
|||
cPos.y = (camPos[1] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
||||
cPos.z = (camPos[2] * LCR_PHYSICS_UNIT) / LCR_GAME_UNIT;
|
||||
|
||||
cRot.x = (camRot[0] * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
||||
cRot.y = (camRot[1] * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
||||
cRot.x = (camRot[0] * TPE_F) / LCR_GAME_UNIT;
|
||||
cRot.y = (camRot[1] * TPE_F) / LCR_GAME_UNIT;
|
||||
cRot.z = 0;
|
||||
|
||||
cView.x = LCR_EFFECTIVE_RESOLUTION_X;
|
||||
cView.y = LCR_EFFECTIVE_RESOLUTION_Y;
|
||||
cView.z = (camFov * TPE_FRACTIONS_PER_UNIT) / LCR_GAME_UNIT;
|
||||
cView.z = (camFov * TPE_F) / LCR_GAME_UNIT;
|
||||
|
||||
TPE_worldDebugDraw(&(LCR_racing.physicsWorld),_LCR_drawPhysicsDebugPixel,
|
||||
cPos,cRot,cView,16,2 * LCR_PHYSICS_UNIT);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue