bresenham

This commit is contained in:
Zack Buhman 2026-03-09 22:56:08 -05:00
parent 50188813f8
commit 175bf4a397
8 changed files with 321 additions and 6 deletions

View File

@ -21,7 +21,8 @@ OBJS = \
src/opengl.o \ src/opengl.o \
src/test.o \ src/test.o \
src/font.o \ src/font.o \
src/window.o src/window.o \
src/bresenham.o
all: test.so all: test.so

13
include/bresenham.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
void bresenham(int x1, int y1, int z1,
int x2, int y2, int z2,
void (*func)(int x, int y, int z));
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,7 @@ extern "C" {
void load(const char * source_path); void load(const char * source_path);
void draw(); void draw();
void kb_update(int up, int down, int left, int right);
void update(float lx, float ly, float rx, float ry, float tl, float tr, void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right, int up, int down, int left, int right,
int a, int b, int x, int y); int a, int b, int x, int y);

View File

@ -8,6 +8,7 @@ function init()
void load(const char * source_path); void load(const char * source_path);
void update_window(int width, int height); void update_window(int width, int height);
void draw(); void draw();
void kb_update(int kbup, int kbdown, int kbleft, int kbright);
void update(float lx, float ly, float rx, float ry, float tl, float tr, void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right, int up, int down, int left, int right,
int a, int b, int x, int y); int a, int b, int x, int y);
@ -34,8 +35,17 @@ local update = function(dt)
local b = joystick:isGamepadDown("b") local b = joystick:isGamepadDown("b")
local x = joystick:isGamepadDown("x") local x = joystick:isGamepadDown("x")
local y = joystick:isGamepadDown("y") local y = joystick:isGamepadDown("y")
test.update(lx, ly, rx, ry, tl, tr, up, down, left, right, a, b, x, y)
test.update(lx, ly, rx, ry, tl, tr,
up, down, left, right,
a, b, x, y)
end end
local up = love.keyboard.isDown("up")
local down = love.keyboard.isDown("down")
local left = love.keyboard.isDown("left")
local right = love.keyboard.isDown("right")
test.kb_update(up, down, left, right);
end end
local draw = function() local draw = function()

18
shader/line.frag Normal file
View File

@ -0,0 +1,18 @@
#version 330 core
in VS_OUT {
vec3 Position; // world coordinates
vec3 Normal;
vec2 Texture;
} fs_in;
layout (location = 0) out vec3 Position;
layout (location = 1) out vec3 Normal;
layout (location = 2) out vec3 Color;
void main()
{
Position = fs_in.Position.xzy;
Normal = normalize(fs_in.Normal.xzy);
Color = vec3(0.5, 0, 1);
}

27
shader/line.vert Normal file
View File

@ -0,0 +1,27 @@
#version 330 core
// per-vertex:
in vec3 Position;
in vec3 Normal;
in vec2 Texture;
// per-instance:
in vec3 BlockPosition;
out VS_OUT {
vec3 Position;
vec3 Normal;
vec2 Texture;
} vs_out;
uniform mat4 Transform;
void main()
{
vec3 position = Position + BlockPosition; // world coordinates
vs_out.Position = position;
vs_out.Normal = Normal;
vs_out.Texture = Texture;
gl_Position = Transform * vec4(position.xzy, 1.0);
}

78
src/bresenham.c Normal file
View File

@ -0,0 +1,78 @@
#include <stdlib.h>
#include "bresenham.h"
void bresenham(int x1, int y1, int z1,
int x2, int y2, int z2,
void (*func)(int x, int y, int z))
{
int pt_x = x1;
int pt_y = y1;
int pt_z = z1;
int dx = x2 - x1;
int dy = y2 - y1;
int dz = z2 - z1;
int x_inc = (dx < 0) ? -1 : 1;
int y_inc = (dy < 0) ? -1 : 1;
int z_inc = (dz < 0) ? -1 : 1;
int l = abs(dx);
int m = abs(dy);
int n = abs(dz);
int dx2 = l << 1;
int dy2 = m << 1;
int dz2 = n << 1;
if ((l >= m) && (l >= n)) {
int err_1 = dy2 - l;
int err_2 = dz2 - l;
for (int i = 0; i < l; i++) {
func(pt_x, pt_y, pt_z);
if (err_1 > 0) {
pt_y += y_inc;
err_1 -= dx2;
}
if (err_2 > 0) {
pt_z += z_inc;
err_2 -= dx2;
}
err_1 += dy2;
err_2 += dz2;
pt_x += x_inc;
}
} else if ((m >= l) && (m >= n)) {
int err_1 = dx2 - m;
int err_2 = dz2 - m;
for (int i = 0; i < m; i++) {
func(pt_x, pt_y, pt_z);
if (err_1 > 0) {
pt_x += x_inc;
err_1 -= dy2;
}
if (err_2 > 0) {
pt_z += z_inc;
err_2 -= dy2;
}
err_1 += dx2;
err_2 += dz2;
pt_y += y_inc;
}
} else {
int err_1 = dy2 - n;
int err_2 = dx2 - n;
for (int i = 0; i < n; i++) {
func(pt_x, pt_y, pt_z);
if (err_1 > 0) {
pt_y += y_inc;
err_1 -= dz2;
}
if (err_2 > 0) {
pt_x += x_inc;
err_2 -= dz2;
}
err_1 += dy2;
err_2 += dx2;
pt_z += z_inc;
}
}
func(pt_x, pt_y, pt_z);
}

