[GameState] Can now display a cross and the selected block.

This commit is contained in:
Quentin Bazin 2018-06-13 21:48:35 +02:00
parent 23630138d4
commit 3cd2335d40
8 changed files with 242 additions and 36 deletions

View File

@ -28,6 +28,10 @@ class GameState : public ApplicationState {
void update();
void draw();
void drawSelectedBlock();
void drawCross();
void findSelectedBlock(bool useDepthBuffer);
private:
glm::mat4 m_projectionMatrix;
@ -39,6 +43,8 @@ class GameState : public ApplicationState {
Skybox m_skybox;
World m_world;
GLuint m_cursorVBO;
};
#endif // GAMESTATE_HPP_

View File

@ -28,10 +28,16 @@ class Block {
u32 id() const { return m_id; }
s8 selectedFace() const { return m_selectedFace; }
void setSelected(bool isSelected, s8 face) { m_isSelected = isSelected; m_selectedFace = face; }
private:
glm::vec3 m_pos;
u32 m_id;
bool m_isSelected = false;
s8 m_selectedFace = -1;
};
#endif // BLOCK_HPP_

View File

@ -25,7 +25,7 @@ class World {
public:
World();
void draw(Shader &shader, const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix);
void draw(Camera &camera, Shader &shader, const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix);
Chunk *getChunk(s32 x, s32 z);
@ -33,8 +33,8 @@ class World {
void removeSelectedBlock() { if(!selectedChunk || !selectedBlock) return; selectedChunk->setBlock(selectedBlock->pos(), 0); selectedChunk->update(); }
bool intersectionLinePlane(const glm::vec3 &normal, const glm::vec3 &planePoint, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance);
bool intersectionLineCube(int cubeX, int cubeY, int cubeZ, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance, s8 *face);
void testCubes(Camera &camera);
bool intersectionLineBlock(int blockX, int blockY, int blockZ, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance, s8 *face);
void testBlocks(Camera &camera, float maxDistance);
// Render distance in chunks
static const u16 renderDistance = 8;

View File

@ -7,12 +7,13 @@ uniform sampler2D u_tex;
vec4 getColor() {
vec4 color = v_color;
if(color == vec4(0, 0, 0, 1)) {
color = texture2D(u_tex, v_texCoord);
}
// Very cheap "transparency": don't draw pixels with a low alpha value
if(color.a < 0.4) discard;
return color;
}

View File

@ -29,6 +29,8 @@ void Renderer::init(Window &window) {
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1, 1);
glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);

View File

@ -17,6 +17,7 @@
#include "OpenGL.hpp"
#include "Config.hpp"
#include "Keyboard.hpp"
#include "Mouse.hpp"
#include "GameState.hpp"
@ -42,6 +43,8 @@ GameState::GameState() : m_camera(Camera::getInstance()) {
m_shader.setUniform("u_tex", 0);
Shader::bind(nullptr);
glGenBuffers(1, &m_cursorVBO);
}
void GameState::update() {
@ -49,9 +52,10 @@ void GameState::update() {
// glm::vec3 start = glm::unProject(glm::vec3(Mouse::getX(), Mouse::getY(), 0.0), m_viewMatrix, m_projectionMatrix, glm::ivec4(0.0, 0.0, SCREEN_WIDTH, SCREEN_HEIGHT));
// glm::vec3 end = glm::unProject(glm::vec3(Mouse::getX(), Mouse::getY(), 1.0), m_viewMatrix, m_projectionMatrix, glm::ivec4(0.0, 0.0, SCREEN_WIDTH, SCREEN_HEIGHT));
m_world.testCubes(m_camera);
m_world.testBlocks(m_camera, 20.0f);
// m_world.removeSelectedBlock();
if (Keyboard::isKeyPressedOnce(Keyboard::X))
m_world.removeSelectedBlock();
}
void GameState::draw() {
@ -61,8 +65,161 @@ void GameState::draw() {
// m_skybox.draw(m_shader);
m_world.draw(m_shader, m_projectionMatrix, m_viewMatrix);
m_world.draw(m_camera, m_shader, m_projectionMatrix, m_viewMatrix);
if (m_world.selectedBlock)
drawSelectedBlock();
drawCross();
Shader::bind(nullptr);
}
void GameState::drawSelectedBlock() {
float bx = m_world.selectedBlock->pos().x;
float by = m_world.selectedBlock->pos().y;
float bz = m_world.selectedBlock->pos().z;
/* Render a box around the block we are pointing at */
float box[24][3] = {
{bx + 0, by + 0, bz + 0},//, 14},
{bx + 1, by + 0, bz + 0},//, 14},
{bx + 0, by + 1, bz + 0},//, 14},
{bx + 1, by + 1, bz + 0},//, 14},
{bx + 0, by + 0, bz + 1},//, 14},
{bx + 1, by + 0, bz + 1},//, 14},
{bx + 0, by + 1, bz + 1},//, 14},
{bx + 1, by + 1, bz + 1},//, 14},
{bx + 0, by + 0, bz + 0},//, 14},
{bx + 0, by + 1, bz + 0},//, 14},
{bx + 1, by + 0, bz + 0},//, 14},
{bx + 1, by + 1, bz + 0},//, 14},
{bx + 0, by + 0, bz + 1},//, 14},
{bx + 0, by + 1, bz + 1},//, 14},
{bx + 1, by + 0, bz + 1},//, 14},
{bx + 1, by + 1, bz + 1},//, 14},
{bx + 0, by + 0, bz + 0},//, 14},
{bx + 0, by + 0, bz + 1},//, 14},
{bx + 1, by + 0, bz + 0},//, 14},
{bx + 1, by + 0, bz + 1},//, 14},
{bx + 0, by + 1, bz + 0},//, 14},
{bx + 0, by + 1, bz + 1},//, 14},
{bx + 1, by + 1, bz + 0},//, 14},
{bx + 1, by + 1, bz + 1},//, 14},
};
glDisable(GL_POLYGON_OFFSET_FILL);
glDisable(GL_CULL_FACE);
glBindBuffer(GL_ARRAY_BUFFER, m_cursorVBO);
m_shader.setUniform("u_modelMatrix", glm::mat4(1));
glBufferData(GL_ARRAY_BUFFER, sizeof(box), box, GL_DYNAMIC_DRAW);
m_shader.enableVertexAttribArray("coord3d");
glVertexAttribPointer(m_shader.attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_LINES, 0, 24);
m_shader.disableVertexAttribArray("coord3d");
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnable(GL_CULL_FACE);
glEnable(GL_POLYGON_OFFSET_FILL);
}
void GameState::drawCross() {
/* Draw a cross in the center of the screen */
float cross[4][3] = {
{-0.04, 0, 0},//, 13},
{+0.04, 0, 0},//, 13},
{0, -0.05, 0},//, 13},
{0, +0.05, 0},//, 13}
};
glDisable(GL_DEPTH_TEST);
glBindBuffer(GL_ARRAY_BUFFER, m_cursorVBO);
m_shader.setUniform("u_modelMatrix", glm::mat4(1));
m_shader.setUniform("u_viewMatrix", glm::mat4(1));
m_shader.setUniform("u_projectionMatrix", glm::mat4(1));
glBufferData(GL_ARRAY_BUFFER, sizeof(cross), cross, GL_DYNAMIC_DRAW);
m_shader.enableVertexAttribArray("coord3d");
glVertexAttribPointer(m_shader.attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glDrawArrays(GL_LINES, 0, 4);
m_shader.disableVertexAttribArray("coord3d");
glBindBuffer(GL_ARRAY_BUFFER, 0);
glEnable(GL_DEPTH_TEST);
m_shader.setUniform("u_projectionMatrix", m_projectionMatrix);
}
// FIXME
void GameState::findSelectedBlock(bool) {
// if(useDepthBuffer) {
// // At which voxel are we looking? First, find out coords of the center pixel
// float depth;
// glReadPixels(ww / 2, wh / 2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
//
// glm::vec4 viewport = glm::vec4(0, 0, ww, wh);
// glm::vec3 winCoord = glm::vec3(ww / 2, wh / 2, depth);
// glm::vec3 objCoord = glm::unProject(winCoord, view, projection, viewport);
//
// // Find out which block it belongs to
// mx = objCoord.x;
// my = objCoord.y;
// mz = objCoord.z;
//
// if(objCoord.x < 0) mx--;
// if(objCoord.y < 0) my--;
// if(objCoord.z < 0) mz--;
//
// // Find out which face of the block we are looking at
// if(fract(objCoord.x) < fract(objCoord.y)) {
// if(fract(objCoord.x) < fract(objCoord.z)) {
// face = 0; // X
// } else {
// face = 2; // Z
// }
// } else {
// if(fract(objCoord.y) < fract(objCoord.z)) {
// face = 1; // Y
// } else {
// face = 2; // Z
// }
// }
//
// if(face == 0 && lookAt.x > 0) face += 3;
// if(face == 1 && lookAt.y > 0) face += 3;
// if(face == 2 && lookAt.z > 0) face += 3;
// } else {
// // Very naive ray casting algorithm to find out which block we are looking at
// glm::vec3 testPos = position;
// glm::vec3 prevPos = position;
//
// for(int i = 0 ; i < 100 ; i++) {
// // Advance from our current position to the direction we are looking at, in small steps
// prevPos = testPos;
// testPos += lookAt * 0.1f;
//
// mx = floorf(testPos.x);
// my = floorf(testPos.y);
// mz = floorf(testPos.z);
//
// // If we find a block that is not air, we are done
// if(world->getBlock(mx, my, mz)) break;
// }
//
// // Find out which face of the block we are looking at
//
// int px = floorf(prevPos.x);
// int py = floorf(prevPos.y);
// int pz = floorf(prevPos.z);
//
// if(px > mx) face = 0;
// else if(px < mx) face = 3;
// else if(py > my) face = 1;
// else if(py < my) face = 4;
// else if(pz > mz) face = 2;
// else if(pz < mz) face = 5;
//
// // If we are looking at air, move the cursor out of sight
// if(!world->getBlock(mx, my, mz)) mx = my = mz = 99999;
// }
}

View File

@ -277,8 +277,8 @@ void Chunk::draw(Shader &shader) {
shader.enableVertexAttribArray("normal");
shader.enableVertexAttribArray("texCoord");
glVertexAttribPointer(shader.attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(shader.attrib("normal"), 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(m_vertices.size() * sizeof(float)));
glVertexAttribPointer(shader.attrib("coord3d"), 3, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(shader.attrib("normal"), 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)(m_vertices.size() * sizeof(float)));
glVertexAttribPointer(shader.attrib("texCoord"), 2, GL_FLOAT, GL_FALSE, 0, (GLvoid*)((m_vertices.size() + m_normals.size()) * sizeof(float)));
Texture::bind(&m_texture);
@ -288,8 +288,8 @@ void Chunk::draw(Shader &shader) {
Texture::bind(nullptr);
// for(u32 i = 0 ; i < m_vertices.size() / 3 ; i += 4) {
// glDrawArrays(GL_LINE_LOOP, i, 4);
//}
// glDrawArrays(GL_LINE_LOOP, i, 4);
// }
shader.disableVertexAttribArray("texCoord");
shader.disableVertexAttribArray("normal");

View File

@ -44,7 +44,7 @@ World::World() {
}
}
void World::draw(Shader &shader, const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) {
void World::draw(Camera &camera, Shader &shader, const glm::mat4 &projectionMatrix, const glm::mat4 &viewMatrix) {
float ud = 1000.0;
s32 ux = 0;
s32 uz = 0;
@ -109,6 +109,40 @@ void World::draw(Shader &shader, const glm::mat4 &projectionMatrix, const glm::m
if(getChunk(ux, uz)->front()) m_terrainGenerator.generate(*getChunk(ux, uz)->front());
if(getChunk(ux, uz)->back()) m_terrainGenerator.generate(*getChunk(ux, uz)->back());
}
// FIXME: MOVE AND REWRITE THIS SH*T
// glBindTexture(GL_TEXTURE_2D, 0);
// Chunk *currentChunk = getChunk(camera.x() / Chunk::width, camera.z() / Chunk::depth);
// if (currentChunk && selectedBlock) {
// float blockCoords[6 * 12] = {
// 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, // FR | 0
// 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, // FL | 1
// 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, // BR | 2
// 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, // BL | 3
// 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, // T | 4
// 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0 // B | 5
// };
//
// int xx = selectedBlock->pos().x;
// int yy = selectedBlock->pos().y;
// int zz = selectedBlock->pos().z;
//
// glColor4ub(255, 255, 255, 64);
// glDisable(GL_ALPHA_TEST);
// glEnable(GL_POLYGON_OFFSET_FILL);
// glPolygonOffset(-1.0, -1.0);
//
// glBegin(GL_QUADS);
// glVertex3f(xx + blockCoords[(selectedBlock->selectedFace() * 12) + 0], yy + blockCoords[(selectedBlock->selectedFace() * 12) + 1], zz + blockCoords[(selectedBlock->selectedFace() * 12) + 2]);
// glVertex3f(xx + blockCoords[(selectedBlock->selectedFace() * 12) + 3], yy + blockCoords[(selectedBlock->selectedFace() * 12) + 4], zz + blockCoords[(selectedBlock->selectedFace() * 12) + 5]);
// glVertex3f(xx + blockCoords[(selectedBlock->selectedFace() * 12) + 6], yy + blockCoords[(selectedBlock->selectedFace() * 12) + 7], zz + blockCoords[(selectedBlock->selectedFace() * 12) + 8]);
// glVertex3f(xx + blockCoords[(selectedBlock->selectedFace() * 12) + 9], yy + blockCoords[(selectedBlock->selectedFace() * 12) + 10], zz + blockCoords[(selectedBlock->selectedFace() * 12) + 11]);
// glEnd();
//
// glDisable(GL_POLYGON_OFFSET_FILL);
// glEnable(GL_ALPHA_TEST);
// glColor4ub(255, 255, 255, 255);
// }
}
Chunk *World::getChunk(s32 x, s32 z) {
@ -157,14 +191,14 @@ bool World::intersectionLinePlane(const glm::vec3 &normal, const glm::vec3 &plan
// Back right = 2 | Back left = 3
// Top = 4 | Bottom = 5
// FIXME: Move to a math module
bool World::intersectionLineCube(int cubeX, int cubeY, int cubeZ, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance, s8 *face) {
bool World::intersectionLineBlock(int blockX, int blockY, int blockZ, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance, s8 *face) {
glm::vec3 planePoint[6] = {
glm::vec3(cubeX + 0.5, cubeY + 1, cubeZ + 0.5), // back
glm::vec3(cubeX + 1, cubeY + 0.5, cubeZ + 0.5), // right
glm::vec3(cubeX, cubeY + 0.5, cubeZ + 0.5), // left
glm::vec3(cubeX + 0.5, cubeY, cubeZ + 0.5), // front
glm::vec3(cubeX + 0.5, cubeY + 0.5, cubeZ + 1), // top
glm::vec3(cubeX + 0.5, cubeY + 0.5, cubeZ) // bottom
glm::vec3(blockX + 0.5, blockY + 1, blockZ + 0.5), // back
glm::vec3(blockX + 1, blockY + 0.5, blockZ + 0.5), // right
glm::vec3(blockX, blockY + 0.5, blockZ + 0.5), // left
glm::vec3(blockX + 0.5, blockY, blockZ + 0.5), // front
glm::vec3(blockX + 0.5, blockY + 0.5, blockZ + 1), // top
glm::vec3(blockX + 0.5, blockY + 0.5, blockZ) // bottom
};
glm::vec3 normal[6] = {
@ -199,9 +233,10 @@ bool World::intersectionLineCube(int cubeX, int cubeY, int cubeZ, const glm::vec
#include <unordered_map>
#include <unistd.h>
#include "Debug.hpp"
// FIXME: MOVE THIS FUNCTION
void World::testCubes(Camera &camera) {
// FIXME: IMPROVE AND MOVE THIS FUNCTION
void World::testBlocks(Camera &camera, float maxDistance) {
glm::vec3 linePoint = glm::vec3(camera.x(),
camera.y(),
camera.z());
@ -224,39 +259,38 @@ void World::testCubes(Camera &camera) {
}
for(auto &it : *blocks) {
if(it->id() == 0) continue;
if(it->pos().z < linePoint.z - 10 || it->pos().z > linePoint.z + 10) continue;
if(it->pos().y < linePoint.y - 10 || it->pos().y > linePoint.y + 10) continue;
if(it->pos().x < linePoint.x - 10 || it->pos().x > linePoint.x + 10) continue;
// it->setSelected(false, -1);
it->setSelected(false, -1);
float d = -1;
s8 f = -1;
bool result = intersectionLineCube(it->pos().x, it->pos().y, it->pos().z, linePoint, directionVector, &d, &f);
bool result = intersectionLineBlock(it->pos().x, it->pos().y, it->pos().z, linePoint, directionVector, &d, &f);
if(result && (d < distance) && (d < 5)) {
if(result && (d < distance) && (d < maxDistance)) {
distance = d;
block = it.get();
face = f;
if(i == 8) chunk = currentChunk;
else if(i < 8) chunk = currentChunk->getSurroundingChunk(i);
write(1, result ? "y" : "n", 1);
DEBUG(block->pos().x, block->pos().y, block->pos().z);
}
}
}
if(block != nullptr) {
if(block) {
selectedBlock = block;
// block->setSelected(true, face);
} else {
// selectedCube->setSelected(false, -1);
block->setSelected(true, face);
}
else if (selectedBlock) {
selectedBlock->setSelected(false, -1);
}
if(chunk != nullptr) {
selectedChunk = chunk;
} else {
selectedChunk = nullptr;
}
selectedChunk = chunk;
}