Precision improvements (Part 2)

Improve player precision, especially location, but also rotation.
This commit is contained in:
Pedro Gimeno 2020-02-23 02:56:39 +01:00
parent 4bb12c872f
commit 6e3c2e066f
5 changed files with 77 additions and 79 deletions

View File

@ -45,50 +45,50 @@ class ClientPlayer : public Player {
public: public:
ClientPlayer(gk::Camera &camera); ClientPlayer(gk::Camera &camera);
void turnH(float angle); void turnH(double angle);
void turnV(float angle); void turnV(double angle);
void move(float direction); void move(double direction);
void processInputs(); void processInputs();
void updatePosition(const ClientWorld &world); void updatePosition(const ClientWorld &world);
void checkCollisions(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); } double dirTargetedX() const { return 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; } double dirTargetedY() const { return 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 dirTargetedZ() const { return sin(m_angleV * RADIANS_PER_DEGREES); }
static ClientPlayer &getInstance() { return *s_instance; } static ClientPlayer &getInstance() { return *s_instance; }
static void setInstance(ClientPlayer *instance) { s_instance = instance; } static void setInstance(ClientPlayer *instance) { s_instance = instance; }
float x() const { return m_x; } double x() const { return m_x; }
float y() const { return m_y; } double y() const { return m_y; }
float z() const { return m_z; } 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; } gk::Camera &camera() { return m_camera; }
private: 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; static ClientPlayer *s_instance;
gk::Camera &m_camera; gk::Camera &m_camera;
float m_x; double m_x;
float m_y; double m_y;
float m_z; double m_z;
float m_angleH; double m_angleH;
float m_angleV; double m_angleV;
glm::vec3 m_velocity{0}; glm::dvec3 m_velocity{0};
bool m_isJumping = false; bool m_isJumping = false;
const float m_gravity = 0.001; const double m_gravity = 0.001;
const float m_jumpSpeed = 0.06f; const double m_jumpSpeed = 0.06f;
}; };
#endif // CLIENTPLAYER_HPP_ #endif // CLIENTPLAYER_HPP_

View File