View File

@ -8,6 +8,7 @@
#include "test.h" #include "test.h"
#include "font.h" #include "font.h"
#include "window.h" #include "window.h"
#include "bresenham.h"
#include "data.inc" #include "data.inc"
@ -33,6 +34,22 @@ struct test_location {
static unsigned int test_program; static unsigned int test_program;
static test_location test_location; static test_location test_location;
struct line_location {
struct {
unsigned int position;
unsigned int normal;
unsigned int texture;
unsigned int block_position;
} attrib;
struct {
unsigned int transform;
} uniform;
};
static unsigned int line_program;
static line_location line_location;
static unsigned int line_vertex_array_object;
static unsigned int line_instance_buffer;
struct quad_location { struct quad_location {
struct { struct {
unsigned int texture_sampler; unsigned int texture_sampler;
@ -443,6 +460,105 @@ view_state view_state;
font::font * terminus_fonts; font::font * terminus_fonts;
struct short_point {
short x;
short y;
short z;
};
static_assert((sizeof (short_point)) == 6);
short_point line_points[128];
static int line_point_ix = 0;
void line_point(int x, int y, int z)
{
if (line_point_ix >= 128)
return;
printf("%d %d %d\n", x, y, z);
line_points[line_point_ix].x = x;
line_points[line_point_ix].y = y;
line_points[line_point_ix].z = z;
line_point_ix += 1;
}
void load_line_program()
{
unsigned int program = compile_from_files("shader/line.vert",
NULL,
"shader/line.frag");
line_location.attrib.position = glGetAttribLocation(program, "Position");
line_location.attrib.normal = glGetAttribLocation(program, "Normal");
line_location.attrib.texture = glGetAttribLocation(program, "Texture");
line_location.attrib.block_position = glGetAttribLocation(program, "BlockPosition");
printf("line program:\n");
printf(" attributes:\n position %u\n normal %u\n texture %u\n block_position %u\n",
line_location.attrib.position,
line_location.attrib.normal,
line_location.attrib.texture,
line_location.attrib.block_position);
line_location.uniform.transform = glGetUniformLocation(program, "Transform");
printf(" uniforms:\n transform %u\n\n",
line_location.uniform.transform);
line_program = program;
}
void load_line_vertex_attributes()
{
glGenVertexArrays(1, &line_vertex_array_object);
glBindVertexArray(line_vertex_array_object);
glVertexBindingDivisor(0, 0);
glVertexBindingDivisor(1, 1);
glEnableVertexAttribArray(line_location.attrib.position);
glVertexAttribFormat(line_location.attrib.position, 3, GL_HALF_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(line_location.attrib.position, 0);
glEnableVertexAttribArray(line_location.attrib.normal);
glVertexAttribFormat(line_location.attrib.normal, 3, GL_HALF_FLOAT, GL_FALSE, 6);
glVertexAttribBinding(line_location.attrib.normal, 0);
glEnableVertexAttribArray(line_location.attrib.texture);
glVertexAttribFormat(line_location.attrib.texture, 2, GL_HALF_FLOAT, GL_FALSE, 12);
glVertexAttribBinding(line_location.attrib.texture, 0);
glEnableVertexAttribArray(line_location.attrib.block_position);
glVertexAttribFormat(line_location.attrib.block_position, 3, GL_SHORT, GL_FALSE, 0);
glVertexAttribBinding(line_location.attrib.block_position, 1);
glBindVertexArray(0);
}
void load_line_instance_buffer()
{
glBindBuffer(GL_ARRAY_BUFFER, line_instance_buffer);
glBufferData(GL_ARRAY_BUFFER, (sizeof (short_point)) * line_point_ix, line_points, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void load_line()
{
int x1 = -55;
int z1 = 48;
int y1 = 50;
int x2 = -60;
int z2 = 55;
int y2 = 53;
line_point_ix = 0;
bresenham(x1, y1, z1, x2, y2, z2, line_point);
load_line_instance_buffer();
}
void load(const char * source_path) void load(const char * source_path)
{ {
g_source_path_length = strlen(source_path); g_source_path_length = strlen(source_path);
@ -487,6 +603,16 @@ void load(const char * source_path)
load_lighting_program(); load_lighting_program();
load_light_uniform_buffer(); load_light_uniform_buffer();
//////////////////////////////////////////////////////////////////////
// line
//////////////////////////////////////////////////////////////////////
load_line_program();
load_line_vertex_attributes();
glGenBuffers(1, &line_instance_buffer);
load_line();
} }
float _ry = 0.0; float _ry = 0.0;
@ -500,6 +626,13 @@ light_parameters lighting = {
.linear = 1.0 .linear = 1.0
}; };
void kb_update(int up, int down, int left, int right)
{
XMVECTOR normal = XMVector3NormalizeEst(XMVector3Cross(view_state.forward, view_state.up));
view_state.eye += view_state.forward * (0.1f * up + -0.1f * down);
view_state.eye += normal * (-0.1f * left + 0.1f * right);
}
void update(float lx, float ly, float rx, float ry, float tl, float tr, void update(float lx, float ly, float rx, float ry, float tl, float tr,
int up, int down, int left, int right, int up, int down, int left, int right,
int a, int b, int x, int y) int a, int b, int x, int y)
@ -594,11 +727,8 @@ void draw_hud()
y += ter_best.desc->glyph_height; y += ter_best.desc->glyph_height;
} }
void draw_minecraft() XMMATRIX current_view_projection()
{ {
// possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
XMVECTOR at = XMVectorAdd(view_state.eye, view_state.direction); XMVECTOR at = XMVectorAdd(view_state.eye, view_state.direction);
XMMATRIX view = XMMatrixLookAtRH(view_state.eye, at, view_state.up); XMMATRIX view = XMMatrixLookAtRH(view_state.eye, at, view_state.up);
@ -608,6 +738,13 @@ void draw_minecraft()
float far_z = 0.1; float far_z = 0.1;
XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z); XMMATRIX projection = XMMatrixPerspectiveFovRH(fov_angle_y, aspect_ratio, near_z, far_z);
XMMATRIX transform = view * projection; XMMATRIX transform = view * projection;
return transform;
}
void draw_minecraft()
{
// possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
glUseProgram(test_program); glUseProgram(test_program);
@ -618,6 +755,7 @@ void draw_minecraft()
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
XMMATRIX transform = current_view_projection();
glUniformMatrix4fv(test_location.uniform.transform, 1, false, (float *)&transform); glUniformMatrix4fv(test_location.uniform.transform, 1, false, (float *)&transform);
glUniform1i(test_location.uniform.terrain_sampler, 0); glUniform1i(test_location.uniform.terrain_sampler, 0);
@ -720,6 +858,34 @@ void draw_lighting()
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0); glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, (void *)0);
} }
void draw_line()
{
glUseProgram(line_program);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER);
XMMATRIX transform = current_view_projection();
glUniformMatrix4fv(line_location.uniform.transform, 1, false, (float *)&transform);
//glEnable(GL_CULL_FACE);
//glCullFace(GL_FRONT);
//glFrontFace(GL_CCW);
glBindVertexArray(line_vertex_array_object);
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
int line_instance_vertex_size = (sizeof (short_point));
glBindVertexBuffer(1, line_instance_buffer, 0, line_instance_vertex_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
int configuration = 63;
int element_count = 6 * popcount(configuration);
const void * indices = (void *)((ptrdiff_t)index_buffer_configuration_offsets[configuration]); // index into configuration.idx
int instance_count = line_point_ix;
glDrawElementsInstanced(GL_TRIANGLES, element_count, GL_UNSIGNED_BYTE, indices, instance_count);
}
void draw() void draw()
{ {
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
@ -729,6 +895,7 @@ void draw()
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw_minecraft(); draw_minecraft();
draw_line();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);