Merge pull request 'Fixed Raycasting' (#1) from raycast-debug into main
Reviewed-on: https://git.0x01fe.net/0x01FE/voxel-engine/pulls/1
This commit is contained in:
commit
c5bc26b630
BIN
.attachments/fixed-raycast.png
Normal file
BIN
.attachments/fixed-raycast.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
@ -35,3 +35,9 @@ Different voxel types are now supported in the data structures and passed to the
|
|||||||
When placing a block, the program now raycasts to place where the camera is looking.
|
When placing a block, the program now raycasts to place where the camera is looking.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### 0.6.1 : Raycast Bug Fixes - 11/17/25
|
||||||
|
|
||||||
|
It took me a couple of days to fix the ray casting. I forgot that my mesh is offset by 0.5, so 3/4 raycasts looked at least a block off of what the camera was looking at.
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
@ -71,32 +71,56 @@ std::optional<std::pair<glm::ivec3, glm::ivec3>> World::raycast_voxel(glm::vec3
|
|||||||
// Normalize direction to ensure consistent behavior
|
// Normalize direction to ensure consistent behavior
|
||||||
direction = glm::normalize(direction);
|
direction = glm::normalize(direction);
|
||||||
|
|
||||||
std::cout << "[RAYCAST] Start: (" << start.x << ", " << start.y << ", " << start.z << ")" << std::endl;
|
// std::cout << "[RAYCAST] Start: (" << start.x << ", " << start.y << ", " << start.z << ")" << std::endl;
|
||||||
std::cout << "[RAYCAST] Direction: (" << direction.x << ", " << direction.y << ", " << direction.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));
|
// Adjust start position to account for voxels being centered at integer + 0.5
|
||||||
std::cout << "[RAYCAST] Starting voxel: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
// (voxel at pos (0,0,0) occupies space from (-0.5,-0.5,-0.5) to (0.5,0.5,0.5))
|
||||||
|
glm::vec3 adjusted_start = start + glm::vec3(0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
|
glm::ivec3 pos = glm::ivec3(std::floor(adjusted_start.x), std::floor(adjusted_start.y), std::floor(adjusted_start.z));
|
||||||
|
// std::cout << "[RAYCAST] Starting voxel: (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
||||||
|
|
||||||
// (+1 or -1 for each axis)
|
// (+1, -1, or 0 for each axis)
|
||||||
glm::ivec3 step_dir = glm::sign(direction);
|
glm::ivec3 step_dir = glm::ivec3(
|
||||||
std::cout << "[RAYCAST] Step direction: (" << step_dir.x << ", " << step_dir.y << ", " << step_dir.z << ")" << std::endl;
|
direction.x > 0 ? 1 : (direction.x < 0 ? -1 : 0),
|
||||||
|
direction.y > 0 ? 1 : (direction.y < 0 ? -1 : 0),
|
||||||
|
direction.z > 0 ? 1 : (direction.z < 0 ? -1 : 0)
|
||||||
|
);
|
||||||
|
// std::cout << "[RAYCAST] Step direction: (" << step_dir.x << ", " << step_dir.y << ", " << step_dir.z << ")" << std::endl;
|
||||||
|
|
||||||
// How far to step in each axis
|
// Delta: how far along the ray we move for a full voxel step in each axis
|
||||||
const float epsilon = 0.0001f;
|
glm::vec3 delta = glm::vec3(
|
||||||
glm::vec3 safe_dir = glm::vec3(
|
step_dir.x != 0 ? std::abs(1.0f / direction.x) : FLT_MAX,
|
||||||
abs(direction.x) < epsilon ? epsilon : direction.x,
|
step_dir.y != 0 ? std::abs(1.0f / direction.y) : FLT_MAX,
|
||||||
abs(direction.y) < epsilon ? epsilon : direction.y,
|
step_dir.z != 0 ? std::abs(1.0f / direction.z) : FLT_MAX
|
||||||
abs(direction.z) < epsilon ? epsilon : direction.z
|
|
||||||
);
|
);
|
||||||
|
|
||||||
glm::vec3 delta = glm::abs(1.0f / safe_dir);
|
// Calculate t_max: distance along ray to next voxel boundary for each axis
|
||||||
|
glm::vec3 t_max;
|
||||||
|
glm::vec3 fract = adjusted_start - glm::vec3(pos);
|
||||||
|
|
||||||
glm::vec3 fract = start - glm::vec3(pos);
|
// For each axis, calculate distance to the next boundary
|
||||||
glm::vec3 t_max = glm::vec3(
|
if (step_dir.x > 0)
|
||||||
(step_dir.x > 0 ? (1.0f - fract.x) : fract.x) * delta.x,
|
t_max.x = (1.0f - fract.x) * delta.x;
|
||||||
(step_dir.y > 0 ? (1.0f - fract.y) : fract.y) * delta.y,
|
else if (step_dir.x < 0)
|
||||||
(step_dir.z > 0 ? (1.0f - fract.z) : fract.z) * delta.z
|
t_max.x = fract.x * delta.x;
|
||||||
);
|
else
|
||||||
|
t_max.x = FLT_MAX;
|
||||||
|
|
||||||
|
if (step_dir.y > 0)
|
||||||
|
t_max.y = (1.0f - fract.y) * delta.y;
|
||||||
|
else if (step_dir.y < 0)
|
||||||
|
t_max.y = fract.y * delta.y;
|
||||||
|
else
|
||||||
|
t_max.y = FLT_MAX;
|
||||||
|
|
||||||
|
if (step_dir.z > 0)
|
||||||
|
t_max.z = (1.0f - fract.z) * delta.z;
|
||||||
|
else if (step_dir.z < 0)
|
||||||
|
t_max.z = fract.z * delta.z;
|
||||||
|
else
|
||||||
|
t_max.z = FLT_MAX;
|
||||||
|
|
||||||
float dist = 0.0f;
|
float dist = 0.0f;
|
||||||
glm::ivec3 last_move = glm::ivec3(0, 0, 0);
|
glm::ivec3 last_move = glm::ivec3(0, 0, 0);
|
||||||
@ -107,11 +131,11 @@ std::optional<std::pair<glm::ivec3, glm::ivec3>> World::raycast_voxel(glm::vec3
|
|||||||
while (dist < max_dist && iterations < max_iterations) {
|
while (dist < max_dist && iterations < max_iterations) {
|
||||||
iterations++;
|
iterations++;
|
||||||
|
|
||||||
std::cout << "[RAYCAST] Iteration " << iterations << " at voxel (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
// std::cout << "[RAYCAST] Iteration " << iterations << " at voxel (" << pos.x << ", " << pos.y << ", " << pos.z << ")" << std::endl;
|
||||||
|
|
||||||
if (this->get_voxel(pos).has_value()) {
|
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] 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;
|
// std::cout << "[RAYCAST] Returning normal: (" << -last_move.x << ", " << -last_move.y << ", " << -last_move.z << ")" << std::endl;
|
||||||
return std::make_pair(pos, -last_move);
|
return std::make_pair(pos, -last_move);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +158,7 @@ std::optional<std::pair<glm::ivec3, glm::ivec3>> World::raycast_voxel(glm::vec3
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "[RAYCAST] No voxel hit after " << iterations << " iterations, dist=" << dist << std::endl;
|
// std::cout << "[RAYCAST] No voxel hit after " << iterations << " iterations, dist=" << dist << std::endl;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
128
src/main.cpp
128
src/main.cpp
@ -13,6 +13,8 @@
|
|||||||
unsigned int SCR_WIDTH = 1920;
|
unsigned int SCR_WIDTH = 1920;
|
||||||
unsigned int SCR_HEIGHT = 1080;
|
unsigned int SCR_HEIGHT = 1080;
|
||||||
|
|
||||||
|
const int EDIT_RANGE = 5;
|
||||||
|
|
||||||
// Jump
|
// Jump
|
||||||
const float JUMP_COOLDOWN = 0.0f;
|
const float JUMP_COOLDOWN = 0.0f;
|
||||||
const float JUMP_POWER = 10.0f; // Initial Jump Speed
|
const float JUMP_POWER = 10.0f; // Initial Jump Speed
|
||||||
@ -35,6 +37,9 @@ 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, 0.0f, 0.0f));
|
Camera camera = Camera(CAMERA_SPEED, glm::vec3(0.0f, 0.0f, 0.0f));
|
||||||
|
|
||||||
|
// Targeted block for highlighting
|
||||||
|
std::optional<glm::ivec3> targeted_block = std::nullopt;
|
||||||
|
|
||||||
// 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
|
||||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
@ -60,7 +65,7 @@ World world;
|
|||||||
void mouse_callback(GLFWwindow * window, double xpos, double ypos)
|
void mouse_callback(GLFWwindow * window, double xpos, double ypos)
|
||||||
{
|
{
|
||||||
float x_offset = xpos - last_x;
|
float x_offset = xpos - last_x;
|
||||||
float y_offset = ypos - last_y;
|
float y_offset = last_y - ypos; // Inverted Y for typical FPS controls
|
||||||
last_x = xpos;
|
last_x = xpos;
|
||||||
last_y = ypos;
|
last_y = ypos;
|
||||||
|
|
||||||
@ -83,7 +88,7 @@ void mouse_callback(GLFWwindow * window, double xpos, double ypos)
|
|||||||
|
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
|
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
|
||||||
direction.y = -sin(glm::radians(pitch));
|
direction.y = sin(glm::radians(pitch)); // Positive Y is up
|
||||||
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);
|
||||||
}
|
}
|
||||||
@ -93,6 +98,34 @@ void processInput(GLFWwindow *window)
|
|||||||
{
|
{
|
||||||
float current_time = glfwGetTime();
|
float current_time = glfwGetTime();
|
||||||
|
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
|
||||||
|
glm::vec3 eye = camera.getEyePosition();
|
||||||
|
glm::mat4 view = camera.getView();
|
||||||
|
glm::vec3 forward = -glm::vec3(view[0][2], view[1][2], view[2][2]); // Extract forward from view matrix
|
||||||
|
|
||||||
|
std::cout << "Camera target (from pitch/yaw): (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
std::cout << "Camera forward (from view matrix): (" << forward.x << ", " << forward.y << ", " << forward.z << ")" << std::endl;
|
||||||
|
std::cout << "Match: " << (glm::length(camera.target - forward) < 0.01f ? "YES" : "NO") << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update targeted block every frame for highlight
|
||||||
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
||||||
|
world.raycast_voxel(camera.getEyePosition(), camera.target, EDIT_RANGE);
|
||||||
|
if (raycast_result.has_value()) {
|
||||||
|
targeted_block = raycast_result.value().first;
|
||||||
|
|
||||||
|
// Debug: print occasionally
|
||||||
|
static int frame_count = 0;
|
||||||
|
if (frame_count % 60 == 0) {
|
||||||
|
std::cout << "Camera eye: (" << camera.getEyePosition().x << ", " << camera.getEyePosition().y << ", " << camera.getEyePosition().z << ")" << std::endl;
|
||||||
|
std::cout << "Camera target dir: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
std::cout << "Highlighted block: (" << targeted_block.value().x << ", " << targeted_block.value().y << ", " << targeted_block.value().z << ")" << std::endl;
|
||||||
|
}
|
||||||
|
frame_count++;
|
||||||
|
} else {
|
||||||
|
targeted_block = std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||||
// if (mouse_lock) {
|
// if (mouse_lock) {
|
||||||
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
// glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||||
@ -182,10 +215,10 @@ void processInput(GLFWwindow *window)
|
|||||||
std::cout << "\n=== LEFT CLICK (PLACE) ===" << std::endl;
|
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 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::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
|
||||||
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
||||||
world.raycast_voxel(camera.getEyePosition(), camera.target, 3);
|
world.raycast_voxel(camera.getEyePosition(), camera.target, EDIT_RANGE);
|
||||||
|
|
||||||
if (raycast_result.has_value()) {
|
if (raycast_result.has_value()) {
|
||||||
auto [target_block, normal] = raycast_result.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 << "Hit block at: (" << target_block.x << ", " << target_block.y << ", " << target_block.z << ")" << std::endl;
|
||||||
@ -207,10 +240,10 @@ void processInput(GLFWwindow *window)
|
|||||||
std::cout << "\n=== RIGHT CLICK (REMOVE) ===" << std::endl;
|
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 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::cout << "Camera target: (" << camera.target.x << ", " << camera.target.y << ", " << camera.target.z << ")" << std::endl;
|
||||||
|
|
||||||
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
std::optional<std::pair<glm::ivec3, glm::ivec3>> raycast_result =
|
||||||
world.raycast_voxel(camera.getEyePosition(), camera.target, 3);
|
world.raycast_voxel(camera.getEyePosition(), camera.target, EDIT_RANGE);
|
||||||
|
|
||||||
if (raycast_result.has_value()) {
|
if (raycast_result.has_value()) {
|
||||||
auto [target_block, normal] = raycast_result.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 << "Hit block at: (" << target_block.x << ", " << target_block.y << ", " << target_block.z << ")" << std::endl;
|
||||||
@ -236,7 +269,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.6.0", NULL, NULL);
|
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "Voxel Engine 0.6.1", 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();
|
||||||
@ -278,10 +311,10 @@ int main() {
|
|||||||
unsigned int crosshairVAO, crosshairVBO;
|
unsigned int crosshairVAO, crosshairVBO;
|
||||||
glGenVertexArrays(1, &crosshairVAO);
|
glGenVertexArrays(1, &crosshairVAO);
|
||||||
glGenBuffers(1, &crosshairVBO);
|
glGenBuffers(1, &crosshairVBO);
|
||||||
|
|
||||||
glBindVertexArray(crosshairVAO);
|
glBindVertexArray(crosshairVAO);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, crosshairVBO);
|
glBindBuffer(GL_ARRAY_BUFFER, crosshairVBO);
|
||||||
|
|
||||||
// Crosshair vertices in NDC (Normalized Device Coordinates: -1 to 1)
|
// Crosshair vertices in NDC (Normalized Device Coordinates: -1 to 1)
|
||||||
float crosshairSize = 0.02f; // Size in NDC
|
float crosshairSize = 0.02f; // Size in NDC
|
||||||
float crosshairVertices[] = {
|
float crosshairVertices[] = {
|
||||||
@ -292,12 +325,65 @@ int main() {
|
|||||||
0.0f, -crosshairSize, 0.0f,
|
0.0f, -crosshairSize, 0.0f,
|
||||||
0.0f, crosshairSize, 0.0f
|
0.0f, crosshairSize, 0.0f
|
||||||
};
|
};
|
||||||
|
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(crosshairVertices), crosshairVertices, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(crosshairVertices), crosshairVertices, GL_STATIC_DRAW);
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
// Setup highlight box (cube outline)
|
||||||
|
unsigned int highlightVAO, highlightVBO, highlightEBO;
|
||||||
|
glGenVertexArrays(1, &highlightVAO);
|
||||||
|
glGenBuffers(1, &highlightVBO);
|
||||||
|
glGenBuffers(1, &highlightEBO);
|
||||||
|
|
||||||
|
glBindVertexArray(highlightVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, highlightVBO);
|
||||||
|
|
||||||
|
// Cube outline vertices (slightly larger than 1 unit cube for visibility)
|
||||||
|
float offset = 0.001f; // Slight offset to prevent z-fighting
|
||||||
|
float highlightVertices[] = {
|
||||||
|
// 8 corners of a cube
|
||||||
|
-0.5f - offset, -0.5f - offset, -0.5f - offset, // 0
|
||||||
|
0.5f + offset, -0.5f - offset, -0.5f - offset, // 1
|
||||||
|
0.5f + offset, 0.5f + offset, -0.5f - offset, // 2
|
||||||
|
-0.5f - offset, 0.5f + offset, -0.5f - offset, // 3
|
||||||
|
-0.5f - offset, -0.5f - offset, 0.5f + offset, // 4
|
||||||
|
0.5f + offset, -0.5f - offset, 0.5f + offset, // 5
|
||||||
|
0.5f + offset, 0.5f + offset, 0.5f + offset, // 6
|
||||||
|
-0.5f - offset, 0.5f + offset, 0.5f + offset // 7
|
||||||
|
};
|
||||||
|
|
||||||
|
// Indices for the 12 edges of the cube
|
||||||
|
unsigned int highlightIndices[] = {
|
||||||
|
// Bottom face
|
||||||
|
0, 1, 1, 2, 2, 3, 3, 0,
|
||||||
|
// Top face
|
||||||
|
4, 5, 5, 6, 6, 7, 7, 4,
|
||||||
|
// Vertical edges
|
||||||
|
0, 4, 1, 5, 2, 6, 3, 7
|
||||||
|
};
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(highlightVertices), highlightVertices, GL_STATIC_DRAW);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, highlightEBO);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(highlightIndices), highlightIndices, GL_STATIC_DRAW);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
// Setup debug ray
|
||||||
|
unsigned int debugRayVAO, debugRayVBO;
|
||||||
|
glGenVertexArrays(1, &debugRayVAO);
|
||||||
|
glGenBuffers(1, &debugRayVBO);
|
||||||
|
|
||||||
|
glBindVertexArray(debugRayVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, debugRayVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6, nullptr, GL_DYNAMIC_DRAW); // 2 points * 3 coords
|
||||||
|
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();
|
||||||
@ -400,6 +486,22 @@ 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 Highlighted Block ----
|
||||||
|
if (targeted_block.has_value()) {
|
||||||
|
shader.use();
|
||||||
|
glm::mat4 model = glm::mat4(1.0f);
|
||||||
|
// Voxels are centered on integer coordinates, so no need to add 0.5
|
||||||
|
model = glm::translate(model, glm::vec3(targeted_block.value()));
|
||||||
|
glm::mat4 mvp = projection * view * model;
|
||||||
|
shader.setMat4("u_mvp", mvp);
|
||||||
|
shader.setVec3("u_Color", glm::vec3(0.0f, 0.0f, 0.0f)); // Black outline
|
||||||
|
|
||||||
|
glLineWidth(2.0f);
|
||||||
|
glBindVertexArray(highlightVAO);
|
||||||
|
glDrawElements(GL_LINES, 24, GL_UNSIGNED_INT, 0); // 24 indices = 12 edges
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
// ---- Draw Crosshair ----
|
// ---- Draw Crosshair ----
|
||||||
glDisable(GL_DEPTH_TEST); // Draw on top of everything
|
glDisable(GL_DEPTH_TEST); // Draw on top of everything
|
||||||
shader.use();
|
shader.use();
|
||||||
@ -425,4 +527,4 @@ int main() {
|
|||||||
|
|
||||||
glfwTerminate(); // Clean up GLFW
|
glfwTerminate(); // Clean up GLFW
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user