Skip to content

Commit

Permalink
Precision improvements (Part 2)
Browse files Browse the repository at this point in the history
Improve player precision, especially location, but also rotation.
  • Loading branch information
Pedro Gimeno committed Feb 24, 2020
1 parent 4bb12c8 commit 6e3c2e0
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 79 deletions.
38 changes: 19 additions & 19 deletions client/include/world/ClientPlayer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,50 +45,50 @@ class ClientPlayer : public Player {
public:
ClientPlayer(gk::Camera &camera);

void turnH(float angle);
void turnV(float angle);
void turnH(double angle);
void turnV(double angle);

void move(float direction);
void move(double direction);

void processInputs();
void updatePosition(const ClientWorld &world);

void checkCollisions(const ClientWorld &world);

float pointTargetedX() const { return m_x + cos(m_angleH * RADIANS_PER_DEGREES) * cos(m_angleV * RADIANS_PER_DEGREES); }
float pointTargetedY() const { return m_y + sin(m_angleH * RADIANS_PER_DEGREES) * cos(m_angleV * RADIANS_PER_DEGREES) - 0.00001; }
float pointTargetedZ() const { return m_z + sin(m_angleV * RADIANS_PER_DEGREES); }
double dirTargetedX() const { return cos(m_angleH * RADIANS_PER_DEGREES) * cos(m_angleV * RADIANS_PER_DEGREES); }
double dirTargetedY() const { return sin(m_angleH * RADIANS_PER_DEGREES) * cos(m_angleV * RADIANS_PER_DEGREES) - 0.00001; }
double dirTargetedZ() const { return sin(m_angleV * RADIANS_PER_DEGREES); }

static ClientPlayer &getInstance() { return *s_instance; }
static void setInstance(ClientPlayer *instance) { s_instance = instance; }

float x() const { return m_x; }
float y() const { return m_y; }
float z() const { return m_z; }
double x() const { return m_x; }
double y() const { return m_y; }
double z() const { return m_z; }

void setPosition(float x, float y, float z);
void setPosition(double x, double y, double z);

gk::Camera &camera() { return m_camera; }

private:
void testPoint(const ClientWorld &world, float x, float y, float z, glm::vec3 &speed);
void testPoint(const ClientWorld &world, double x, double y, double z, glm::dvec3 &vel);

static ClientPlayer *s_instance;

gk::Camera &m_camera;

float m_x;
float m_y;
float m_z;
double m_x;
double m_y;
double m_z;

float m_angleH;
float m_angleV;
double m_angleH;
double m_angleV;

glm::vec3 m_velocity{0};
glm::dvec3 m_velocity{0};
bool m_isJumping = false;

const float m_gravity = 0.001;
const float m_jumpSpeed = 0.06f;
const double m_gravity = 0.001;
const double m_jumpSpeed = 0.06f;
};

