library: 3D vertex manipulation functions

This commit is contained in:
Adam
2024-03-15 03:29:22 +00:00
parent 230ca279a6
commit 41bdade88c
5 changed files with 135 additions and 2 deletions

View File

@@ -1246,13 +1246,16 @@ void _bolt_gl_onDrawElements(uint32_t mode, unsigned int count, uint32_t type, c
int draw_tex;
gl.GetFramebufferAttachmentParameteriv(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &draw_tex);
if (draw_tex == c->target_3d_tex) {
int atlas, settings_atlas;
int atlas, settings_atlas, ubo_binding, ubo_view_index, ubo_viewport_index;
float atlas_meta[4];
gl.GetUniformiv(c->bound_program->id, c->bound_program->loc_uTextureAtlas, &atlas);
gl.GetUniformiv(c->bound_program->id, c->bound_program->loc_uTextureAtlasSettings, &settings_atlas);
gl.GetUniformfv(c->bound_program->id, c->bound_program->loc_uAtlasMeta, atlas_meta);
struct GLTexture2D* tex = c->texture_units[atlas];
struct GLTexture2D* tex_settings = c->texture_units[settings_atlas];
gl.GetActiveUniformBlockiv(c->bound_program->id, c->bound_program->block_index_ViewTransforms, GL_UNIFORM_BLOCK_BINDING, &ubo_binding);
gl.GetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, ubo_binding, &ubo_view_index);
const float* view_proj_matrix = (float*)(_bolt_context_get_buffer(c, ubo_view_index)->data + c->bound_program->offset_uViewProjMatrix);
struct GLPluginDrawElementsVertex3DUserData vertex_userdata;
vertex_userdata.c = c;
@@ -1268,6 +1271,10 @@ void _bolt_gl_onDrawElements(uint32_t mode, unsigned int count, uint32_t type, c
struct GLPluginTextureUserData tex_userdata;
tex_userdata.tex = tex;
struct GLPlugin3DMatrixUserData matrix_userdata;
gl.GetUniformfv(c->bound_program->id, c->bound_program->loc_uModelMatrix, matrix_userdata.model_matrix);
memcpy(matrix_userdata.viewproj_matrix, view_proj_matrix, 16 * sizeof(float));
struct Render3D render;
render.vertex_count = count;
render.vertex_functions.userdata = &vertex_userdata;
@@ -1281,6 +1288,10 @@ void _bolt_gl_onDrawElements(uint32_t mode, unsigned int count, uint32_t type, c
render.texture_functions.size = _bolt_gl_plugin_texture_size;
render.texture_functions.compare = _bolt_gl_plugin_texture_compare;
render.texture_functions.data = _bolt_gl_plugin_texture_data;
render.matrix_functions.userdata = &matrix_userdata;
render.matrix_functions.to_world_space = _bolt_gl_plugin_matrix3d_toworldspace;
render.matrix_functions.to_screen_space = _bolt_gl_plugin_matrix3d_toscreenspace;
render.matrix_functions.world_pos = _bolt_gl_plugin_matrix3d_worldpos;
_bolt_plugin_handle_3d(&render);
}
@@ -1473,6 +1484,48 @@ void _bolt_gl_plugin_drawelements_vertex3d_colour(size_t index, void* userdata,
out[3] = (double)colour[0];
}
void _bolt_gl_plugin_matrix3d_toworldspace(int x, int y, int z, void* userdata, double* out) {
const struct GLPlugin3DMatrixUserData* data = userdata;
const double dx = (double)x;
const double dy = (double)y;
const double dz = (double)z;
const float* mmx = data->model_matrix;
const double outx = (dx * (double)mmx[0]) + (dy * mmx[4]) + (dz * mmx[8]) + mmx[12];
const double outy = (dx * (double)mmx[1]) + (dy * mmx[5]) + (dz * mmx[9]) + mmx[13];
const double outz = (dx * (double)mmx[2]) + (dy * mmx[6]) + (dz * mmx[10]) + mmx[14];
const double homogenous = (dx * (double)mmx[3]) + (dy * mmx[7]) + (dz * mmx[11]) + mmx[15];
out[0] = outx / homogenous;
out[1] = outy / homogenous;
out[2] = outz / homogenous;
}
void _bolt_gl_plugin_matrix3d_toscreenspace(int x, int y, int z, void* userdata, double* out) {
const struct GLContext* c = _bolt_context();
struct GLPlugin3DMatrixUserData* data = userdata;
const double dx = (double)x;
const double dy = (double)y;
const double dz = (double)z;
const float* mmx = data->model_matrix;
const float* vpmx = data->viewproj_matrix;
const double mx = (dx * (double)mmx[0]) + (dy * (double)mmx[4]) + (dz * (double)mmx[8]) + (double)mmx[12];
const double my = (dx * (double)mmx[1]) + (dy * (double)mmx[5]) + (dz * (double)mmx[9]) + (double)mmx[13];
const double mz = (dx * (double)mmx[2]) + (dy * (double)mmx[6]) + (dz * (double)mmx[10]) + (double)mmx[14];
const double mh = (dx * (double)mmx[3]) + (dy * (double)mmx[7]) + (dz * (double)mmx[11]) + (double)mmx[15];
const double outx = (mx * (double)vpmx[0]) + (my * (double)vpmx[4]) + (mz * (double)vpmx[8]) + (mh * (double)vpmx[12]);
const double outy = (mx * (double)vpmx[1]) + (my * (double)vpmx[5]) + (mz * (double)vpmx[9]) + (mh * (double)vpmx[13]);
const double homogenous = (mx * (double)vpmx[3]) + (my * (double)vpmx[7]) + (mz * (double)vpmx[11]) + (mh * (double)vpmx[15]);
out[0] = (((outx / homogenous) + 1.0) * c->game_view_w / 2.0) + (double)c->game_view_x;
out[1] = (((-outy / homogenous) + 1.0) * c->game_view_h / 2.0) + (double)c->game_view_y;
}
void _bolt_gl_plugin_matrix3d_worldpos(void* userdata, double* out) {
struct GLPlugin3DMatrixUserData* data = userdata;
const float* mmx = data->model_matrix;
out[0] = (double)data->model_matrix[12];
out[1] = (double)data->model_matrix[13];
out[2] = (double)data->model_matrix[14];
}
size_t _bolt_gl_plugin_texture_id(void* userdata) {
const struct GLPluginTextureUserData* data = userdata;
return data->tex->id;

View File

@@ -310,6 +310,14 @@ void _bolt_gl_plugin_drawelements_vertex3d_meta_xywh(size_t meta, void* userdata
void _bolt_gl_plugin_drawelements_vertex3d_uv(size_t index, void* userdata, double* out);
void _bolt_gl_plugin_drawelements_vertex3d_colour(size_t index, void* userdata, double* out);
struct GLPlugin3DMatrixUserData {
float model_matrix[16];
float viewproj_matrix[16];
};
void _bolt_gl_plugin_matrix3d_toworldspace(int x, int y, int z, void* userdata, double* out);
void _bolt_gl_plugin_matrix3d_toscreenspace(int x, int y, int z, void* userdata, double* out);
void _bolt_gl_plugin_matrix3d_worldpos(void* userdata, double* out);
struct GLPluginTextureUserData {
struct GLTexture2D* tex;
};

View File

@@ -131,7 +131,7 @@ void _bolt_plugin_init(void (*_surface_init)(struct SurfaceFunctions*, unsigned
lua_pushstring(state, RENDER3D_META_REGISTRYNAME);
lua_newtable(state);
lua_pushstring(state, "__index");
lua_createtable(state, 0, 10);
lua_createtable(state, 0, 13);
API_ADD_SUB(vertexcount, render3d)
API_ADD_SUB(vertexxyz, render3d)
API_ADD_SUB(vertexmeta, render3d)
@@ -142,6 +142,9 @@ void _bolt_plugin_init(void (*_surface_init)(struct SurfaceFunctions*, unsigned
API_ADD_SUB(texturesize, render3d)
API_ADD_SUB(texturecompare, render3d)
API_ADD_SUB(texturedata, render3d)
API_ADD_SUB(toworldspace, render3d)
API_ADD_SUB(toscreenspace, render3d)
API_ADD_SUB(worldposition, render3d)
API_ADD_SUB_ALIAS(vertexcolour, vertexcolor, render3d)
lua_settable(state, -3);
lua_settable(state, LUA_REGISTRYINDEX);
@@ -628,3 +631,41 @@ static int api_render3d_texturedata(lua_State* state) {
lua_pushlstring(state, (const char*)ret, len);
return 1;
}
static int api_render3d_toworldspace(lua_State* state) {
_bolt_check_argc(state, 4, "render3d_toworldspace");
struct Render3D* render = lua_touserdata(state, 1);
const int x = lua_tointeger(state, 2);
const int y = lua_tointeger(state, 3);
const int z = lua_tointeger(state, 4);
double out[3];
render->matrix_functions.to_world_space(x, y, z, render->matrix_functions.userdata, out);
lua_pushnumber(state, out[0]);
lua_pushnumber(state, out[1]);
lua_pushnumber(state, out[2]);
return 3;
}
static int api_render3d_toscreenspace(lua_State* state) {
_bolt_check_argc(state, 4, "render3d_toscreenspace");
struct Render3D* render = lua_touserdata(state, 1);
const int x = lua_tointeger(state, 2);
const int y = lua_tointeger(state, 3);
const int z = lua_tointeger(state, 4);
double out[2];
render->matrix_functions.to_screen_space(x, y, z, render->matrix_functions.userdata, out);
lua_pushnumber(state, out[0]);
lua_pushnumber(state, out[1]);
return 2;
}
static int api_render3d_worldposition(lua_State* state) {
_bolt_check_argc(state, 1, "render3d_worldposition");
struct Render3D* render = lua_touserdata(state, 1);
double out[3];
render->matrix_functions.world_pos(render->matrix_functions.userdata, out);
lua_pushnumber(state, out[0]);
lua_pushnumber(state, out[1]);
lua_pushnumber(state, out[2]);
return 3;
}

View File

@@ -80,6 +80,21 @@ struct TextureFunctions {
uint8_t* (*data)(void* userdata, size_t x, size_t y);
};
/// Struct containing "vtable" callback information for 3D renders' transformation matrices.
struct Render3DMatrixFunctions {
/// Userdata which will be passed to the functions contained in this struct.
void* userdata;
/// Converts an XYZ coordinate from model space to world space.
void (*to_world_space)(int x, int y, int z, void* userdata, double* out);
/// Converts an XYZ coordinate from model space to screen space in pixels.
void (*to_screen_space)(int x, int y, int z, void* userdata, double* out);
/// Gets the world-space coordinate equivalent to (0,0,0) in model space.
void (*world_pos)(void* userdata, double* out);
};
/// Struct containing "vtable" callback information for surfaces.
struct SurfaceFunctions {
/// Userdata which will be passed to the functions contained in this struct.
@@ -107,6 +122,7 @@ struct Render3D {
uint32_t vertex_count;
struct Vertex3DFunctions vertex_functions;
struct TextureFunctions texture_functions;
struct Render3DMatrixFunctions matrix_functions;
};
struct RenderMinimapEvent {

View File

@@ -351,3 +351,18 @@ static int api_render3d_texturecompare(lua_State*);
/// Encoding Lua strings is computationally expensive, and indexing the data one byte at a time is
/// even more so. Unless you really need to do that, use `texturecompare()` instead.
static int api_render3d_texturedata(lua_State*);
/// [-4, +3, -]
/// Converts an XYZ coordinate from model space to world space using this render's model matrix.
static int api_render3d_toworldspace(lua_State*);
/// [-4, +2, -]
/// Converts an XYZ coordinate from model space to screen space using this render's model, view,
/// and projection matrices. Output is in pixels.
static int api_render3d_toscreenspace(lua_State*);
/// [-1, +3, -]
/// Returns the world coordinates this model is being rendered at.
///
/// Equivalent to `render:toworldspace(0, 0, 0)`
static int api_render3d_worldposition(lua_State*);