added some really bad raycasting
This commit is contained in:
parent
46be697e2f
commit
ae5b2a0185
BIN
.attachments/raycasting_test.png
Normal file
BIN
.attachments/raycasting_test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
6
Notes.md
Normal file
6
Notes.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
These are just some notes on the blogpost I was following. While it was great, I thought the author might want to know where some areas were lacking (i would).
|
||||||
|
|
||||||
|
- in the definition of raycast_voxel `step` is never defined, nor explained. I'm pretty sure it's just supposed to be `step_dir` though.
|
||||||
|
- `get_voxel` returns the type `Voxel?` but `Chunk.voxels` doesn't hold a type named `Voxel` only a HashMap<ivec3, VoxelKind>
|
||||||
|
|
||||||
@ -29,3 +29,9 @@ Chunks now generate around the player in a square based on a render distance. Th
|
|||||||
Different voxel types are now supported in the data structures and passed to the shaders.
|
Different voxel types are now supported in the data structures and passed to the shaders.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## 0.6.0 : Raycasting Placing - 11/13/25
|
||||||
|
|
||||||
|
When placing a block, the program now raycasts to place where the camera is looking.
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
14
src/Camera.h
14
src/Camera.h
@ -4,7 +4,7 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
const float CAMERA_HEIGHT = 1.7f;
|
const float CAMERA_HEIGHT = 1.8f;
|
||||||
const float GRAVITY = 18.6f; // Should be in m/s^2 but it doesn't really work out with 9.8 so we double it
|
const float GRAVITY = 18.6f; // Should be in m/s^2 but it doesn't really work out with 9.8 so we double it
|
||||||
|
|
||||||
class Camera
|
class Camera
|
||||||
@ -62,11 +62,12 @@ class Camera
|
|||||||
|
|
||||||
glm::mat4 getView()
|
glm::mat4 getView()
|
||||||
{
|
{
|
||||||
glm::mat4 v = glm::lookAt(this->position,
|
glm::vec3 real_camera_pos = this->position;
|
||||||
this->target + this->position,
|
real_camera_pos.y += CAMERA_HEIGHT;
|
||||||
this->worldUp);
|
|
||||||
|
|
||||||
v = glm::translate(v, glm::vec3(0.0f, -CAMERA_HEIGHT, 0.0f));
|
glm::mat4 v = glm::lookAt(real_camera_pos,
|
||||||
|
real_camera_pos + this->target,
|
||||||
|
this->worldUp);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -92,6 +93,9 @@ class Camera
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 getEyePosition() const {
|
||||||
|
return position + glm::vec3(0.0f, CAMERA_HEIGHT, 0.0f);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -46,9 +46,19 @@ void addFace(glm::ivec3 pos, const float *faceVertices, float voxelKind, std::ve
|
|||||||
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
unsigned int vIndex = vbo.size() / VERTEX_SIZE;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
const float* v = &faceVertices[i * 6]; // Face data is still 6 floats per vertex
|
const float* v = &faceVertices[i * 6]; // Face data is still 6 floats per vertex
|
||||||
vbo.push_back(v[0] + pos.x);
|
float world_x = v[0] + pos.x;
|
||||||
vbo.push_back(v[1] + pos.y);
|
float world_y = v[1] + pos.y;
|
||||||
vbo.push_back(v[2] + pos.z);
|
float world_z = v[2] + pos.z;
|
||||||
|
|
||||||
|
// Debug: Print first vertex of first face
|
||||||
|
if (vbo.empty() && i == 0) {
|
||||||
|
std::cout << "[MESH] First vertex - Local pos: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
||||||
|
std::cout << "[MESH] First vertex - World: (" << world_x << ", " << world_y << ", " << world_z << ")" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
vbo.push_back(world_x);
|
||||||
|
vbo.push_back(world_y);
|
||||||
|
vbo.push_back(world_z);
|
||||||
vbo.push_back(v[3]);
|
vbo.push_back(v[3]);
|
||||||
vbo.push_back(v[4]);
|
vbo.push_back(v[4]);
|
||||||
vbo.push_back(v[5]);
|
vbo.push_back(v[5]);
|
||||||
@ -117,5 +127,10 @@ void Chunk::generateMesh() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Chunk::regenerateMesh() {
|
void Chunk::regenerateMesh() {
|
||||||
|
std::cout << "[REGENERATE] Regenerating mesh with " << voxels.size() << " voxels" << std::endl;
|
||||||
|
if (!voxels.empty()) {
|
||||||
|
auto first = voxels.begin();
|
||||||
|
std::cout << "[REGENERATE] First voxel at local: (" << first->first.x << ", " << first->first.y << ", " << first->first.z << ")" << std::endl;
|
||||||
|
}
|
||||||
this->generateMesh();
|
this->generateMesh();
|
||||||
}
|
}
|
||||||
|
|||||||
119
src/World.cpp
119
src/World.cpp
@ -1,10 +1,34 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// Helper function to handle negative modulo correctly
|
||||||
|
glm::ivec3 positive_modulo(glm::ivec3 value, int divisor) {
|
||||||
|
glm::ivec3 result;
|
||||||
|
result.x = ((value.x % divisor) + divisor) % divisor;
|
||||||
|
result.y = ((value.y % divisor) + divisor) % divisor;
|
||||||
|
result.z = ((value.z % divisor) + divisor) % divisor;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to correctly floor divide for chunk positions
|
||||||
|
glm::ivec3 floor_divide(glm::ivec3 value, int divisor) {
|
||||||
|
glm::ivec3 result;
|
||||||
|
result.x = (int)std::floor((float)value.x / divisor);
|
||||||
|
result.y = (int)std::floor((float)value.y / divisor);
|
||||||
|
result.z = (int)std::floor((float)value.z / divisor);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
World::World() {}
|
World::World() {}
|
||||||
|
|
||||||
void World::set_voxel(glm::ivec3 position, std::optional<VoxelKind> kind) {
|
void World::set_voxel(glm::ivec3 position, std::optional<VoxelKind> kind) {
|
||||||
glm::ivec3 chunk_position = position / CHUNK_SIZE;
|
glm::ivec3 chunk_position = floor_divide(position, CHUNK_SIZE);
|
||||||
glm::ivec3 local_position = position % CHUNK_SIZE;
|
glm::ivec3 local_position = positive_modulo(position, CHUNK_SIZE);
|
||||||
|
|
||||||
|
std::cout << "[SET_VOXEL] World pos: (" << position.x << ", " << position.y << ", " << position.z << ")" << std::endl;
|
||||||
|
std::cout << "[SET_VOXEL] Chunk pos: (" << chunk_position.x << ", " << chunk_position.y << ", " << chunk_position.z << ")" << std::endl;
|
||||||
|
std::cout << "[SET_VOXEL] Local pos: (" << local_position.x << ", " << local_position.y << ", " << local_position.z << ")" << std::endl;
|
||||||
|
|
||||||
Chunk * chunk = get_or_create_chunk(chunk_position);
|
Chunk * chunk = get_or_create_chunk(chunk_position);
|
||||||
if (!kind.has_value()) {
|
if (!kind.has_value()) {
|
||||||
@ -22,11 +46,11 @@ Chunk* World::get_or_create_chunk(glm::ivec3 chunk_position) {
|
|||||||
// Fill in new chunk with a flat plane of voxels at y=0
|
// Fill in new chunk with a flat plane of voxels at y=0
|
||||||
std::unordered_map<glm::ivec3, VoxelKind> voxels;
|
std::unordered_map<glm::ivec3, VoxelKind> voxels;
|
||||||
if (chunk_position.y == 0) {
|
if (chunk_position.y == 0) {
|
||||||
for (int z = 0; z <= CHUNK_SIZE; z++) {
|
for (int z = 0; z < CHUNK_SIZE; z++) {
|
||||||
for (int y = 0; y <= CHUNK_SIZE; y++) {
|
for (int y = 0; y < CHUNK_SIZE; y++) {
|
||||||
for (int x = 0; x <= CHUNK_SIZE; x++) {
|
for (int x = 0; x < CHUNK_SIZE; x++) {
|
||||||
glm::ivec3 offset = glm::ivec3(x, y, z);
|
glm::ivec3 offset = glm::ivec3(x, y, z);
|
||||||
glm::ivec3 world_voxel_position = chunk_position * 32 + offset;
|
glm::ivec3 world_voxel_position = chunk_position * CHUNK_SIZE + offset;
|
||||||
|
|
||||||
if (world_voxel_position.y == 0) {
|
if (world_voxel_position.y == 0) {
|
||||||
voxels[offset] = VoxelKind::Dirt;
|
voxels[offset] = VoxelKind::Dirt;
|
||||||
@ -42,3 +66,86 @@ Chunk* World::get_or_create_chunk(glm::ivec3 chunk_position) {
|
|||||||
}
|
}
|
||||||
return &this->chunks[chunk_position];
|
return &this->chunks[chunk_position];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> World::raycast_voxel(glm::vec3 start, glm::vec3 direction, float max_dist) {
|
||||||
|
// Normalize direction to ensure consistent behavior
|
||||||
|
direction = glm::normalize(direction);
|
||||||
|
|
||||||
|
std::cout << "[RAYCAST] Start: (" << start.x << ", " << start.y << ", " << start.z << ")" << std::endl;
|
||||||
|
std::cout << "[RAYCAST] Direction: (" << direction.x << ", " << direction.y << ", " << direction.z << ")" << std::endl;
|
||||||
|
|
||||||
|
glm::ivec3 pos = glm::ivec3(std::floor(start.x), std::floor(start.y), std::floor(start.z));
|
||||||
|
std::cout << "[RAYCAST] Starting voxel: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
||||||
|
|
||||||
|
// (+1 or -1 for each axis)
|
||||||
|
glm::ivec3 step_dir = glm::sign(direction);
|
||||||
|
std::cout << "[RAYCAST] Step direction: (" << step_dir.x << ", " << step_dir.y << ", " << step_dir.z << ")" << std::endl;
|
||||||
|
|
||||||
|
// How far to step in each axis
|
||||||
|
const float epsilon = 0.0001f;
|
||||||
|
glm::vec3 safe_dir = glm::vec3(
|
||||||
|
abs(direction.x) < epsilon ? epsilon : direction.x,
|
||||||
|
abs(direction.y) < epsilon ? epsilon : direction.y,
|
||||||
|
abs(direction.z) < epsilon ? epsilon : direction.z
|
||||||
|
);
|
||||||
|
|
||||||
|
glm::vec3 delta = glm::abs(1.0f / safe_dir);
|
||||||
|
|
||||||
|
glm::vec3 fract = start - glm::vec3(pos);
|
||||||
|
glm::vec3 t_max = glm::vec3(
|
||||||
|
(step_dir.x > 0 ? (1.0f - fract.x) : fract.x) * delta.x,
|
||||||
|
(step_dir.y > 0 ? (1.0f - fract.y) : fract.y) * delta.y,
|
||||||
|
(step_dir.z > 0 ? (1.0f - fract.z) : fract.z) * delta.z
|
||||||
|
);
|
||||||
|
|
||||||
|
float dist = 0.0f;
|
||||||
|
glm::ivec3 last_move = glm::ivec3(0, 0, 0);
|
||||||
|
|
||||||
|
int iterations = 0;
|
||||||
|
const int max_iterations = 100; // Safety limit
|
||||||
|
|
||||||
|
while (dist < max_dist && iterations < max_iterations) {
|
||||||
|
iterations++;
|
||||||
|
|
||||||
|
std::cout << "[RAYCAST] Iteration " << iterations << " at voxel (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
||||||
|
|
||||||
|
if (this->get_voxel(pos).has_value()) {
|
||||||
|
std::cout << "[RAYCAST] Hit voxel at (" << pos.x << ", " << pos.y << ", " << pos.z << ") after " << iterations << " iterations" << std::endl;
|
||||||
|
std::cout << "[RAYCAST] Returning normal: (" << -last_move.x << ", " << -last_move.y << ", " << -last_move.z << ")" << std::endl;
|
||||||
|
return std::make_pair(pos, -last_move);
|
||||||
|
}
|
||||||
|
|
||||||
|
// step in the axis with the smallest t_max - that's the next voxel boundary
|
||||||
|
if (t_max.x < t_max.y && t_max.x < t_max.z) {
|
||||||
|
pos.x += step_dir.x;
|
||||||
|
last_move = glm::ivec3(step_dir.x, 0, 0);
|
||||||
|
dist = t_max.x;
|
||||||
|
t_max.x += delta.x;
|
||||||
|
} else if (t_max.y < t_max.z) {
|
||||||
|
pos.y += step_dir.y;
|
||||||
|
last_move = glm::ivec3(0, step_dir.y, 0);
|
||||||
|
dist = t_max.y;
|
||||||
|
t_max.y += delta.y;
|
||||||
|
} else {
|
||||||
|
pos.z += step_dir.z;
|
||||||
|
last_move = glm::ivec3(0, 0, step_dir.z);
|
||||||
|
dist = t_max.z;
|
||||||
|
t_max.z += delta.z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "[RAYCAST] No voxel hit after " << iterations << " iterations, dist=" << dist << std::endl;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<VoxelKind> World::get_voxel(glm::ivec3 position) {
|
||||||
|
glm::ivec3 chunk_position = floor_divide(position, CHUNK_SIZE);
|
||||||
|
glm::ivec3 local_position = positive_modulo(position, CHUNK_SIZE);
|
||||||
|
|
||||||
|
Chunk* chunk = this->get_or_create_chunk(chunk_position);
|
||||||
|
auto it = chunk->voxels.find(local_position);
|
||||||
|
if (it != chunk->voxels.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|||||||
@ -17,6 +17,10 @@ class World
|
|||||||
|
|
||||||
void set_voxel(glm::ivec3 position, std::optional<VoxelKind> kind);
|
void set_voxel(glm::ivec3 position, std::optional<VoxelKind> kind);
|
||||||
|
|
||||||
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_voxel(glm::vec3 start, glm::vec3 direction, float max_dist);
|
||||||
|
|
||||||
|
std::optional<VoxelKind> get_voxel(glm::ivec3 position);
|
||||||
|
|
||||||
Chunk* get_or_create_chunk(glm::ivec3 chunk_position);
|
Chunk* get_or_create_chunk(glm::ivec3 chunk_position);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
129
src/main.cpp
129
src/main.cpp
@ -33,7 +33,7 @@ const int VIEW_DISTANCE = 4; // In Chunks
|
|||||||
bool W_pressed, S_pressed, A_pressed, D_pressed = false;
|
bool W_pressed, S_pressed, A_pressed, D_pressed = false;
|
||||||
|
|
||||||
glm::mat4 projection = glm::mat4(1.0f);
|
glm::mat4 projection = glm::mat4(1.0f);
|
||||||
Camera camera = Camera(CAMERA_SPEED, glm::vec3(0.0f, 1.0f, 3.0f));
|
Camera camera = Camera(CAMERA_SPEED, glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
// Callback function for when the window is resized
|
// Callback function for when the window is resized
|
||||||
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
|
||||||
@ -86,10 +86,6 @@ void mouse_callback(GLFWwindow * window, double xpos, double ypos)
|
|||||||
direction.y = -sin(glm::radians(pitch));
|
direction.y = -sin(glm::radians(pitch));
|
||||||
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
|
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||||
camera.target = glm::normalize(direction);
|
camera.target = glm::normalize(direction);
|
||||||
|
|
||||||
if(glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_2) == GLFW_PRESS) {
|
|
||||||
world.set_voxel(glm::ivec3(camera.position), VoxelKind::Stone);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
|
||||||
@ -176,6 +172,57 @@ void processInput(GLFWwindow *window)
|
|||||||
camera.speed = CAMERA_SPEED * 7.5;
|
camera.speed = CAMERA_SPEED * 7.5;
|
||||||
if(glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_RELEASE)
|
if(glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_RELEASE)
|
||||||
camera.speed = CAMERA_SPEED * 20;
|
camera.speed = CAMERA_SPEED * 20;
|
||||||
|
|
||||||
|
static bool left_mouse_pressed = false;
|
||||||
|
static bool right_mouse_pressed = false;
|
||||||
|
|
||||||
|
// Left click - place block
|
||||||
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS && !left_mouse_pressed) {
|
||||||
|
left_mouse_pressed = true;
|
||||||
|
std::cout << "\n=== LEFT CLICK (PLACE) ===" << std::endl;
|
||||||
|
std::cout << "Camera eye pos: (" << camera.getEyePosition().x << ", " << camera.getEyePosition().y << ", " << camera.getEyePosition().z << ")" << std::endl;
|
||||||
|
std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
|
||||||
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
||||||
|
world.raycast_voxel(camera.getEyePosition(), camera.target, 3);
|
||||||
|
|
||||||
|
if (raycast_result.has_value()) {
|
||||||
|
auto [target_block, normal] = raycast_result.value();
|
||||||
|
std::cout << "Hit block at: (" << target_block.x << ", " << target_block.y << ", " << target_block.z << ")" << std::endl;
|
||||||
|
std::cout << "Normal: (" << normal.x << ", " << normal.y << ", " << normal.z << ")" << std::endl;
|
||||||
|
glm::ivec3 place_pos = target_block + normal;
|
||||||
|
std::cout << "Placing at: (" << place_pos.x << ", " << place_pos.y << ", " << place_pos.z << ")" << std::endl;
|
||||||
|
world.set_voxel(place_pos, VoxelKind::Stone);
|
||||||
|
} else {
|
||||||
|
std::cout << "No block hit within range" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE) {
|
||||||
|
left_mouse_pressed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right click - remove block
|
||||||
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS && !right_mouse_pressed) {
|
||||||
|
right_mouse_pressed = true;
|
||||||
|
std::cout << "\n=== RIGHT CLICK (REMOVE) ===" << std::endl;
|
||||||
|
std::cout << "Camera eye pos: (" << camera.getEyePosition().x << ", " << camera.getEyePosition().y << ", " << camera.getEyePosition().z << ")" << std::endl;
|
||||||
|
std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
|
||||||
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
||||||
|
world.raycast_voxel(camera.getEyePosition(), camera.target, 3);
|
||||||
|
|
||||||
|
if (raycast_result.has_value()) {
|
||||||
|
auto [target_block, normal] = raycast_result.value();
|
||||||
|
std::cout << "Hit block at: (" << target_block.x << ", " << target_block.y << ", " << target_block.z << ")" << std::endl;
|
||||||
|
std::cout << "Removing block at: (" << target_block.x << ", " << target_block.y << ", " << target_block.z << ")" << std::endl;
|
||||||
|
world.set_voxel(target_block, std::nullopt);
|
||||||
|
} else {
|
||||||
|
std::cout << "No block hit within range" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_RELEASE) {
|
||||||
|
right_mouse_pressed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@ -189,7 +236,7 @@ int main() {
|
|||||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
|
||||||
// 2. --- Create a Window ---
|
// 2. --- Create a Window ---
|
||||||
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Voxel Engine 0.5.0", NULL, NULL);
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Voxel Engine 0.6.0", NULL, NULL);
|
||||||
if (window == NULL) {
|
if (window == NULL) {
|
||||||
std::cerr << "Failed to create GLFW window" << std::endl;
|
std::cerr << "Failed to create GLFW window" << std::endl;
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
@ -227,6 +274,30 @@ int main() {
|
|||||||
// Setup projection matrix
|
// Setup projection matrix
|
||||||
projection = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / (float)SCR_HEIGHT, Z_NEAR, Z_FAR); // This doesn't need to be recalculated every frame
|
projection = glm::perspective(glm::radians(FOV), (float)SCR_WIDTH / (float)SCR_HEIGHT, Z_NEAR, Z_FAR); // This doesn't need to be recalculated every frame
|
||||||
|
|
||||||
|
// Setup crosshair
|
||||||
|
unsigned int crosshairVAO, crosshairVBO;
|
||||||
|
glGenVertexArrays(1, &crosshairVAO);
|
||||||
|
glGenBuffers(1, &crosshairVBO);
|
||||||
|
|
||||||
|
glBindVertexArray(crosshairVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, crosshairVBO);
|
||||||
|
|
||||||
|
// Crosshair vertices in NDC (Normalized Device Coordinates: -1 to 1)
|
||||||
|
float crosshairSize = 0.02f; // Size in NDC
|
||||||
|
float crosshairVertices[] = {
|
||||||
|
// Horizontal line
|
||||||
|
-crosshairSize, 0.0f, 0.0f,
|
||||||
|
crosshairSize, 0.0f, 0.0f,
|
||||||
|
// Vertical line
|
||||||
|
0.0f, -crosshairSize, 0.0f,
|
||||||
|
0.0f, crosshairSize, 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(crosshairVertices), crosshairVertices, GL_STATIC_DRAW);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
glm::mat4 view;
|
glm::mat4 view;
|
||||||
double start_time = glfwGetTime();
|
double start_time = glfwGetTime();
|
||||||
double move_time = glfwGetTime();
|
double move_time = glfwGetTime();
|
||||||
@ -246,15 +317,19 @@ int main() {
|
|||||||
|
|
||||||
shader.use();
|
shader.use();
|
||||||
|
|
||||||
if (!debug_printed) {
|
// if (!debug_printed) {
|
||||||
std::cout << "\n=== RENDER DEBUG ===" << std::endl;
|
// std::cout << "\n=== RENDER DEBUG ===" << std::endl;
|
||||||
std::cout << "Camera pos: (" << camera.position.x << ", " << camera.position.y << ", " << camera.position.z << ")" << std::endl;
|
// std::cout << "Camera pos: (" << camera.position.x << ", " << camera.position.y << ", " << camera.position.z << ")" << std::endl;
|
||||||
std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
// std::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
// std::cout << "Number of chunks to draw: " << world.chunks.size() << std::endl;
|
// // std::cout << "Number of chunks to draw: " << world.chunks.size() << std::endl;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Generate chunks around the camera
|
// Generate chunks around the camera
|
||||||
glm::ivec3 camera_chunk = glm::ivec3(camera.position) / CHUNK_SIZE;
|
glm::ivec3 camera_chunk = glm::ivec3(
|
||||||
|
std::floor(camera.position.x / CHUNK_SIZE),
|
||||||
|
std::floor(camera.position.y / CHUNK_SIZE),
|
||||||
|
std::floor(camera.position.z / CHUNK_SIZE)
|
||||||
|
);
|
||||||
|
|
||||||
// ---- PASS 1: Draw solid grey cubes ----
|
// ---- PASS 1: Draw solid grey cubes ----
|
||||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||||
@ -276,16 +351,26 @@ int main() {
|
|||||||
Chunk* chunk = world.get_or_create_chunk(chunk_pos);
|
Chunk* chunk = world.get_or_create_chunk(chunk_pos);
|
||||||
|
|
||||||
Mesh* chunk_mesh = chunk->getMesh();
|
Mesh* chunk_mesh = chunk->getMesh();
|
||||||
if (chunk_mesh)
|
if (chunk_mesh) {
|
||||||
|
// Debug: Log when rendering chunks with your placed block
|
||||||
|
static bool logged_placed_block = false;
|
||||||
|
if (!logged_placed_block && chunk->voxels.count(glm::ivec3(0, 1, 31)) > 0) {
|
||||||
|
std::cout << "\n[RENDER] ===== FOUND PLACED BLOCK =====" << std::endl;
|
||||||
|
std::cout << "[RENDER] Drawing chunk at pos (" << chunk_pos.x << ", " << chunk_pos.y << ", " << chunk_pos.z << ")" << std::endl;
|
||||||
|
std::cout << "[RENDER] Translation: (" << (chunk_pos.x * CHUNK_SIZE) << ", " << (chunk_pos.y * CHUNK_SIZE) << ", " << (chunk_pos.z * CHUNK_SIZE) << ")" << std::endl;
|
||||||
|
std::cout << "[RENDER] Final world position should be: (" << (chunk_pos.x * CHUNK_SIZE + 0) << ", " << (chunk_pos.y * CHUNK_SIZE + 1) << ", " << (chunk_pos.z * CHUNK_SIZE + 31) << ")" << std::endl;
|
||||||
|
logged_placed_block = true;
|
||||||
|
}
|
||||||
chunk_mesh->draw();
|
chunk_mesh->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug_printed) {
|
|
||||||
debug_printed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (!debug_printed) {
|
||||||
|
// debug_printed = true;
|
||||||
|
// }
|
||||||
|
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
// ---- PASS 2: Draw wireframe on top ----
|
// ---- PASS 2: Draw wireframe on top ----
|
||||||
@ -315,6 +400,16 @@ int main() {
|
|||||||
// --- Reset polygon mode for next frame (good practice) ---
|
// --- Reset polygon mode for next frame (good practice) ---
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
// ---- Draw Crosshair ----
|
||||||
|
glDisable(GL_DEPTH_TEST); // Draw on top of everything
|
||||||
|
shader.use();
|
||||||
|
shader.setMat4("u_mvp", glm::mat4(1.0f)); // Identity matrix (NDC coordinates)
|
||||||
|
shader.setVec3("u_Color", glm::vec3(1.0f, 1.0f, 1.0f)); // White
|
||||||
|
glBindVertexArray(crosshairVAO);
|
||||||
|
glDrawArrays(GL_LINES, 0, 4); // 4 vertices = 2 lines
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
double end_time = glfwGetTime();
|
double end_time = glfwGetTime();
|
||||||
float time_since_last_move = end_time - move_time;
|
float time_since_last_move = end_time - move_time;
|
||||||
if (time_since_last_move >= 0.017)
|
if (time_since_last_move >= 0.017)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user