[TODO] Added. [Chunk|World] Mouse picking: WIP.
This commit is contained in:
parent
3c76f5ebaa
commit
23630138d4
60
TODO
Normal file
60
TODO
Normal file
@ -0,0 +1,60 @@
|
||||
TODO
|
||||
|
||||
# Nettoyage
|
||||
|
||||
• TODO: Vérifier les utilisations inutiles de pointeurs
|
||||
• TODO: Nettoyer les vieux headers
|
||||
• TODO: `Types.hpp` → `IntTypes.hpp`
|
||||
• TODO: Remplacer les anciennes classes par leur upgrade:
|
||||
◦ TODO: `ApplicationState` / `ApplicationStateStack`
|
||||
◦ TODO: `GameClock`
|
||||
◦ TODO: `Window` (depuis `ZeldaOOL`)
|
||||
◦ TODO: `Debug` / `Exception` (+ gestion dans le `main()`)
|
||||
◦ TODO: Input system (Mouse + Keyboard)
|
||||
• TODO: Découper les gros pâtés en sous-classes
|
||||
• TODO: Séparer le code client du code serveur
|
||||
|
||||
# ToDoList
|
||||
|
||||
## Joueur
|
||||
|
||||
• TODO: Collisions + Gravité
|
||||
◦ TODO: Système d’entités (réutiliser l’ECS mais en multi-thread)
|
||||
• TODO: Ciblage de bloc
|
||||
◦ TODO: Ajout de bloc
|
||||
◦ TODO: Suppression de bloc
|
||||
|
||||
## Items
|
||||
|
||||
• TODO: Créer un système d’items
|
||||
◦ TODO: Inventaire basique (1 slot)
|
||||
◦ TODO: Récupération du bloc cassé
|
||||
• TODO: Faire un vrai drop d’item
|
||||
• TODO: Ajouter les animations de destruction des blocs
|
||||
|
||||
## Monde
|
||||
|
||||
• TODO: Cycle jour/nuit
|
||||
◦ TODO: Dynamic lighting
|
||||
• TODO: Chargement des chunks multi-thread
|
||||
|
||||
## Génération
|
||||
|
||||
• TODO: Augmenter la hauteur du terrain
|
||||
• TODO: Dirt + Grass
|
||||
• TODO: WATEEEEEEER
|
||||
• TODO: Arbres
|
||||
• TODO: Fleurs (emit light at night?)
|
||||
• TODO: Biomes
|
||||
• TODO: Génération multi-thread
|
||||
|
||||
## Affichage
|
||||
|
||||
• TODO: Optimiser au maximum l’affichage des chunks
|
||||
◦ TODO: Faire le max de culling
|
||||
▸ DONE: Face culling
|
||||
▸ DONE: Frustum culling
|
||||
▸ TODO: Occlusion culling
|
||||
◦ TODO: Face-merging
|
||||
→ Trouver une solution pour utiliser un texture atlas avec ça
|
||||
|
@ -5,13 +5,9 @@
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 14/12/2014 13:45:14
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Quentin BAZIN, <quent42340@gmail.com>
|
||||
* Company:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@ -23,4 +19,7 @@
|
||||
|
||||
#define APP_NAME "KubKraft"
|
||||
|
||||
#define DIST_NEAR 0.1f
|
||||
#define DIST_FAR 1000.0f
|
||||
|
||||
#endif // CONFIG_HPP_
|
||||
|
@ -5,13 +5,9 @@
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 29/12/2014 04:56:02
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Quentin BAZIN, <quent42340@gmail.com>
|
||||
* Company:
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
@ -24,13 +20,17 @@
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block(u32 id);
|
||||
Block(const glm::vec3 &pos, u32 id);
|
||||
|
||||
glm::vec4 getTexCoords();
|
||||
|
||||
const glm::vec3 &pos() const { return m_pos; }
|
||||
|
||||
u32 id() const { return m_id; }
|
||||
|
||||
private:
|
||||
glm::vec3 m_pos;
|
||||
|
||||
u32 m_id;
|
||||
};
|
||||
|
||||
|
@ -32,9 +32,11 @@ class Chunk : public NonCopyable {
|
||||
|
||||
void draw(Shader &shader);
|
||||
|
||||
void addBlock(u32 id);
|
||||
Block *getBlock(s8 x, s8 y, s8 z);
|
||||
|
||||
void addBlock(const glm::vec3 &pos, u32 id);
|
||||
void setBlock(const glm::vec3 &pos, u32 id);
|
||||
|
||||
u32 getCoordID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate);
|
||||
|
||||
u32 getVertexID(u8 x, u8 y, u8 z, u8 i, u8 j, u8 coordinate);
|
||||
@ -46,10 +48,13 @@ class Chunk : public NonCopyable {
|
||||
s32 y() const { return m_y; }
|
||||
s32 z() const { return m_z; }
|
||||
|
||||
const std::vector<std::unique_ptr<Block>> &data() const { return m_data; }
|
||||
|
||||
Chunk *left() const { return m_surroundingChunks[0]; }
|
||||
Chunk *right() const { return m_surroundingChunks[1]; }
|
||||
Chunk *front() const { return m_surroundingChunks[2]; }
|
||||
Chunk *back() const { return m_surroundingChunks[3]; }
|
||||
Chunk *getSurroundingChunk(u8 i) { return (i > 3) ? nullptr : m_surroundingChunks[i]; }
|
||||
|
||||
static const u8 width = 16;
|
||||
static const u8 height = 32;
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "Chunk.hpp"
|
||||
#include "TerrainGenerator.hpp"
|
||||
|
||||
class Camera;
|
||||
|
||||
class World {
|
||||
public:
|
||||
World();
|
||||
@ -27,9 +29,20 @@ class World {
|
||||
|
||||
Chunk *getChunk(s32 x, s32 z);
|
||||
|
||||
void addSelectedBlock() { if(!selectedChunk || !selectedBlock) return; selectedChunk->setBlock(selectedBlock->pos(), 1); selectedChunk->update(); }
|
||||
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);
|
||||
|
||||
// Render distance in chunks
|
||||
static const u16 renderDistance = 8;
|
||||
|
||||
// FIXME: MOVE THIS QUICKLY
|
||||
static Block *selectedBlock;
|
||||
static Chunk *selectedChunk;
|
||||
|
||||
private:
|
||||
s32 m_width;
|
||||
s32 m_depth;
|
||||
|
@ -35,14 +35,14 @@ int main(int, char *[]) {
|
||||
std::cerr << "Fatal error " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch(const std::exception &e) {
|
||||
std::cerr << "Exception caught: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
catch(...) {
|
||||
std::cerr << "Fatal error: Unknown error." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
// catch(const std::exception &e) {
|
||||
// std::cerr << "Exception caught: " << e.what() << std::endl;
|
||||
// return 1;
|
||||
// }
|
||||
// catch(...) {
|
||||
// std::cerr << "Fatal error: Unknown error." << std::endl;
|
||||
// return 1;
|
||||
// }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,7 +14,10 @@
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
#include "Config.hpp"
|
||||
#include "Mouse.hpp"
|
||||
#include "GameState.hpp"
|
||||
|
||||
GameState::GameState() : m_camera(Camera::getInstance()) {
|
||||
@ -30,7 +33,8 @@ GameState::GameState() : m_camera(Camera::getInstance()) {
|
||||
|
||||
Shader::bind(&m_shader);
|
||||
|
||||
m_projectionMatrix = glm::perspective(45.0f, (float)SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 1000.0f);
|
||||
// m_projectionMatrix = glm::perspective(45.0f, (float)SCREEN_WIDTH / SCREEN_HEIGHT, DIST_NEAR, DIST_FAR);
|
||||
m_projectionMatrix = glm::perspective(45.0f, (float)SCREEN_WIDTH / SCREEN_HEIGHT, DIST_NEAR, DIST_FAR);
|
||||
m_viewMatrix = m_camera.update();
|
||||
|
||||
m_shader.setUniform("u_projectionMatrix", m_projectionMatrix);
|
||||
@ -42,6 +46,12 @@ GameState::GameState() : m_camera(Camera::getInstance()) {
|
||||
|
||||
void GameState::update() {
|
||||
m_viewMatrix = m_camera.processInputs();
|
||||
|
||||
// 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.removeSelectedBlock();
|
||||
}
|
||||
|
||||
void GameState::draw() {
|
||||
|
@ -5,19 +5,15 @@
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Version: 1.0
|
||||
* Created: 29/12/2014 04:56:17
|
||||
* Revision: none
|
||||
* Compiler: gcc
|
||||
*
|
||||
* Author: Quentin BAZIN, <quent42340@gmail.com>
|
||||
* Company:
|
||||
* Author: Quentin Bazin, <quent42340@gmail.com>
|
||||
*
|
||||
* =====================================================================================
|
||||
*/
|
||||
#include "Block.hpp"
|
||||
|
||||
Block::Block(u32 id) {
|
||||
Block::Block(const glm::vec3 &pos, u32 id) : m_pos(pos) {
|
||||
m_id = id;
|
||||
}
|
||||
|
||||
@ -31,6 +27,6 @@ glm::vec4 Block::getTexCoords() {
|
||||
return glm::vec4(textureX,
|
||||
textureY,
|
||||
textureX + 16.0f / textureWidth,
|
||||
textureY + 16.0f / textureHeight);
|
||||
textureY + 16.0f / textureHeight);
|
||||
}
|
||||
|
||||
|
@ -211,6 +211,61 @@ void Chunk::update() {
|
||||
VertexBuffer::bind(nullptr);
|
||||
}
|
||||
|
||||
class Ray {
|
||||
public:
|
||||
Ray(const glm::vec3 &orig, const glm::vec3 &dir) : orig(orig), dir(dir)
|
||||
{
|
||||
invdir.x = 1 / dir.x;
|
||||
invdir.y = 1 / dir.y;
|
||||
invdir.z = 1 / dir.z;
|
||||
sign[0] = (invdir.x < 0);
|
||||
sign[1] = (invdir.y < 0);
|
||||
sign[2] = (invdir.z < 0);
|
||||
}
|
||||
glm::vec3 orig, dir; // ray orig and dir
|
||||
glm::vec3 invdir;
|
||||
int sign[3];
|
||||
};
|
||||
|
||||
class AxisAlignedBB {
|
||||
public:
|
||||
AxisAlignedBB(const glm::vec3 &vmin, const glm::vec3 &vmax)
|
||||
{
|
||||
bounds[0] = vmin;
|
||||
bounds[1] = vmax;
|
||||
}
|
||||
glm::vec3 bounds[2];
|
||||
|
||||
bool intersect(const Ray &r) const
|
||||
{
|
||||
float tmin, tmax, tymin, tymax, tzmin, tzmax;
|
||||
|
||||
tmin = (bounds[r.sign[0]].x - r.orig.x) * r.invdir.x;
|
||||
tmax = (bounds[1-r.sign[0]].x - r.orig.x) * r.invdir.x;
|
||||
tymin = (bounds[r.sign[1]].y - r.orig.y) * r.invdir.y;
|
||||
tymax = (bounds[1-r.sign[1]].y - r.orig.y) * r.invdir.y;
|
||||
|
||||
if ((tmin > tymax) || (tymin > tmax))
|
||||
return false;
|
||||
if (tymin > tmin)
|
||||
tmin = tymin;
|
||||
if (tymax < tmax)
|
||||
tmax = tymax;
|
||||
|
||||
tzmin = (bounds[r.sign[2]].z - r.orig.z) * r.invdir.z;
|
||||
tzmax = (bounds[1-r.sign[2]].z - r.orig.z) * r.invdir.z;
|
||||
|
||||
if ((tmin > tzmax) || (tzmin > tmax))
|
||||
return false;
|
||||
if (tzmin > tmin)
|
||||
tmin = tzmin;
|
||||
if (tzmax < tmax)
|
||||
tmax = tzmax;
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void Chunk::draw(Shader &shader) {
|
||||
if(m_isChanged) update();
|
||||
|
||||
@ -243,8 +298,17 @@ void Chunk::draw(Shader &shader) {
|
||||
VertexBuffer::bind(nullptr);
|
||||
}
|
||||
|
||||
void Chunk::addBlock(u32 id) {
|
||||
m_data.push_back(std::unique_ptr<Block>(new Block(id)));
|
||||
void Chunk::addBlock(const glm::vec3 &pos, u32 id) {
|
||||
m_data.push_back(std::unique_ptr<Block>(new Block(pos, id)));
|
||||
}
|
||||
|
||||
void Chunk::setBlock(const glm::vec3 &pos, u32 id) {
|
||||
glm::vec3 localPos = pos;
|
||||
localPos.x -= m_x * width;
|
||||
localPos.y -= m_y * height;
|
||||
localPos.z -= m_z * depth;
|
||||
|
||||
m_data.at(localPos.y + localPos.x * height + localPos.z * height * width).reset(new Block(pos, id));
|
||||
}
|
||||
|
||||
Block *Chunk::getBlock(s8 x, s8 y, s8 z) {
|
||||
|
@ -14,8 +14,13 @@
|
||||
#define GLM_FORCE_RADIANS
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "Camera.hpp"
|
||||
#include "Config.hpp"
|
||||
#include "World.hpp"
|
||||
|
||||
Block *World::selectedBlock = nullptr;
|
||||
Chunk *World::selectedChunk = nullptr;
|
||||
|
||||
World::World() {
|
||||
m_width = 100;
|
||||
m_depth = 100;
|
||||
@ -113,3 +118,145 @@ Chunk *World::getChunk(s32 x, s32 z) {
|
||||
return m_chunks.at(x + z * m_width).get();
|
||||
}
|
||||
|
||||
// FIXME: Move to a math module
|
||||
bool World::intersectionLinePlane(const glm::vec3 &normal, const glm::vec3 &planePoint, const glm::vec3 &lineOrigPoint, const glm::vec3 &directionVector, float *distance) {
|
||||
float p1 = directionVector.x * normal.x + directionVector.y * normal.y + directionVector.z * normal.z; // First point to be tested
|
||||
|
||||
if(p1 == 0) return false; // Degenerate case
|
||||
|
||||
glm::vec3 u = glm::vec3(planePoint.x - lineOrigPoint.x,
|
||||
planePoint.y - lineOrigPoint.y,
|
||||
planePoint.z - lineOrigPoint.z);
|
||||
|
||||
float p2 = u.x * normal.x + u.y * normal.y + u.z * normal.z; // Second point to be tested
|
||||
|
||||
float k = p2 / p1;
|
||||
|
||||
if((k < 0) || (k > 5)) return false;
|
||||
|
||||
// Intersection point
|
||||
glm::vec3 i = glm::vec3(lineOrigPoint.x + k * directionVector.x,
|
||||
lineOrigPoint.y + k * directionVector.y,
|
||||
lineOrigPoint.z + k * directionVector.z);
|
||||
|
||||
glm::vec3 v = glm::vec3(i.x - planePoint.x,
|
||||
i.y - planePoint.y,
|
||||
i.z - planePoint.z);
|
||||
|
||||
float size = 0.5;
|
||||
|
||||
if(v.x >= -size && v.x <= size && v.y >= -size && v.y <= size && v.z >= -size && v.z <= size) {
|
||||
if(distance != nullptr) *distance = k;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Front right = 0 | Front left = 1
|
||||
// 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) {
|
||||
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 normal[6] = {
|
||||
glm::vec3(0, 1, 0), // back
|
||||
glm::vec3(1, 0, 0), // right
|
||||
glm::vec3(-1, 0, 0), // left
|
||||
glm::vec3(0, -1, 0), // front
|
||||
glm::vec3(0, 0, 1), // top
|
||||
glm::vec3(0, 0, -1) // bottom
|
||||
};
|
||||
|
||||
float shortestDistance = DIST_FAR;
|
||||
float dist = DIST_FAR + 1.0;
|
||||
int nearestFace = -1;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
bool result = intersectionLinePlane(normal[i], planePoint[i], lineOrigPoint, directionVector, &dist);
|
||||
if (result && (dist < shortestDistance)) {
|
||||
shortestDistance = dist;
|
||||
nearestFace = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (nearestFace < 0) {
|
||||
return false;
|
||||
} else {
|
||||
if (distance != nullptr) *distance = shortestDistance;
|
||||
if (face != nullptr) *face = nearestFace;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unistd.h>
|
||||
|
||||
// FIXME: MOVE THIS FUNCTION
|
||||
void World::testCubes(Camera &camera) {
|
||||
glm::vec3 linePoint = glm::vec3(camera.x(),
|
||||
camera.y(),
|
||||
camera.z());
|
||||
|
||||
glm::vec3 directionVector = glm::vec3(camera.pointTargetedX() - camera.x(),
|
||||
camera.pointTargetedY() - camera.y(),
|
||||
camera.pointTargetedZ() - camera.z());
|
||||
|
||||
Chunk *currentChunk = getChunk(camera.x() / Chunk::width, camera.z() / Chunk::depth);
|
||||
float distance = DIST_FAR;
|
||||
Block *block = nullptr;
|
||||
int face = -1;
|
||||
Chunk *chunk = nullptr;
|
||||
const std::vector<std::unique_ptr<Block>> *blocks = nullptr;
|
||||
for(unsigned short i = 0 ; i < 9 ; i++) {
|
||||
if(i == 8) blocks = ¤tChunk->data();
|
||||
else if(i < 8) {
|
||||
if(currentChunk->getSurroundingChunk(i) == nullptr) continue;
|
||||
blocks = ¤tChunk->getSurroundingChunk(i)->data();
|
||||
}
|
||||
|
||||
for(auto &it : *blocks) {
|
||||
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);
|
||||
|
||||
float d = -1;
|
||||
s8 f = -1;
|
||||
|
||||
bool result = intersectionLineCube(it->pos().x, it->pos().y, it->pos().z, linePoint, directionVector, &d, &f);
|
||||
|
||||
if(result && (d < distance) && (d < 5)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(block != nullptr) {
|
||||
selectedBlock = block;
|
||||
// block->setSelected(true, face);
|
||||
} else {
|
||||
// selectedCube->setSelected(false, -1);
|
||||
}
|
||||
|
||||
if(chunk != nullptr) {
|
||||
selectedChunk = chunk;
|
||||
} else {
|
||||
selectedChunk = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,9 +26,9 @@ void TerrainGenerator::generate(Chunk &chunk) {
|
||||
|
||||
for(u8 y = 0 ; y < Chunk::height ; y++) {
|
||||
if(y + chunk.y() * Chunk::height < h) {
|
||||
chunk.addBlock(1);
|
||||
chunk.addBlock(glm::vec3{x + chunk.x() * Chunk::width, y + chunk.y() * Chunk::height, z + chunk.z() * Chunk::depth}, 1);
|
||||
} else {
|
||||
chunk.addBlock(0);
|
||||
chunk.addBlock(glm::vec3{x + chunk.x() * Chunk::width, y + chunk.y() * Chunk::height, z + chunk.z() * Chunk::depth}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user