collision: closest point point aabb

This commit is contained in:
Zack Buhman 2026-03-13 14:22:45 -05:00
parent f6bd91824b
commit 84fbd05841
8 changed files with 347 additions and 12 deletions

View File

@ -30,7 +30,8 @@ OBJS = \
src/view.o \ src/view.o \
src/minecraft.o \ src/minecraft.o \
src/hud.o \ src/hud.o \
src/lighting.o src/lighting.o \
src/collision_scene.o
all: test.so all: test.so

25
include/collision.h Normal file
View File

@ -0,0 +1,25 @@
#pragma once
#include "directxmath/directxmath.h"
namespace collision {
struct AABB {
XMVECTOR min;
XMVECTOR max;
};
static inline AABB cube_aabb(XMVECTOR const & center, float half)
{
half = fabsf(half);
XMVECTOR min = center + XMVectorReplicate(-half);
XMVECTOR max = center + XMVectorReplicate( half);
return AABB(min, max);
}
static inline XMVECTOR closest_point_point_aabb(XMVECTOR const & p, AABB const & aabb)
{
return XMVectorClamp(p, aabb.min, aabb.max);
}
}

View File

@ -0,0 +1,7 @@
#pragma once
namespace collision_scene {
void load();
void draw();
void update(int up, int down, int left, int right);
}

View File

@ -0,0 +1,14 @@
#version 330 core
out vec4 Color;
flat in int InstanceID;
uniform vec3 BaseColor;
void main()
{
float intensity = (InstanceID == 0) ? 0.7 : 0.3;
Color = vec4(BaseColor * intensity, 1);
}

View File

@ -0,0 +1,39 @@
#version 330 core
// per-vertex
in vec2 Position;
flat out int InstanceID;
uniform mat4 Transform;
uniform bool UseGridTransform;
vec2 world_translation()
{
if (gl_InstanceID == 0)
return vec2(0, 0);
int instance = gl_InstanceID + 1;
float negative = ((instance % 2) == 0) ? -1.0 : 1.0;
vec2 translation = (Position.x == 0) ? vec2(1, 0) : vec2(0, 1);
return translation * negative * (instance >> 1);
}
vec2 grid_transform(vec2 position)
{
return position * 4 + world_translation();
}
void main()
{
InstanceID = gl_InstanceID;
vec2 position;
if (UseGridTransform)
position = grid_transform(Position);
else
position = Position;
gl_Position = Transform * vec4(position, 0, 1);
}

View File

@ -1,11 +0,0 @@
#include "directxmath/directxmath.h"
struct AABB {
XMVECTOR min;
XMVECTOR max;
};
XMVECTOR closest_point_point_aabb(XMVECTOR const &p, AABB const& aabb)
{
return XMVectorClamp(p, aabb.min, aabb.max);
}

246
src/collision_scene.cpp Normal file
View File