@ -115,8 +115,8 @@ void BlockCursor::onEvent(const SDL_Event &event, const Hotbar &hotbar) {
if (!blockId || block.drawType() == BlockDrawType::Liquid) { if (!blockId || block.drawType() == BlockDrawType::Liquid) {
// Second, we check if the new block is not inside the player // Second, we check if the new block is not inside the player
const Block &newBlock = Registry::getInstance().getBlock(hotbar.currentItem()); const Block &newBlock = Registry::getInstance().getBlock(hotbar.currentItem());
gk::FloatBox boundingBox = newBlock.boundingBox() + gk::Vector3i{x, y, 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() + gk::Vector3f{m_player.x(), m_player.y(), m_player.z()}; gk::FloatBox playerBoundingBox = m_player.hitbox();
if (!boundingBox.intersects(playerBoundingBox)) { if (!boundingBox.intersects(playerBoundingBox)) {
m_world.setBlock(x, y, z, hotbar.currentItem()); m_world.setBlock(x, y, z, hotbar.currentItem());
@ -242,7 +242,7 @@ void BlockCursor::draw(gk::RenderTarget &target, gk::RenderStates states) const
glCheck(glDisable(GL_CULL_FACE)); glCheck(glDisable(GL_CULL_FACE));
// Subtract the camera position - see comment in ClientWorld::draw() // 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); 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); target.draw(m_vbo, GL_LINES, 0, 24, states);
@ -259,9 +259,9 @@ void BlockCursor::draw(gk::RenderTarget &target, gk::RenderStates states) const
} }
glm::ivec4 BlockCursor::findSelectedBlock() const { glm::ivec4 BlockCursor::findSelectedBlock() const {
glm::dvec3 position{m_player.camera().getPosition().x, glm::dvec3 position{m_player.camera().getDPosition().x,
m_player.camera().getPosition().y, m_player.camera().getDPosition().y,
m_player.camera().getPosition().z}; m_player.camera().getDPosition().z};
int_fast32_t bestX = int_fast32_t(floor(position.x)); int_fast32_t bestX = int_fast32_t(floor(position.x));
int_fast32_t bestY = int_fast32_t(floor(position.y)); int_fast32_t bestY = int_fast32_t(floor(position.y));
@ -296,9 +296,7 @@ glm::ivec4 BlockCursor::findSelectedBlock() const {
} }
} }
glm::dvec3 lookAt{m_player.pointTargetedX() - m_player.camera().getPosition().x, glm::dvec3 lookAt{m_player.dirTargetedX(), m_player.dirTargetedY(), m_player.dirTargetedZ()};
m_player.pointTargetedY() - m_player.camera().getPosition().y,
m_player.pointTargetedZ() - m_player.camera().getPosition().z};
// Ray casting algorithm to find out which block we are looking at // Ray casting algorithm to find out which block we are looking at
const double maxReach = 10.; const double maxReach = 10.;

View File

@ -125,7 +125,7 @@ void BlockCursorRaycast::rayCastToAxis(const Axis axis, const glm::dvec3 &positi
if(blockID && block.drawType() != BlockDrawType::Liquid) { if(blockID && block.drawType() != BlockDrawType::Liquid) {
// Check bounding box; this should loop over all selection boxes // Check bounding box; this should loop over all selection boxes
// when they are implemented // 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; bool hit = false;

View File

@ -41,41 +41,41 @@ ClientPlayer::ClientPlayer(gk::Camera &camera) : m_camera(camera) {
m_angleH = -90.0; m_angleH = -90.0;
m_angleV = 0.01; m_angleV = 0.01;
m_camera.setPosition(m_x, m_y, m_z - 0.1); m_camera.setDPosition(m_x, m_y, m_z - 0.1);
m_camera.setTargetPosition(pointTargetedX(), pointTargetedY(), pointTargetedZ()); m_camera.setDirection(dirTargetedX(), dirTargetedY(), dirTargetedZ());
} }
void ClientPlayer::turnH(float angle) { void ClientPlayer::turnH(double angle) {
m_angleH += angle; m_angleH += angle;
while(m_angleH >= 180.0f) { while(m_angleH >= 180.0) {
m_angleH -= 360.0f; m_angleH -= 360.0;
} }
while(m_angleH < -180.0f) { while(m_angleH < -180.0) {
m_angleH += 360.0f; 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; m_angleV += angle;
if(89.9f < m_angleV) { if(89.9 < m_angleV) {
m_angleV = 89.9f; m_angleV = 89.9;
} }
else if(-89.9f > m_angleV) { else if(-89.9 > m_angleV) {
m_angleV = -89.9f; 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; direction += m_angleH;
m_velocity.x = 0.04f * cosf(direction * RADIANS_PER_DEGREES); m_velocity.x = 0.04 * cos(direction * RADIANS_PER_DEGREES);
m_velocity.y = 0.04f * sinf(direction * RADIANS_PER_DEGREES); m_velocity.y = 0.04 * sin(direction * RADIANS_PER_DEGREES);
} }
void ClientPlayer::processInputs() { void ClientPlayer::processInputs() {
@ -92,16 +92,16 @@ void ClientPlayer::processInputs() {
m_velocity.z = -0.1; m_velocity.z = -0.1;
} }
if(gk::GamePad::isKeyPressed(GameKey::Up)) move(0.0f); if(gk::GamePad::isKeyPressed(GameKey::Up)) move(0.0);
else if(gk::GamePad::isKeyPressed(GameKey::Down)) move(180.0f); else if(gk::GamePad::isKeyPressed(GameKey::Down)) move(180.0);
if(gk::GamePad::isKeyPressed(GameKey::Left)) move(90.0f); if(gk::GamePad::isKeyPressed(GameKey::Left)) move(90.0);
else if(gk::GamePad::isKeyPressed(GameKey::Right)) move(-90.0f); 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::Left) && gk::GamePad::isKeyPressed(GameKey::Up)) move(45.0);
if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Up)) move(-45.0f); 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.0f); 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.0f); if (gk::GamePad::isKeyPressed(GameKey::Right) && gk::GamePad::isKeyPressed(GameKey::Down)) move(-135.0);
if (gk::GamePad::isKeyPressed(GameKey::Sprint)) { if (gk::GamePad::isKeyPressed(GameKey::Sprint)) {
m_velocity.x *= 1.5; m_velocity.x *= 1.5;
@ -122,19 +122,19 @@ void ClientPlayer::updatePosition(const ClientWorld &world) {
checkCollisions(world); checkCollisions(world);
if (!Config::isFlyModeEnabled && m_velocity.z != 0) { if (!Config::isFlyModeEnabled && m_velocity.z != 0) {
m_velocity.x *= 0.75f; m_velocity.x *= 0.75;
m_velocity.y *= 0.75f; m_velocity.y *= 0.75;
} }
m_x += m_velocity.x; m_x += m_velocity.x;
m_y += m_velocity.y; m_y += m_velocity.y;
m_z += m_velocity.z; 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); Player::setPosition(m_x, m_y, m_z);
if (m_velocity.x != 0 || m_velocity.y != 0 || m_velocity.z != 0) 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.x = 0;
m_velocity.y = 0; m_velocity.y = 0;
@ -143,20 +143,20 @@ void ClientPlayer::updatePosition(const ClientWorld &world) {
m_velocity.z = 0; 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_x = x;
m_y = y; m_y = y;
m_z = z; m_z = z;
Player::setPosition(x, y, 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) { void ClientPlayer::checkCollisions(const ClientWorld &world) {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__ANDROID__) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__ANDROID__)
const float PLAYER_HEIGHT = 1.8; const double PLAYER_HEIGHT = 1.8;
float eyeheight = m_z + PLAYER_HEIGHT - 1.4; double eyeheight = m_z + PLAYER_HEIGHT - 1.4;
// testPoint(world, glm::vec3(m_x, m_y, m_z), m_velocity); // 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); 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);
@ -166,12 +166,12 @@ 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);
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 #else
for (float z = m_z + m_hitbox.z ; z <= m_z + m_hitbox.z + m_hitbox.sizeZ + 0.1f ; z += 0.9f) { for (double z = m_z + m_hitbox.z ; z <= m_z + (m_hitbox.z + m_hitbox.sizeZ) + 0.1 ; z += 0.9) {
for (float y = m_y + m_hitbox.y ; y <= m_y + m_hitbox.y + m_hitbox.sizeY + 0.1f ; y += 0.2f) { for (double y = m_y + m_hitbox.y ; y <= m_y + (m_hitbox.y + m_hitbox.sizeY) + 0.1 ; y += 0.2) {
for (float x = m_x + m_hitbox.x ; x <= m_x + m_hitbox.x + m_hitbox.sizeX + 0.1f ; x += 0.2f) { 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 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 || 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) || z == m_z + m_hitbox.z || z == m_z + (m_hitbox.z + m_hitbox.sizeZ))
testPoint(world, x, y, z, m_velocity); testPoint(world, x, y, z, m_velocity);
} }
} }
@ -179,23 +179,23 @@ void ClientPlayer::checkCollisions(const ClientWorld &world) {
#endif #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); u32 blockID = world.getBlock(x, y, z);
const Block &block = Registry::getInstance().getBlock(blockID); const Block &block = Registry::getInstance().getBlock(blockID);
return !blockID || block.drawType() == BlockDrawType::Liquid || block.drawType() == BlockDrawType::XShape; 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!!! // FIXME: Temporary fix, find the real problem!!!
if (x < 1) --x; if (x < 1) --x;
if (y < 1) --y; if (y < 1) --y;
if (z < 1) --z; if (z < 1) --z;
if(!passable(world, x + speed.x, y, z)) speed.x = 0; if(!passable(world, x + vel.x, y, z)) vel.x = 0;
if(!passable(world, x, y + speed.y, z)) speed.y = 0; if(!passable(world, x, y + vel.y, z)) vel.y = 0;
if(!passable(world, x, y, z + speed.z)) { if(!passable(world, x, y, z + vel.z)) {
if(speed.z < 0 && m_isJumping) m_isJumping = false; if(vel.z < 0 && m_isJumping) m_isJumping = false;
speed.z = 0; vel.z = 0;
} }
} }

View File

@ -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 // vertex coordinates passed to the renderer are all small, and single
// precision floats suffice for the drawing. // precision floats suffice for the drawing.
gk::Vector3d cameraPos(m_camera->getPosition()); gk::Vector3d cameraPos(m_camera->getDPosition());
m_camera->setPosition(0, 0, 0); // Temporarily move the camera to the origin m_camera->setDPosition(0, 0, 0); // Temporarily move the camera to the origin
std::vector<std::pair<ClientChunk*, gk::Transform>> chunks; std::vector<std::pair<ClientChunk*, gk::Transform>> chunks;
for(auto &it : m_chunks) { for(auto &it : m_chunks) {
@ -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
} }