#endif // CLIENTPLAYER_HPP_
16 changes: 7 additions & 9 deletions client/source/hud/BlockCursor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) {
if (!blockId || block.drawType() == BlockDrawType::Liquid) {
// Second, we check if the new block is not inside the player
const Block &newBlock = Registry::getInstance().getBlock(hotbar.currentItem());
gk::FloatBox boundingBox = newBlock.boundingBox() + gk::Vector3i{x, y, z};
gk::FloatBox playerBoundingBox = m_player.hitbox() + gk::Vector3f{m_player.x(), m_player.y(), m_player.z()};
gk::FloatBox boundingBox = newBlock.boundingBox() + gk::Vector3f(x - m_player.x(), y - m_player.y(), z - m_player.z());
gk::FloatBox playerBoundingBox = m_player.hitbox();
if (!boundingBox.intersects(playerBoundingBox)) {
m_world.setBlock(x, y, z, hotbar.currentItem());

Expand Down Expand Up @@ -242,7 +242,7 @@ void BlockCursor::draw(gk::RenderTarget &target, gk::RenderStates states) const
glCheck(glDisable(GL_CULL_FACE));

// Subtract the camera position - see comment in ClientWorld::draw()
gk::Vector3d cameraPosition = m_player.camera().getPosition();
gk::Vector3d cameraPosition = m_player.camera().getDPosition();
states.transform.translate(m_selectedBlock.x - cameraPosition.x, m_selectedBlock.y - cameraPosition.y, m_selectedBlock.z - cameraPosition.z);

target.draw(m_vbo, GL_LINES, 0, 24, states);
Expand All @@ -259,9 +259,9 @@ void BlockCursor::draw(gk::RenderTarget &target, gk::RenderStates states) const
}

glm::ivec4 BlockCursor::findSelectedBlock() const {
glm::dvec3 position{m_player.camera().getPosition().x,
m_player.camera().getPosition().y,
m_player.camera().getPosition().z};
glm::dvec3 position{m_player.camera().getDPosition().x,
m_player.camera().getDPosition().y,
m_player.camera().getDPosition().z};

int_fast32_t bestX = int_fast32_t(floor(position.x));
int_fast32_t bestY = int_fast32_t(floor(position.y));
Expand Down Expand Up @@ -296,9 +296,7 @@ glm::ivec4 BlockCursor::findSelectedBlock() const {
}
}

glm::dvec3 lookAt{m_player.pointTargetedX() - m_player.camera().getPosition().x,
m_player.pointTargetedY() - m_player.camera().getPosition().y,
m_player.pointTargetedZ() - m_player.camera().getPosition().z};
glm::dvec3 lookAt{m_player.dirTargetedX(), m_player.dirTargetedY(), m_player.dirTargetedZ()};

// Ray casting algorithm to find out which block we are looking at
const double maxReach = 10.;
Expand Down
2 changes: 1 addition & 1 deletion client/source/math/BlockCursorRaycast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ void BlockCursorRaycast::rayCastToAxis(const Axis axis, const glm::dvec3 &positi
if(blockID && block.drawType() != BlockDrawType::Liquid) {
// Check bounding box; this should loop over all selection boxes
// when they are implemented
gk::DoubleBox selBox = block.boundingBox() + gk::Vector3d(double(nx), double(ny), double(nz));
gk::DoubleBox selBox = block.boundingBox() + gk::Vector3d{double(nx), double(ny), double(nz)};

bool hit = false;

Expand Down
94 changes: 47 additions & 47 deletions client/source/world/ClientPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,41 +41,41 @@ ClientPlayer::ClientPlayer(gk::Camera &camera) : m_camera(camera) {
m_angleH = -90.0;
m_angleV = 0.01;

m_camera.setPosition(m_x, m_y, m_z - 0.1);
m_camera.setTargetPosition(pointTargetedX(), pointTargetedY(), pointTargetedZ());
m_camera.setDPosition(m_x, m_y, m_z - 0.1);
m_camera.setDirection(dirTargetedX(), dirTargetedY(), dirTargetedZ());
}

void ClientPlayer::turnH(float angle) {
void ClientPlayer::turnH(double angle) {
m_angleH += angle;

while(m_angleH >= 180.0f) {
m_angleH -= 360.0f;
while(m_angleH >= 180.0) {
m_angleH -= 360.0;
}
while(m_angleH < -180.0f) {
m_angleH += 360.0f;
while(m_angleH < -180.0) {
m_angleH += 360.0;
}

m_camera.setTargetPosition(pointTargetedX(), pointTargetedY(), pointTargetedZ());
m_camera.setDirection(dirTargetedX(), dirTargetedY(), dirTargetedZ());
}

void ClientPlayer::turnV(float angle) {
void ClientPlayer::turnV(double angle) {
m_angleV += angle;

if(89.9f < m_angleV) {
m_angleV = 89.9f;
if(89.9 < m_angleV) {
m_angleV = 89.9;
}
else if(-89.9f > m_angleV) {
m_angleV = -89.9f;
else if(-89.9 > m_angleV) {
m_angleV = -89.9;
}

m_camera.setTargetPosition(pointTargetedX(), pointTargetedY(), pointTargetedZ());
m_camera.setDirection(dirTargetedX(), dirTargetedY(), dirTargetedZ());
}

void ClientPlayer::move(float direction) {
void ClientPlayer::move(double direction) {
direction += m_angleH;

m_velocity.x = 0.04f * cosf(direction * RADIANS_PER_DEGREES);
m_velocity.y = 0.04f * sinf(direction * RADIANS_PER_DEGREES);
m_velocity.x = 0.04 * cos(direction * RADIANS_PER_DEGREES);
m_velocity.y = 0.04 * sin(direction * RADIANS_PER_DEGREES);
}

void ClientPlayer::processInputs() {
Expand All @@ -92,16 +92,16 @@ void ClientPlayer::processInputs() {
m_velocity.z = -0.1;
}

if(gk::GamePad::isKeyPressed(GameKey::Up)) move(0.0f);
else if(gk::GamePad::isKeyPressed(GameKey::Down)) move(180.0f);
if(gk::GamePad::isKeyPressed(GameKey::Up)) move(0.0);
else if(gk::GamePad::isKeyPressed(GameKey::Down)) move(180.0);

if(gk::GamePad::isKeyPressed(GameKey::Left)) move(90.0f);
else if(gk::GamePad::isKeyPressed(GameKey::Right)) move(-90.0f);
if(gk::GamePad::isKeyPressed(GameKey::Left)) move(90.0);
else if(gk::GamePad::isKeyPressed(GameKey::Right)) move(-90.0);

if (gk::GamePad::isKeyPressed(GameKey::Left) && gk::GamePad::isKeyPressed(GameKey::Up)) move(45.0f);
if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Up)) move(-45.0f);
if (gk::GamePad::isKeyPressed(GameKey::Left) && gk::GamePad::isKeyPressed(GameKey::Down)) move(135.0f);
if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Down)) move(-135.0f);
if (gk::GamePad::isKeyPressed(GameKey::Left) && gk::GamePad::isKeyPressed(GameKey::Up)) move(45.0);
if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Up)) move(-45.0);
if (gk::GamePad::isKeyPressed(GameKey::Left) && gk::GamePad::isKeyPressed(GameKey::Down)) move(135.0);
if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Down)) move(-135.0);

if (gk::GamePad::isKeyPressed(GameKey::Sprint)) {
m_velocity.x *= 1.5;
Expand All @@ -122,19 +122,19 @@ void ClientPlayer::updatePosition(const ClientWorld &world) {
checkCollisions(world);

if (!Config::isFlyModeEnabled && m_velocity.z != 0) {
m_velocity.x *= 0.75f;
m_velocity.y *= 0.75f;
m_velocity.x *= 0.75;
m_velocity.y *= 0.75;
}

m_x += m_velocity.x;
m_y += m_velocity.y;
m_z += m_velocity.z;

m_camera.setPosition(m_x, m_y, m_z - 0.1);
m_camera.setDPosition(m_x, m_y, m_z - 0.1);
Player::setPosition(m_x, m_y, m_z);

if (m_velocity.x != 0 || m_velocity.y != 0 || m_velocity.z != 0)
m_camera.setTargetPosition(pointTargetedX(), pointTargetedY(), pointTargetedZ());
m_camera.setDirection(dirTargetedX(), dirTargetedY(), dirTargetedZ());

m_velocity.x = 0;
m_velocity.y = 0;
Expand All @@ -143,20 +143,20 @@ void ClientPlayer::updatePosition(const ClientWorld &world) {
m_velocity.z = 0;
}

void ClientPlayer::setPosition(float x, float y, float z) {
void ClientPlayer::setPosition(double x, double y, double z) {
m_x = x;
m_y = y;
m_z = z;

Player::setPosition(x, y, z);
m_camera.setPosition(x, y, z - 0.1);
m_camera.setDPosition(x, y, z - 0.1);
}

void ClientPlayer::checkCollisions(const ClientWorld &world) {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__ANDROID__)
const float PLAYER_HEIGHT = 1.8;
float eyeheight = m_z + PLAYER_HEIGHT - 1.4;
// testPoint(world, glm::vec3(m_x, m_y, m_z), m_velocity);
const double PLAYER_HEIGHT = 1.8;
double eyeheight = m_z + PLAYER_HEIGHT - 1.4;
// testPoint(world, glm::dvec3(m_x, m_y, m_z), m_velocity);
testPoint(world, m_x - 0.2, m_y - 0.2, eyeheight - PLAYER_HEIGHT - 0.4, m_velocity);
testPoint(world, m_x + 0.2, m_y - 0.2, eyeheight - PLAYER_HEIGHT - 0.4, m_velocity);
testPoint(world, m_x - 0.2, m_y + 0.2, eyeheight - PLAYER_HEIGHT - 0.4, m_velocity);
Expand All @@ -166,36 +166,36 @@ void ClientPlayer::checkCollisions(const ClientWorld &world) {
testPoint(world, m_x - 0.2, m_y + 0.2, eyeheight - 0.4, m_velocity);
testPoint(world, m_x + 0.2, m_y + 0.2, eyeheight - 0.4, m_velocity);
#else
for (float z = m_z + m_hitbox.z ; z <= m_z + m_hitbox.z + m_hitbox.sizeZ + 0.1f ; z += 0.9f) {
for (float y = m_y + m_hitbox.y ; y <= m_y + m_hitbox.y + m_hitbox.sizeY + 0.1f ; y += 0.2f) {
for (float x = m_x + m_hitbox.x ; x <= m_x + m_hitbox.x + m_hitbox.sizeX + 0.1f ; x += 0.2f) {
if (x == m_x + m_hitbox.x || x == m_x + m_hitbox.x + m_hitbox.sizeX
|| y == m_y + m_hitbox.y || y == m_y + m_hitbox.y + m_hitbox.sizeY
|| z == m_z + m_hitbox.z || z == m_z + m_hitbox.z + m_hitbox.sizeZ)
for (double z = m_z + m_hitbox.z ; z <= m_z + (m_hitbox.z + m_hitbox.sizeZ) + 0.1 ; z += 0.9) {
for (double y = m_y + m_hitbox.y ; y <= m_y + (m_hitbox.y + m_hitbox.sizeY) + 0.1 ; y += 0.2) {
for (double x = m_x + m_hitbox.x ; x <= m_x + (m_hitbox.x + m_hitbox.sizeX) + 0.1 ; x += 0.2) {
if (x == m_x + m_hitbox.x || x == m_x + (m_hitbox.x + m_hitbox.sizeX)
|| y == m_y + m_hitbox.y || y == m_y + (m_hitbox.y + m_hitbox.sizeY)
|| z == m_z + m_hitbox.z || z == m_z + (m_hitbox.z + m_hitbox.sizeZ))
testPoint(world, x, y, z, m_velocity);
}
}
}
#endif
}

bool passable(const ClientWorld &world, float x, float y, float z) {
bool passable(const ClientWorld &world, double x, double y, double z) {
u32 blockID = world.getBlock(x, y, z);
const Block &block = Registry::getInstance().getBlock(blockID);
return !blockID || block.drawType() == BlockDrawType::Liquid || block.drawType() == BlockDrawType::XShape;
}

void ClientPlayer::testPoint(const ClientWorld &world, float x, float y, float z, glm::vec3 &speed) {
void ClientPlayer::testPoint(const ClientWorld &world, double x, double y, double z, glm::dvec3 &vel) {
// FIXME: Temporary fix, find the real problem!!!
if (x < 1) --x;
if (y < 1) --y;
if (z < 1) --z;

if(!passable(world, x + speed.x, y, z)) speed.x = 0;
if(!passable(world, x, y + speed.y, z)) speed.y = 0;
if(!passable(world, x, y, z + speed.z)) {
if(speed.z < 0 && m_isJumping) m_isJumping = false;
speed.z = 0;
if(!passable(world, x + vel.x, y, z)) vel.x = 0;
if(!passable(world, x, y + vel.y, z)) vel.y = 0;
if(!passable(world, x, y, z + vel.z)) {
if(vel.z < 0 && m_isJumping) m_isJumping = false;
vel.z = 0;
}
}

6 changes: 3 additions & 3 deletions client/source/world/ClientWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const
// vertex coordinates passed to the renderer are all small, and single
// precision floats suffice for the drawing.

gk::Vector3d cameraPos(m_camera->getPosition());
m_camera->setPosition(0, 0, 0); // Temporarily move the camera to the origin
gk::Vector3d cameraPos(m_camera->getDPosition());
m_camera->setDPosition(0, 0, 0); // Temporarily move the camera to the origin

std::vector<std::pair<ClientChunk*, gk::Transform>> chunks;
for(auto &it : m_chunks) {
Expand Down Expand Up @@ -285,6 +285,6 @@ void ClientWorld::draw(gk::RenderTarget &target, gk::RenderStates states) const
}
}

m_camera->setPosition(cameraPos); // Restore the camera to its original position
m_camera->setDPosition(cameraPos); // Restore the camera to its original position
}

0 comments on commit 6e3c2e0

Please sign in to comment.