@ -0,0 +1,246 @@
#include "glad/gl.h"
#include "directxmath/directxmath.h"
#include "opengl.h"
#include "collision.h"
#include "collision_scene.h"
namespace collision_scene {
struct location {
struct {
unsigned int position;
} attrib;
struct {
unsigned int transform;
unsigned int use_grid_transform;
unsigned int base_color;
} uniform;
};
static unsigned int program;
static location location;
static unsigned int vertex_array_object;
static unsigned int per_vertex_buffer;
static unsigned int index_buffer;
static XMVECTOR point_position;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnarrowing"
const _Float16 vertex_data[] = {
// 0: lines
-1.0, 0.0, 1.0, 0.0, // horizontal, left to right
0.0, 1.0, 0.0, -1.0, // vertical, top to bottom
// 4: "cube"
-1.0, 1.0, // tl
1.0, 1.0, // tr
1.0, -1.0, // br
-1.0, -1.0, // bl
// 8: "circle"
0.000000, -1.000000,
-0.195090, -0.980785,
-0.382683, -0.923880,
-0.555570, -0.831470,
-0.707107, -0.707107,
-0.831470, -0.555570,
-0.923880, -0.382683,
-0.980785, -0.195090,
-1.000000, 0.000000,
-0.980785, 0.195090,
-0.923880, 0.382683,
-0.831470, 0.555570,
-0.707107, 0.707107,
-0.555570, 0.831470,
-0.382683, 0.923880,
-0.195090, 0.980785,
0.000000, 1.000000,
0.195090, 0.980785,
0.382683, 0.923880,
0.555570, 0.831470,
0.707107, 0.707107,
0.831470, 0.555570,
0.923880, 0.382683,
0.980785, 0.195090,
1.000000, 0.000000,
0.980785, -0.195090,
0.923880, -0.382683,
0.831470, -0.555570,
0.707107, -0.707107,
0.555570, -0.831470,
0.382683, -0.923880,
0.195090, -0.980785,
};
#pragma GCC diagnostic pop
const int vertex_data_size = (sizeof (vertex_data));
const int per_vertex_size = (sizeof (_Float16)) * 2;
const unsigned short index_data[] = {
// "cube" (line strip)
0, 1, 2, 3, 0,
// "circle" (line strip)
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
0,
};
const int index_data_size = (sizeof (index_data));
void load_program()
{
program = compile_from_files("shader/collision_scene.vert",
nullptr,
"shader/collision_scene.frag");
location.attrib.position = glGetAttribLocation(program, "Position");
location.uniform.transform = glGetUniformLocation(program, "Transform");
location.uniform.use_grid_transform = glGetUniformLocation(program, "UseGridTransform");
location.uniform.base_color = glGetUniformLocation(program, "BaseColor");
}
void load_vertex_attributes()
{
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
glVertexBindingDivisor(0, 0);
glEnableVertexAttribArray(location.attrib.position);
glVertexAttribFormat(location.attrib.position, 2, GL_HALF_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(location.attrib.position, 0);
glBindVertexArray(0);
}
void load_per_vertex_buffer()
{
glGenBuffers(1, &per_vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, per_vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_data_size, vertex_data, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void load_index_buffer()
{
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_data_size, index_data, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void load()
{
load_program();
load_vertex_attributes();
load_per_vertex_buffer();
load_index_buffer();
point_position = XMVectorSet(0, 0, 0, 1);
}
static inline XMMATRIX view()
{
XMVECTOR eye = XMVectorSet(0, 0, 1, 0);
XMVECTOR at = XMVectorSet(0, 0, 0, 0);
XMVECTOR up = XMVectorSet(0, 1, 0, 0);
return XMMatrixLookAtRH(eye, at, up);
}
static inline XMMATRIX projection()
{
return XMMatrixOrthographicRH(10, 10, 0, 10);
}
void update(int up, int down, int left, int right)
{
float rate = 0.1f;
float forward = (rate * up + -rate * down);
float strafe = (-rate * left + rate * right);
point_position = XMVector3Transform(point_position, XMMatrixTranslation(strafe, forward, 0));
}
static inline void set_transform(XMMATRIX const & transform)
{
XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform);
glUniformMatrix4fv(location.uniform.transform, 1, false, (float *)&float_transform);
}
void draw()
{
glUseProgram(program);
glBlendFunc(GL_ONE, GL_ZERO);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glBindVertexArray(vertex_array_object);
glBindVertexBuffer(0, per_vertex_buffer, 0, per_vertex_size);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
XMMATRIX transform = view() * projection();
XMFLOAT4X4 float_transform;
XMStoreFloat4x4(&float_transform, transform);
// grid
glUniformMatrix4fv(location.uniform.transform, 1, false, (float *)&float_transform);
glUniform3f(location.uniform.base_color, 0, 1, 0);
glUniform1i(location.uniform.use_grid_transform, 1);
glDrawArraysInstanced(GL_LINES, 0, 4, 7);
// cube
float cube_half = 0.5;
XMVECTOR cube_position = XMVectorSet(1, 0, 0, 0);
XMMATRIX cube_transform
= XMMatrixScaling(cube_half, cube_half, cube_half)
* XMMatrixTranslationFromVector(cube_position)
* transform;
set_transform(cube_transform);
glUniform3f(location.uniform.base_color, 0, 0.5, 1.0);
glUniform1i(location.uniform.use_grid_transform, 0);
const int cube_base_vertex = 4;
const int cube_base_index = 0;
glDrawElementsBaseVertex(GL_LINE_STRIP, 5, GL_UNSIGNED_SHORT, (void*)(cube_base_index), cube_base_vertex);
// circle
const int circle_base_vertex = 8;
const int circle_base_index = 5 * (sizeof (unsigned short));
XMMATRIX point_scale = XMMatrixScaling(0.05, 0.05, 0.05);
// point
glUniform3f(location.uniform.base_color, 1.0, 0.5, 0.0);
XMMATRIX point_transform
= point_scale
* XMMatrixTranslationFromVector(point_position)
* transform;
set_transform(point_transform);
glDrawElementsBaseVertex(GL_LINE_STRIP, 33, GL_UNSIGNED_SHORT, (void*)(circle_base_index), circle_base_vertex);
// closest point
glUniform3f(location.uniform.base_color, 1.0, 0.0, 0.0);
collision::AABB cube_aabb = collision::cube_aabb(cube_position, cube_half);
XMVECTOR closest_point_position = collision::closest_point_point_aabb(point_position, cube_aabb);
XMMATRIX closest_point_transform
= point_scale
* XMMatrixTranslationFromVector(closest_point_position)
* transform;
set_transform(closest_point_transform);
glDrawElementsBaseVertex(GL_LINE_STRIP, 33, GL_UNSIGNED_SHORT, (void*)(circle_base_index), circle_base_vertex);
}
}

View File

@ -17,6 +17,7 @@
#include "minecraft.h" #include "minecraft.h"
#include "hud.h" #include "hud.h"
#include "lighting.h" #include "lighting.h"
#include "collision_scene.h"
struct line_location { struct line_location {
struct { struct {
@ -278,6 +279,12 @@ void load(const char * source_path)
non_block::load_index_buffer(); non_block::load_index_buffer();
non_block::load_per_vertex_buffer(); non_block::load_per_vertex_buffer();
non_block::load_vertex_attributes(); non_block::load_vertex_attributes();
//////////////////////////////////////////////////////////////////////
// collision_scene
//////////////////////////////////////////////////////////////////////
collision_scene::load();
} }
void update_keyboard(int up, int down, int left, int right) void update_keyboard(int up, int down, int left, int right)
@ -285,6 +292,7 @@ void update_keyboard(int up, int down, int left, int right)
//float forward = (0.1f * up + -0.1f * down); //float forward = (0.1f * up + -0.1f * down);
//float strafe = (-0.1f * left + 0.1f * right); //float strafe = (-0.1f * left + 0.1f * right);
//view::third_person::apply_translation(forward, strafe, 0); //view::third_person::apply_translation(forward, strafe, 0);
collision_scene::update(up, down, left, right);
} }
const int max_joysticks = 8; const int max_joysticks = 8;
@ -452,6 +460,7 @@ void draw()
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(-1.0f); glClearDepth(-1.0f);
/*
// possibly re-initialize geometry buffer if window width/height changes // possibly re-initialize geometry buffer if window width/height changes
init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types); init_geometry_buffer(geometry_buffer_pnc, geometry_buffer_pnc_types);
@ -468,6 +477,11 @@ void draw()
lighting::draw(); lighting::draw();
//draw_quad(); //draw_quad();
hud::draw(); hud::draw();
*/
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
collision_scene::draw();
last_frame_time = current_time; last_frame_time = current_time;
} }