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:
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_

View File

@ -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());
@ -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);
@ -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));
@ -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.;

View File

@ -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;

View File

@ -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() {
@ -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;
@ -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;
@ -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);
@ -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);
#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);
}
}
@ -179,23 +179,23 @@ void ClientPlayer::checkCollisions(const ClientWorld &world) {
#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;
}
}

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
// 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) {
@ -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
}