mirror of https://github.com/bjornbytes/lovr.git
Rename Buffer to Mesh;
This commit is contained in:
parent
3da4d4def9
commit
a2e1fd8972
|
@ -6,9 +6,9 @@
|
|||
#include "filesystem/filesystem.h"
|
||||
#include <math.h>
|
||||
|
||||
map_int_t BufferAttributeTypes;
|
||||
map_int_t BufferDrawModes;
|
||||
map_int_t BufferUsages;
|
||||
map_int_t MeshAttributeTypes;
|
||||
map_int_t MeshDrawModes;
|
||||
map_int_t MeshUsages;
|
||||
map_int_t CompareModes;
|
||||
map_int_t DrawModes;
|
||||
map_int_t FilterModes;
|
||||
|
@ -64,28 +64,28 @@ static Texture* luax_readtexture(lua_State* L, int index) {
|
|||
int l_lovrGraphicsInit(lua_State* L) {
|
||||
lua_newtable(L);
|
||||
luaL_register(L, NULL, lovrGraphics);
|
||||
luax_registertype(L, "Buffer", lovrBuffer);
|
||||
luax_registertype(L, "Mesh", lovrMesh);
|
||||
luax_registertype(L, "Font", lovrFont);
|
||||
luax_registertype(L, "Model", lovrModel);
|
||||
luax_registertype(L, "Shader", lovrShader);
|
||||
luax_registertype(L, "Skybox", lovrSkybox);
|
||||
luax_registertype(L, "Texture", lovrTexture);
|
||||
|
||||
map_init(&BufferAttributeTypes);
|
||||
map_set(&BufferAttributeTypes, "float", BUFFER_FLOAT);
|
||||
map_set(&BufferAttributeTypes, "byte", BUFFER_BYTE);
|
||||
map_set(&BufferAttributeTypes, "int", BUFFER_INT);
|
||||
map_init(&MeshAttributeTypes);
|
||||
map_set(&MeshAttributeTypes, "float", MESH_FLOAT);
|
||||
map_set(&MeshAttributeTypes, "byte", MESH_BYTE);
|
||||
map_set(&MeshAttributeTypes, "int", MESH_INT);
|
||||
|
||||
map_init(&BufferDrawModes);
|
||||
map_set(&BufferDrawModes, "points", BUFFER_POINTS);
|
||||
map_set(&BufferDrawModes, "strip", BUFFER_TRIANGLE_STRIP);
|
||||
map_set(&BufferDrawModes, "triangles", BUFFER_TRIANGLES);
|
||||
map_set(&BufferDrawModes, "fan", BUFFER_TRIANGLE_FAN);
|
||||
map_init(&MeshDrawModes);
|
||||
map_set(&MeshDrawModes, "points", MESH_POINTS);
|
||||
map_set(&MeshDrawModes, "strip", MESH_TRIANGLE_STRIP);
|
||||
map_set(&MeshDrawModes, "triangles", MESH_TRIANGLES);
|
||||
map_set(&MeshDrawModes, "fan", MESH_TRIANGLE_FAN);
|
||||
|
||||
map_init(&BufferUsages);
|
||||
map_set(&BufferUsages, "static", BUFFER_STATIC);
|
||||
map_set(&BufferUsages, "dynamic", BUFFER_DYNAMIC);
|
||||
map_set(&BufferUsages, "stream", BUFFER_STREAM);
|
||||
map_init(&MeshUsages);
|
||||
map_set(&MeshUsages, "static", MESH_STATIC);
|
||||
map_set(&MeshUsages, "dynamic", MESH_DYNAMIC);
|
||||
map_set(&MeshUsages, "stream", MESH_STREAM);
|
||||
|
||||
map_init(&DrawModes);
|
||||
map_set(&DrawModes, "fill", DRAW_MODE_FILL);
|
||||
|
@ -515,74 +515,6 @@ int l_lovrGraphicsPrint(lua_State* L) {
|
|||
|
||||
// Types
|
||||
|
||||
int l_lovrGraphicsNewBuffer(lua_State* L) {
|
||||
int size;
|
||||
int dataIndex = 0;
|
||||
int drawModeIndex = 2;
|
||||
BufferFormat format;
|
||||
vec_init(&format);
|
||||
|
||||
if (lua_isnumber(L, 1)) {
|
||||
size = lua_tointeger(L, 1);
|
||||
} else if (lua_istable(L, 1)) {
|
||||
if (lua_isnumber(L, 2)) {
|
||||
drawModeIndex++;
|
||||
luax_checkbufferformat(L, 1, &format);
|
||||
size = lua_tointeger(L, 2);
|
||||
dataIndex = 0;
|
||||
} else if (lua_istable(L, 2)) {
|
||||
drawModeIndex++;
|
||||
luax_checkbufferformat(L, 1, &format);
|
||||
size = lua_objlen(L, 2);
|
||||
dataIndex = 2;
|
||||
} else {
|
||||
size = lua_objlen(L, 1);
|
||||
dataIndex = 1;
|
||||
}
|
||||
} else {
|
||||
luaL_argerror(L, 1, "table or number expected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
BufferDrawMode* drawMode = (BufferDrawMode*) luax_optenum(L, drawModeIndex, "fan", &BufferDrawModes, "buffer draw mode");
|
||||
BufferUsage* usage = (BufferUsage*) luax_optenum(L, drawModeIndex + 1, "dynamic", &BufferUsages, "buffer usage");
|
||||
Buffer* buffer = lovrBufferCreate(size, format.length ? &format : NULL, *drawMode, *usage);
|
||||
|
||||
if (dataIndex) {
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
|
||||
lua_rawgeti(L, dataIndex, i + 1);
|
||||
if (!lua_istable(L, -1)) {
|
||||
return luaL_error(L, "Vertex information should be specified as a table");
|
||||
}
|
||||
|
||||
int component = 0;
|
||||
char* vertex = lovrBufferGetScratchVertex(buffer);
|
||||
for (int j = 0; j < format.length; j++) {
|
||||
BufferAttribute attribute = format.data[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
lua_rawgeti(L, -1, ++component);
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
|
||||
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
|
||||
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
lovrBufferSetVertex(buffer, i, lovrBufferGetScratchVertex(buffer));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
vec_deinit(&format);
|
||||
luax_pushtype(L, Buffer, buffer);
|
||||
lovrRelease(&buffer->ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsNewFont(lua_State* L) {
|
||||
void* data = NULL;
|
||||
size_t size = 0;
|
||||
|
@ -609,6 +541,74 @@ int l_lovrGraphicsNewFont(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsNewMesh(lua_State* L) {
|
||||
int size;
|
||||
int dataIndex = 0;
|
||||
int drawModeIndex = 2;
|
||||
MeshFormat format;
|
||||
vec_init(&format);
|
||||
|
||||
if (lua_isnumber(L, 1)) {
|
||||
size = lua_tointeger(L, 1);
|
||||
} else if (lua_istable(L, 1)) {
|
||||
if (lua_isnumber(L, 2)) {
|
||||
drawModeIndex++;
|
||||
luax_checkmeshformat(L, 1, &format);
|
||||
size = lua_tointeger(L, 2);
|
||||
dataIndex = 0;
|
||||
} else if (lua_istable(L, 2)) {
|
||||
drawModeIndex++;
|
||||
luax_checkmeshformat(L, 1, &format);
|
||||
size = lua_objlen(L, 2);
|
||||
dataIndex = 2;
|
||||
} else {
|
||||
size = lua_objlen(L, 1);
|
||||
dataIndex = 1;
|
||||
}
|
||||
} else {
|
||||
luaL_argerror(L, 1, "table or number expected");
|
||||
return 0;
|
||||
}
|
||||
|
||||
MeshDrawMode* drawMode = (MeshDrawMode*) luax_optenum(L, drawModeIndex, "fan", &MeshDrawModes, "mesh draw mode");
|
||||
MeshUsage* usage = (MeshUsage*) luax_optenum(L, drawModeIndex + 1, "dynamic", &MeshUsages, "mesh usage");
|
||||
Mesh* mesh = lovrMeshCreate(size, format.length ? &format : NULL, *drawMode, *usage);
|
||||
|
||||
if (dataIndex) {
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
for (size_t i = 0; i < lua_objlen(L, dataIndex); i++) {
|
||||
lua_rawgeti(L, dataIndex, i + 1);
|
||||
if (!lua_istable(L, -1)) {
|
||||
return luaL_error(L, "Vertex information should be specified as a table");
|
||||
}
|
||||
|
||||
int component = 0;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
for (int j = 0; j < format.length; j++) {
|
||||
MeshAttribute attribute = format.data[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
lua_rawgeti(L, -1, ++component);
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
|
||||
case MESH_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
|
||||
case MESH_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, i, lovrMeshGetScratchVertex(mesh));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
vec_deinit(&format);
|
||||
luax_pushtype(L, Mesh, mesh);
|
||||
lovrRelease(&mesh->ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrGraphicsNewModel(lua_State* L) {
|
||||
const char* path = lua_tostring(L, 1);
|
||||
size_t size;
|
||||
|
@ -757,8 +757,8 @@ const luaL_Reg lovrGraphics[] = {
|
|||
{ "getWidth", l_lovrGraphicsGetWidth },
|
||||
{ "getHeight", l_lovrGraphicsGetHeight },
|
||||
{ "getDimensions", l_lovrGraphicsGetDimensions },
|
||||
{ "newBuffer", l_lovrGraphicsNewBuffer },
|
||||
{ "newFont", l_lovrGraphicsNewFont },
|
||||
{ "newMesh", l_lovrGraphicsNewMesh },
|
||||
{ "newModel", l_lovrGraphicsNewModel },
|
||||
{ "newShader", l_lovrGraphicsNewShader },
|
||||
{ "newSkybox", l_lovrGraphicsNewSkybox },
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "luax.h"
|
||||
#include "graphics/buffer.h"
|
||||
#include "graphics/mesh.h"
|
||||
#include "math/math.h"
|
||||
#include "lib/map/map.h"
|
||||
|
||||
|
@ -12,7 +12,6 @@ int l_lovrMathInit(lua_State* L);
|
|||
int l_lovrTimerInit(lua_State* L);
|
||||
|
||||
extern const luaL_Reg lovrAudio[];
|
||||
extern const luaL_Reg lovrBuffer[];
|
||||
extern const luaL_Reg lovrController[];
|
||||
extern const luaL_Reg lovrEvent[];
|
||||
extern const luaL_Reg lovrFilesystem[];
|
||||
|
@ -20,6 +19,7 @@ extern const luaL_Reg lovrFont[];
|
|||
extern const luaL_Reg lovrGraphics[];
|
||||
extern const luaL_Reg lovrHeadset[];
|
||||
extern const luaL_Reg lovrMath[];
|
||||
extern const luaL_Reg lovrMesh[];
|
||||
extern const luaL_Reg lovrModel[];
|
||||
extern const luaL_Reg lovrShader[];
|
||||
extern const luaL_Reg lovrSkybox[];
|
||||
|
@ -28,9 +28,9 @@ extern const luaL_Reg lovrTexture[];
|
|||
extern const luaL_Reg lovrTimer[];
|
||||
extern const luaL_Reg lovrTransform[];
|
||||
|
||||
extern map_int_t BufferAttributeTypes;
|
||||
extern map_int_t BufferDrawModes;
|
||||
extern map_int_t BufferUsages;
|
||||
extern map_int_t MeshAttributeTypes;
|
||||
extern map_int_t MeshDrawModes;
|
||||
extern map_int_t MeshUsages;
|
||||
extern map_int_t CompareModes;
|
||||
extern map_int_t ControllerAxes;
|
||||
extern map_int_t ControllerButtons;
|
||||
|
@ -43,5 +43,5 @@ extern map_int_t TextureProjections;
|
|||
extern map_int_t TimeUnits;
|
||||
extern map_int_t WrapModes;
|
||||
|
||||
void luax_checkbufferformat(lua_State* L, int index, BufferFormat* format);
|
||||
void luax_checkmeshformat(lua_State* L, int index, MeshFormat* format);
|
||||
void luax_readtransform(lua_State* L, int i, mat4 transform);
|
||||
|
|
|
@ -1,371 +0,0 @@
|
|||
#include "api/lovr.h"
|
||||
|
||||
void luax_checkbufferformat(lua_State* L, int index, BufferFormat* format) {
|
||||
if (!lua_istable(L, index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int length = lua_objlen(L, index);
|
||||
for (int i = 0; i < length; i++) {
|
||||
lua_rawgeti(L, index, i + 1);
|
||||
|
||||
if (!lua_istable(L, -1) || lua_objlen(L, -1) != 3) {
|
||||
luaL_error(L, "Expected vertex format specified as tables containing name, data type, and size");
|
||||
return;
|
||||
}
|
||||
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua_rawgeti(L, -2, 2);
|
||||
lua_rawgeti(L, -3, 3);
|
||||
|
||||
const char* name = lua_tostring(L, -3);
|
||||
BufferAttributeType* type = (BufferAttributeType*) luax_checkenum(L, -2, &BufferAttributeTypes, "buffer attribute type");
|
||||
int count = lua_tointeger(L, -1);
|
||||
BufferAttribute attribute = { .name = name, .type = *type, .count = count };
|
||||
vec_push(format, attribute);
|
||||
lua_pop(L, 4);
|
||||
}
|
||||
}
|
||||
|
||||
int l_lovrBufferDraw(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
float transform[16];
|
||||
luax_readtransform(L, 2, transform);
|
||||
lovrBufferDraw(buffer, transform);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetVertexFormat(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
BufferAttribute attribute = format.data[i];
|
||||
lua_newtable(L);
|
||||
|
||||
// Name
|
||||
lua_pushstring(L, attribute.name);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
// Type
|
||||
luax_pushenum(L, &BufferAttributeTypes, attribute.type);
|
||||
lua_rawseti(L, -2, 2);
|
||||
|
||||
// Count
|
||||
lua_pushinteger(L, attribute.count);
|
||||
lua_rawseti(L, -2, 3);
|
||||
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetDrawMode(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
luax_pushenum(L, &BufferDrawModes, lovrBufferGetDrawMode(buffer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetDrawMode(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
BufferDrawMode* drawMode = (BufferDrawMode*) luax_checkenum(L, 2, &BufferDrawModes, "buffer draw mode");
|
||||
lovrBufferSetDrawMode(buffer, *drawMode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetVertexCount(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
lua_pushnumber(L, lovrBufferGetVertexCount(buffer));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetVertex(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
char* vertex = lovrBufferGetScratchVertex(buffer);
|
||||
lovrBufferGetVertex(buffer, index, vertex);
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
|
||||
int total = 0;
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
BufferAttribute attribute = format.data[i];
|
||||
total += attribute.count;
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: lua_pushnumber(L, *((float*) vertex)); break;
|
||||
case BUFFER_BYTE: lua_pushnumber(L, *((unsigned char*) vertex)); break;
|
||||
case BUFFER_INT: lua_pushnumber(L, *((int*) vertex)); break;
|
||||
}
|
||||
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetVertex(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
char* vertex = lovrBufferGetScratchVertex(buffer);
|
||||
|
||||
if (index < 0 || index >= buffer->size) {
|
||||
return luaL_error(L, "Invalid buffer vertex index: %d", index + 1);
|
||||
}
|
||||
|
||||
// Unwrap table
|
||||
int arg = 3;
|
||||
if (lua_istable(L, 3)) {
|
||||
arg++;
|
||||
for (size_t i = 0; i < lua_objlen(L, 3); i++) {
|
||||
lua_rawgeti(L, 3, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
BufferAttribute attribute = format.data[i];
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, arg++, 255); break;
|
||||
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
lovrBufferSetVertex(buffer, index, lovrBufferGetScratchVertex(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetVertexAttribute(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrBufferGetScratchVertex(buffer);
|
||||
lovrBufferGetVertex(buffer, vertexIndex, vertex);
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= buffer->size) {
|
||||
return luaL_error(L, "Invalid buffer vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid buffer attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
BufferAttribute attribute;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
attribute = format.data[i];
|
||||
if (i == attributeIndex) {
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: lua_pushnumber(L, *((float*) vertex)); break;
|
||||
case BUFFER_BYTE: lua_pushinteger(L, *((unsigned char*) vertex)); break;
|
||||
case BUFFER_INT: lua_pushinteger(L, *((int*) vertex)); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
} else {
|
||||
vertex += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
return attribute.count;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetVertexAttribute(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrBufferGetScratchVertex(buffer);
|
||||
lovrBufferGetVertex(buffer, vertexIndex, vertex);
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= buffer->size) {
|
||||
return luaL_error(L, "Invalid buffer vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid buffer attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
int arg = 4;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
BufferAttribute attribute = format.data[i];
|
||||
if (i == attributeIndex) {
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, arg++, 255); break;
|
||||
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
} else {
|
||||
vertex += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
lovrBufferSetVertex(buffer, vertexIndex, lovrBufferGetScratchVertex(buffer));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetVertices(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
BufferFormat format = lovrBufferGetVertexFormat(buffer);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int vertexCount = lua_objlen(L, 2);
|
||||
|
||||
if (vertexCount > lovrBufferGetVertexCount(buffer)) {
|
||||
return luaL_error(L, "Too many vertices for Buffer\n", lovrBufferGetVertexCount(buffer));
|
||||
}
|
||||
|
||||
char* vertices = malloc(buffer->stride * vertexCount);
|
||||
char* vertex = vertices;
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
int component = 0;
|
||||
for (int j = 0; j < format.length; j++) {
|
||||
BufferAttribute attribute = format.data[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
lua_rawgeti(L, -1, ++component);
|
||||
switch (attribute.type) {
|
||||
case BUFFER_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
|
||||
case BUFFER_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
|
||||
case BUFFER_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrBufferSetVertices(buffer, vertices, buffer->stride * vertexCount);
|
||||
free(vertices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetVertexMap(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
int count;
|
||||
unsigned int* indices = lovrBufferGetVertexMap(buffer, &count);
|
||||
|
||||
if (count == 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_pushinteger(L, indices[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetVertexMap(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrBufferSetVertexMap(buffer, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int count = lua_objlen(L, 2);
|
||||
unsigned int* indices = malloc(count * sizeof(unsigned int));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
free(indices);
|
||||
return luaL_error(L, "Buffer vertex map index #%d must be numeric", i);
|
||||
}
|
||||
|
||||
int index = lua_tointeger(L, -1);
|
||||
if (index > buffer->size || index < 0) {
|
||||
free(indices);
|
||||
return luaL_error(L, "Invalid vertex map value: %d", index);
|
||||
}
|
||||
|
||||
indices[i] = index - 1;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrBufferSetVertexMap(buffer, indices, count);
|
||||
free(indices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetDrawRange(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
if (!lovrBufferIsRangeEnabled(buffer)) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int start, count;
|
||||
lovrBufferGetDrawRange(buffer, &start, &count);
|
||||
lua_pushinteger(L, start + 1);
|
||||
lua_pushinteger(L, count);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetDrawRange(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrBufferSetRangeEnabled(buffer, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lovrBufferSetRangeEnabled(buffer, 1);
|
||||
int rangeStart = luaL_checkinteger(L, 2) - 1;
|
||||
int rangeCount = luaL_checkinteger(L, 3);
|
||||
if (lovrBufferSetDrawRange(buffer, rangeStart, rangeCount)) {
|
||||
return luaL_error(L, "Invalid buffer draw range (%d, %d)", rangeStart + 1, rangeCount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrBufferGetTexture(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
Texture* texture = lovrBufferGetTexture(buffer);
|
||||
|
||||
if (texture) {
|
||||
luax_pushtype(L, Texture, texture);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrBufferSetTexture(lua_State* L) {
|
||||
Buffer* buffer = luax_checktype(L, 1, Buffer);
|
||||
Texture* texture = lua_isnoneornil(L, 2) ? NULL : luax_checktype(L, 2, Texture);
|
||||
lovrBufferSetTexture(buffer, texture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrBuffer[] = {
|
||||
{ "draw", l_lovrBufferDraw },
|
||||
{ "getVertexFormat", l_lovrBufferGetVertexFormat },
|
||||
{ "getVertexCount", l_lovrBufferGetVertexCount },
|
||||
{ "getVertex", l_lovrBufferGetVertex },
|
||||
{ "setVertex", l_lovrBufferSetVertex },
|
||||
{ "getVertexAttribute", l_lovrBufferGetVertexAttribute },
|
||||
{ "setVertexAttribute", l_lovrBufferSetVertexAttribute },
|
||||
{ "setVertices", l_lovrBufferSetVertices },
|
||||
{ "getVertexMap", l_lovrBufferGetVertexMap },
|
||||
{ "setVertexMap", l_lovrBufferSetVertexMap },
|
||||
{ "getDrawMode", l_lovrBufferGetDrawMode },
|
||||
{ "setDrawMode", l_lovrBufferSetDrawMode },
|
||||
{ "getDrawRange", l_lovrBufferGetDrawRange },
|
||||
{ "setDrawRange", l_lovrBufferSetDrawRange },
|
||||
{ "getTexture", l_lovrBufferGetTexture },
|
||||
{ "setTexture", l_lovrBufferSetTexture },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -0,0 +1,371 @@
|
|||
#include "api/lovr.h"
|
||||
|
||||
void luax_checkmeshformat(lua_State* L, int index, MeshFormat* format) {
|
||||
if (!lua_istable(L, index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int length = lua_objlen(L, index);
|
||||
for (int i = 0; i < length; i++) {
|
||||
lua_rawgeti(L, index, i + 1);
|
||||
|
||||
if (!lua_istable(L, -1) || lua_objlen(L, -1) != 3) {
|
||||
luaL_error(L, "Expected vertex format specified as tables containing name, data type, and size");
|
||||
return;
|
||||
}
|
||||
|
||||
lua_rawgeti(L, -1, 1);
|
||||
lua_rawgeti(L, -2, 2);
|
||||
lua_rawgeti(L, -3, 3);
|
||||
|
||||
const char* name = lua_tostring(L, -3);
|
||||
MeshAttributeType* type = (MeshAttributeType*) luax_checkenum(L, -2, &MeshAttributeTypes, "mesh attribute type");
|
||||
int count = lua_tointeger(L, -1);
|
||||
MeshAttribute attribute = { .name = name, .type = *type, .count = count };
|
||||
vec_push(format, attribute);
|
||||
lua_pop(L, 4);
|
||||
}
|
||||
}
|
||||
|
||||
int l_lovrMeshDraw(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
float transform[16];
|
||||
luax_readtransform(L, 2, transform);
|
||||
lovrMeshDraw(mesh, transform);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexFormat(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
MeshAttribute attribute = format.data[i];
|
||||
lua_newtable(L);
|
||||
|
||||
// Name
|
||||
lua_pushstring(L, attribute.name);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
// Type
|
||||
luax_pushenum(L, &MeshAttributeTypes, attribute.type);
|
||||
lua_rawseti(L, -2, 2);
|
||||
|
||||
// Count
|
||||
lua_pushinteger(L, attribute.count);
|
||||
lua_rawseti(L, -2, 3);
|
||||
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetDrawMode(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
luax_pushenum(L, &MeshDrawModes, lovrMeshGetDrawMode(mesh));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetDrawMode(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
MeshDrawMode* drawMode = (MeshDrawMode*) luax_checkenum(L, 2, &MeshDrawModes, "mesh draw mode");
|
||||
lovrMeshSetDrawMode(mesh, *drawMode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexCount(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
lua_pushnumber(L, lovrMeshGetVertexCount(mesh));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, index, vertex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
int total = 0;
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
MeshAttribute attribute = format.data[i];
|
||||
total += attribute.count;
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: lua_pushnumber(L, *((float*) vertex)); break;
|
||||
case MESH_BYTE: lua_pushnumber(L, *((unsigned char*) vertex)); break;
|
||||
case MESH_INT: lua_pushnumber(L, *((int*) vertex)); break;
|
||||
}
|
||||
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
|
||||
if (index < 0 || index >= mesh->size) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", index + 1);
|
||||
}
|
||||
|
||||
// Unwrap table
|
||||
int arg = 3;
|
||||
if (lua_istable(L, 3)) {
|
||||
arg++;
|
||||
for (size_t i = 0; i < lua_objlen(L, 3); i++) {
|
||||
lua_rawgeti(L, 3, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < format.length; i++) {
|
||||
MeshAttribute attribute = format.data[i];
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: *((float*) vertex) = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case MESH_BYTE: *((unsigned char*) vertex) = luaL_optint(L, arg++, 255); break;
|
||||
case MESH_INT: *((int*) vertex) = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, index, lovrMeshGetScratchVertex(mesh));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexAttribute(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, vertexIndex, vertex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
MeshAttribute attribute;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
attribute = format.data[i];
|
||||
if (i == attributeIndex) {
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: lua_pushnumber(L, *((float*) vertex)); break;
|
||||
case MESH_BYTE: lua_pushinteger(L, *((unsigned char*) vertex)); break;
|
||||
case MESH_INT: lua_pushinteger(L, *((int*) vertex)); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
} else {
|
||||
vertex += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
return attribute.count;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
char* vertex = lovrMeshGetScratchVertex(mesh);
|
||||
lovrMeshGetVertex(mesh, vertexIndex, vertex);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= mesh->size) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format.length) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
int arg = 4;
|
||||
for (int i = 0; i <= attributeIndex; i++) {
|
||||
MeshAttribute attribute = format.data[i];
|
||||
if (i == attributeIndex) {
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: *((float*) vertex) = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case MESH_BYTE: *((unsigned char*) vertex) = luaL_optint(L, arg++, 255); break;
|
||||
case MESH_INT: *((int*) vertex) = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
}
|
||||
} else {
|
||||
vertex += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
}
|
||||
|
||||
lovrMeshSetVertex(mesh, vertexIndex, lovrMeshGetScratchVertex(mesh));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetVertices(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
MeshFormat format = lovrMeshGetVertexFormat(mesh);
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int vertexCount = lua_objlen(L, 2);
|
||||
|
||||
if (vertexCount > lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Too many vertices for Mesh\n", lovrMeshGetVertexCount(mesh));
|
||||
}
|
||||
|
||||
char* vertices = malloc(mesh->stride * vertexCount);
|
||||
char* vertex = vertices;
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
int component = 0;
|
||||
for (int j = 0; j < format.length; j++) {
|
||||
MeshAttribute attribute = format.data[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
lua_rawgeti(L, -1, ++component);
|
||||
switch (attribute.type) {
|
||||
case MESH_FLOAT: *((float*) vertex) = luaL_optnumber(L, -1, 0.f); break;
|
||||
case MESH_BYTE: *((unsigned char*) vertex) = luaL_optint(L, -1, 255); break;
|
||||
case MESH_INT: *((int*) vertex) = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
vertex += sizeof(attribute.type);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrMeshSetVertices(mesh, vertices, mesh->stride * vertexCount);
|
||||
free(vertices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexMap(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int count;
|
||||
unsigned int* indices = lovrMeshGetVertexMap(mesh, &count);
|
||||
|
||||
if (count == 0) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_pushinteger(L, indices[i]);
|
||||
lua_rawseti(L, -2, i + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetVertexMap(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrMeshSetVertexMap(mesh, NULL, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
int count = lua_objlen(L, 2);
|
||||
unsigned int* indices = malloc(count * sizeof(unsigned int));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
if (!lua_isnumber(L, -1)) {
|
||||
free(indices);
|
||||
return luaL_error(L, "Mesh vertex map index #%d must be numeric", i);
|
||||
}
|
||||
|
||||
int index = lua_tointeger(L, -1);
|
||||
if (index > mesh->size || index < 0) {
|
||||
free(indices);
|
||||
return luaL_error(L, "Invalid vertex map value: %d", index);
|
||||
}
|
||||
|
||||
indices[i] = index - 1;
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrMeshSetVertexMap(mesh, indices, count);
|
||||
free(indices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetDrawRange(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
if (!lovrMeshIsRangeEnabled(mesh)) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int start, count;
|
||||
lovrMeshGetDrawRange(mesh, &start, &count);
|
||||
lua_pushinteger(L, start + 1);
|
||||
lua_pushinteger(L, count);
|
||||
return 2;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetDrawRange(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrMeshSetRangeEnabled(mesh, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lovrMeshSetRangeEnabled(mesh, 1);
|
||||
int rangeStart = luaL_checkinteger(L, 2) - 1;
|
||||
int rangeCount = luaL_checkinteger(L, 3);
|
||||
if (lovrMeshSetDrawRange(mesh, rangeStart, rangeCount)) {
|
||||
return luaL_error(L, "Invalid mesh draw range (%d, %d)", rangeStart + 1, rangeCount);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetTexture(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
Texture* texture = lovrMeshGetTexture(mesh);
|
||||
|
||||
if (texture) {
|
||||
luax_pushtype(L, Texture, texture);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrMeshSetTexture(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
Texture* texture = lua_isnoneornil(L, 2) ? NULL : luax_checktype(L, 2, Texture);
|
||||
lovrMeshSetTexture(mesh, texture);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrMesh[] = {
|
||||
{ "draw", l_lovrMeshDraw },
|
||||
{ "getVertexFormat", l_lovrMeshGetVertexFormat },
|
||||
{ "getVertexCount", l_lovrMeshGetVertexCount },
|
||||
{ "getVertex", l_lovrMeshGetVertex },
|
||||
{ "setVertex", l_lovrMeshSetVertex },
|
||||
{ "getVertexAttribute", l_lovrMeshGetVertexAttribute },
|
||||
{ "setVertexAttribute", l_lovrMeshSetVertexAttribute },
|
||||
{ "setVertices", l_lovrMeshSetVertices },
|
||||
{ "getVertexMap", l_lovrMeshGetVertexMap },
|
||||
{ "setVertexMap", l_lovrMeshSetVertexMap },
|
||||
{ "getDrawMode", l_lovrMeshGetDrawMode },
|
||||
{ "setDrawMode", l_lovrMeshSetDrawMode },
|
||||
{ "getDrawRange", l_lovrMeshGetDrawRange },
|
||||
{ "setDrawRange", l_lovrMeshSetDrawRange },
|
||||
{ "getTexture", l_lovrMeshGetTexture },
|
||||
{ "setTexture", l_lovrMeshSetTexture },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -1,237 +0,0 @@
|
|||
#include "graphics/buffer.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "graphics/shader.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
Buffer* lovrBufferCreate(int size, BufferFormat* format, BufferDrawMode drawMode, BufferUsage usage) {
|
||||
Buffer* buffer = lovrAlloc(sizeof(Buffer), lovrBufferDestroy);
|
||||
if (!buffer) return NULL;
|
||||
|
||||
vec_init(&buffer->map);
|
||||
vec_init(&buffer->format);
|
||||
|
||||
if (format) {
|
||||
vec_extend(&buffer->format, format);
|
||||
} else {
|
||||
BufferAttribute position = { .name = "lovrPosition", .type = BUFFER_FLOAT, .count = 3 };
|
||||
BufferAttribute normal = { .name = "lovrNormal", .type = BUFFER_FLOAT, .count = 3 };
|
||||
BufferAttribute texCoord = { .name = "lovrTexCoord", .type = BUFFER_FLOAT, .count = 2 };
|
||||
vec_push(&buffer->format, position);
|
||||
vec_push(&buffer->format, normal);
|
||||
vec_push(&buffer->format, texCoord);
|
||||
}
|
||||
|
||||
int stride = 0;
|
||||
int i;
|
||||
BufferAttribute attribute;
|
||||
vec_foreach(&buffer->format, attribute, i) {
|
||||
stride += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
|
||||
if (stride == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->size = size;
|
||||
buffer->stride = stride;
|
||||
buffer->data = malloc(buffer->size * buffer->stride);
|
||||
buffer->scratchVertex = malloc(buffer->stride);
|
||||
buffer->drawMode = drawMode;
|
||||
buffer->usage = usage;
|
||||
buffer->vao = 0;
|
||||
buffer->vbo = 0;
|
||||
buffer->ibo = 0;
|
||||
buffer->isRangeEnabled = 0;
|
||||
buffer->rangeStart = 0;
|
||||
buffer->rangeCount = buffer->size;
|
||||
buffer->texture = NULL;
|
||||
|
||||
glGenBuffers(1, &buffer->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer->size * buffer->stride, buffer->data, buffer->usage);
|
||||
glGenVertexArrays(1, &buffer->vao);
|
||||
glGenBuffers(1, &buffer->ibo);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void lovrBufferDestroy(const Ref* ref) {
|
||||
Buffer* buffer = containerof(ref, Buffer);
|
||||
if (buffer->texture) {
|
||||
lovrRelease(&buffer->texture->ref);
|
||||
}
|
||||
glDeleteBuffers(1, &buffer->vbo);
|
||||
glDeleteVertexArrays(1, &buffer->vao);
|
||||
vec_deinit(&buffer->map);
|
||||
vec_deinit(&buffer->format);
|
||||
free(buffer->scratchVertex);
|
||||
free(buffer->data);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void lovrBufferDraw(Buffer* buffer, mat4 transform) {
|
||||
int usingIbo = buffer->map.length > 0;
|
||||
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(transform);
|
||||
lovrGraphicsBindTexture(buffer->texture);
|
||||
lovrGraphicsPrepare();
|
||||
|
||||
glBindVertexArray(buffer->vao);
|
||||
|
||||
// Figure out how many vertex attributes there are
|
||||
int vertexAttributeCount;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &vertexAttributeCount);
|
||||
|
||||
// Disable all vertex attributes
|
||||
for (int i = 0; i < vertexAttributeCount; i++) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
// Enable the vertex attributes in use and bind the correct data FIXME
|
||||
Shader* shader = lovrGraphicsGetShader();
|
||||
if (shader) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
|
||||
size_t offset = 0;
|
||||
int i;
|
||||
BufferAttribute attribute;
|
||||
vec_foreach(&buffer->format, attribute, i) {
|
||||
int location = lovrShaderGetAttributeId(shader, attribute.name);
|
||||
if (location >= 0) {
|
||||
glEnableVertexAttribArray(location);
|
||||
if (attribute.type == BUFFER_INT) {
|
||||
glVertexAttribIPointer(location, attribute.count, attribute.type, buffer->stride, (void*) offset);
|
||||
} else {
|
||||
glVertexAttribPointer(location, attribute.count, attribute.type, GL_FALSE, buffer->stride, (void*) offset);
|
||||
}
|
||||
}
|
||||
offset += sizeof(attribute.type) * attribute.count;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine range of vertices to be rendered and whether we're using an IBO or not
|
||||
int start, count;
|
||||
if (buffer->isRangeEnabled) {
|
||||
start = buffer->rangeStart;
|
||||
count = buffer->rangeCount;
|
||||
} else {
|
||||
start = 0;
|
||||
count = usingIbo ? buffer->map.length : buffer->size;
|
||||
}
|
||||
|
||||
// Render! Use the IBO if a draw range is set
|
||||
if (usingIbo) {
|
||||
uintptr_t startAddress = (uintptr_t) start;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->ibo);
|
||||
glDrawElements(buffer->drawMode, count, GL_UNSIGNED_INT, (GLvoid*) startAddress);
|
||||
} else {
|
||||
glDrawArrays(buffer->drawMode, start, count);
|
||||
}
|
||||
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
|
||||
BufferFormat lovrBufferGetVertexFormat(Buffer* buffer) {
|
||||
return buffer->format;
|
||||
}
|
||||
|
||||
BufferDrawMode lovrBufferGetDrawMode(Buffer* buffer) {
|
||||
return buffer->drawMode;
|
||||
}
|
||||
|
||||
int lovrBufferSetDrawMode(Buffer* buffer, BufferDrawMode drawMode) {
|
||||
buffer->drawMode = drawMode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lovrBufferGetVertexCount(Buffer* buffer) {
|
||||
return buffer->size;
|
||||
}
|
||||
|
||||
int lovrBufferGetVertexSize(Buffer* buffer) {
|
||||
return buffer->stride;
|
||||
}
|
||||
|
||||
void* lovrBufferGetScratchVertex(Buffer* buffer) {
|
||||
return buffer->scratchVertex;
|
||||
}
|
||||
|
||||
void lovrBufferGetVertex(Buffer* buffer, int index, void* dest) {
|
||||
if (index >= buffer->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(dest, (char*) buffer->data + index * buffer->stride, buffer->stride);
|
||||
}
|
||||
|
||||
void lovrBufferSetVertex(Buffer* buffer, int index, void* vertex) {
|
||||
memcpy((char*) buffer->data + index * buffer->stride, vertex, buffer->stride);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer->size * buffer->stride, buffer->data, buffer->usage);
|
||||
}
|
||||
|
||||
void lovrBufferSetVertices(Buffer* buffer, void* vertices, int size) {
|
||||
if (size > buffer->size * buffer->stride) {
|
||||
error("Buffer is not big enough");
|
||||
}
|
||||
|
||||
memcpy(buffer->data, vertices, size);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, buffer->size * buffer->stride, buffer->data, buffer->usage);
|
||||
}
|
||||
|
||||
unsigned int* lovrBufferGetVertexMap(Buffer* buffer, int* count) {
|
||||
*count = buffer->map.length;
|
||||
return buffer->map.data;
|
||||
}
|
||||
|
||||
void lovrBufferSetVertexMap(Buffer* buffer, unsigned int* map, int count) {
|
||||
if (count == 0 || !map) {
|
||||
vec_clear(&buffer->map);
|
||||
} else {
|
||||
vec_clear(&buffer->map);
|
||||
vec_pusharr(&buffer->map, map, count);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), buffer->map.data, GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
char lovrBufferIsRangeEnabled(Buffer* buffer) {
|
||||
return buffer->isRangeEnabled;
|
||||
}
|
||||
|
||||
void lovrBufferSetRangeEnabled(Buffer* buffer, char isEnabled) {
|
||||
buffer->isRangeEnabled = isEnabled;
|
||||
}
|
||||
|
||||
void lovrBufferGetDrawRange(Buffer* buffer, int* start, int* count) {
|
||||
*start = buffer->rangeStart;
|
||||
*count = buffer->rangeCount;
|
||||
}
|
||||
|
||||
int lovrBufferSetDrawRange(Buffer* buffer, int start, int count) {
|
||||
if (start < 0 || count < 0 || start + count > buffer->size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer->rangeStart = start;
|
||||
buffer->rangeCount = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture* lovrBufferGetTexture(Buffer* buffer) {
|
||||
return buffer->texture;
|
||||
}
|
||||
|
||||
void lovrBufferSetTexture(Buffer* buffer, Texture* texture) {
|
||||
if (buffer->texture) {
|
||||
lovrRelease(&buffer->texture->ref);
|
||||
}
|
||||
|
||||
buffer->texture = texture;
|
||||
|
||||
if (buffer->texture) {
|
||||
lovrRetain(&buffer->texture->ref);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
#include "glfw.h"
|
||||
#include "util.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "math/math.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
BUFFER_POINTS = GL_POINTS,
|
||||
BUFFER_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
|
||||
BUFFER_TRIANGLES = GL_TRIANGLES,
|
||||
BUFFER_TRIANGLE_FAN = GL_TRIANGLE_FAN
|
||||
} BufferDrawMode;
|
||||
|
||||
typedef enum {
|
||||
BUFFER_STATIC = GL_STATIC_DRAW,
|
||||
BUFFER_DYNAMIC = GL_DYNAMIC_DRAW,
|
||||
BUFFER_STREAM = GL_STREAM_DRAW
|
||||
} BufferUsage;
|
||||
|
||||
typedef enum {
|
||||
BUFFER_FLOAT = GL_FLOAT,
|
||||
BUFFER_BYTE = GL_BYTE,
|
||||
BUFFER_INT = GL_INT
|
||||
} BufferAttributeType;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
BufferAttributeType type;
|
||||
int count;
|
||||
} BufferAttribute;
|
||||
|
||||
typedef vec_t(BufferAttribute) BufferFormat;
|
||||
|
||||
typedef struct Buffer {
|
||||
Ref ref;
|
||||
int size;
|
||||
int stride;
|
||||
void* data;
|
||||
void* scratchVertex;
|
||||
BufferFormat format;
|
||||
BufferDrawMode drawMode;
|
||||
BufferUsage usage;
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
GLuint ibo;
|
||||
vec_uint_t map;
|
||||
char isRangeEnabled;
|
||||
int rangeStart;
|
||||
int rangeCount;
|
||||
Texture* texture;
|
||||
} Buffer;
|
||||
|
||||
Buffer* lovrBufferCreate(int size, BufferFormat* format, BufferDrawMode drawMode, BufferUsage usage);
|
||||
void lovrBufferDestroy(const Ref* ref);
|
||||
void lovrBufferDraw(Buffer* buffer, mat4 transform);
|
||||
BufferFormat lovrBufferGetVertexFormat(Buffer* buffer);
|
||||
BufferDrawMode lovrBufferGetDrawMode(Buffer* buffer);
|
||||
int lovrBufferSetDrawMode(Buffer* buffer, BufferDrawMode drawMode);
|
||||
int lovrBufferGetVertexCount(Buffer* buffer);
|
||||
int lovrBufferGetVertexSize(Buffer* buffer);
|
||||
void* lovrBufferGetScratchVertex(Buffer* buffer);
|
||||
void lovrBufferGetVertex(Buffer* buffer, int index, void* dest);
|
||||
void lovrBufferSetVertex(Buffer* buffer, int index, void* vertex);
|
||||
void lovrBufferSetVertices(Buffer* buffer, void* vertices, int size);
|
||||
unsigned int* lovrBufferGetVertexMap(Buffer* buffer, int* count);
|
||||
void lovrBufferSetVertexMap(Buffer* buffer, unsigned int* map, int count);
|
||||
char lovrBufferIsRangeEnabled(Buffer* buffer);
|
||||
void lovrBufferSetRangeEnabled(Buffer* buffer, char isEnabled);
|
||||
void lovrBufferGetDrawRange(Buffer* buffer, int* start, int* count);
|
||||
int lovrBufferSetDrawRange(Buffer* buffer, int start, int count);
|
||||
Texture* lovrBufferGetTexture(Buffer* buffer);
|
||||
void lovrBufferSetTexture(Buffer* buffer, Texture* texture);
|
|
@ -1,5 +1,5 @@
|
|||
#include "graphics/buffer.h"
|
||||
#include "graphics/font.h"
|
||||
#include "graphics/mesh.h"
|
||||
#include "graphics/model.h"
|
||||
#include "graphics/shader.h"
|
||||
#include "graphics/skybox.h"
|
||||
|
|
|
@ -0,0 +1,237 @@
|
|||
#include "graphics/mesh.h"
|
||||
#include "graphics/graphics.h"
|
||||
#include "graphics/shader.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||
Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy);
|
||||
if (!mesh) return NULL;
|
||||
|
||||
vec_init(&mesh->map);
|
||||
vec_init(&mesh->format);
|
||||
|
||||
if (format) {
|
||||
vec_extend(&mesh->format, format);
|
||||
} else {
|
||||
MeshAttribute position = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
|
||||
MeshAttribute normal = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
|
||||
MeshAttribute texCoord = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
|
||||
vec_push(&mesh->format, position);
|
||||
vec_push(&mesh->format, normal);
|
||||
vec_push(&mesh->format, texCoord);
|
||||
}
|
||||
|
||||
int stride = 0;
|
||||
int i;
|
||||
MeshAttribute attribute;
|
||||
vec_foreach(&mesh->format, attribute, i) {
|
||||
stride += attribute.count * sizeof(attribute.type);
|
||||
}
|
||||
|
||||
if (stride == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mesh->size = size;
|
||||
mesh->stride = stride;
|
||||
mesh->data = malloc(mesh->size * mesh->stride);
|
||||
mesh->scratchVertex = malloc(mesh->stride);
|
||||
mesh->drawMode = drawMode;
|
||||
mesh->usage = usage;
|
||||
mesh->vao = 0;
|
||||
mesh->vbo = 0;
|
||||
mesh->ibo = 0;
|
||||
mesh->isRangeEnabled = 0;
|
||||
mesh->rangeStart = 0;
|
||||
mesh->rangeCount = mesh->size;
|
||||
mesh->texture = NULL;
|
||||
|
||||
glGenBuffers(1, &mesh->vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
glGenBuffers(1, &mesh->ibo);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void lovrMeshDestroy(const Ref* ref) {
|
||||
Mesh* mesh = containerof(ref, Mesh);
|
||||
if (mesh->texture) {
|
||||
lovrRelease(&mesh->texture->ref);
|
||||
}
|
||||
glDeleteBuffers(1, &mesh->vbo);
|
||||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
vec_deinit(&mesh->map);
|
||||
vec_deinit(&mesh->format);
|
||||
free(mesh->scratchVertex);
|
||||
free(mesh->data);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
void lovrMeshDraw(Mesh* mesh, mat4 transform) {
|
||||
int usingIbo = mesh->map.length > 0;
|
||||
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(transform);
|
||||
lovrGraphicsBindTexture(mesh->texture);
|
||||
lovrGraphicsPrepare();
|
||||
|
||||
glBindVertexArray(mesh->vao);
|
||||
|
||||
// Figure out how many vertex attributes there are
|
||||
int vertexAttributeCount;
|
||||
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &vertexAttributeCount);
|
||||
|
||||
// Disable all vertex attributes
|
||||
for (int i = 0; i < vertexAttributeCount; i++) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
|
||||
// Enable the vertex attributes in use and bind the correct data FIXME
|
||||
Shader* shader = lovrGraphicsGetShader();
|
||||
if (shader) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
size_t offset = 0;
|
||||
int i;
|
||||
MeshAttribute attribute;
|
||||
vec_foreach(&mesh->format, attribute, i) {
|
||||
int location = lovrShaderGetAttributeId(shader, attribute.name);
|
||||
if (location >= 0) {
|
||||
glEnableVertexAttribArray(location);
|
||||
if (attribute.type == MESH_INT) {
|
||||
glVertexAttribIPointer(location, attribute.count, attribute.type, mesh->stride, (void*) offset);
|
||||
} else {
|
||||
glVertexAttribPointer(location, attribute.count, attribute.type, GL_FALSE, mesh->stride, (void*) offset);
|
||||
}
|
||||
}
|
||||
offset += sizeof(attribute.type) * attribute.count;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine range of vertices to be rendered and whether we're using an IBO or not
|
||||
int start, count;
|
||||
if (mesh->isRangeEnabled) {
|
||||
start = mesh->rangeStart;
|
||||
count = mesh->rangeCount;
|
||||
} else {
|
||||
start = 0;
|
||||
count = usingIbo ? mesh->map.length : mesh->size;
|
||||
}
|
||||
|
||||
// Render! Use the IBO if a draw range is set
|
||||
if (usingIbo) {
|
||||
uintptr_t startAddress = (uintptr_t) start;
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
|
||||
glDrawElements(mesh->drawMode, count, GL_UNSIGNED_INT, (GLvoid*) startAddress);
|
||||
} else {
|
||||
glDrawArrays(mesh->drawMode, start, count);
|
||||
}
|
||||
|
||||
lovrGraphicsPop();
|
||||
}
|
||||
|
||||
MeshFormat lovrMeshGetVertexFormat(Mesh* mesh) {
|
||||
return mesh->format;
|
||||
}
|
||||
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh) {
|
||||
return mesh->drawMode;
|
||||
}
|
||||
|
||||
int lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode) {
|
||||
mesh->drawMode = drawMode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lovrMeshGetVertexCount(Mesh* mesh) {
|
||||
return mesh->size;
|
||||
}
|
||||
|
||||
int lovrMeshGetVertexSize(Mesh* mesh) {
|
||||
return mesh->stride;
|
||||
}
|
||||
|
||||
void* lovrMeshGetScratchVertex(Mesh* mesh) {
|
||||
return mesh->scratchVertex;
|
||||
}
|
||||
|
||||
void lovrMeshGetVertex(Mesh* mesh, int index, void* dest) {
|
||||
if (index >= mesh->size) {
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(dest, (char*) mesh->data + index * mesh->stride, mesh->stride);
|
||||
}
|
||||
|
||||
void lovrMeshSetVertex(Mesh* mesh, int index, void* vertex) {
|
||||
memcpy((char*) mesh->data + index * mesh->stride, vertex, mesh->stride);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
}
|
||||
|
||||
void lovrMeshSetVertices(Mesh* mesh, void* vertices, int size) {
|
||||
if (size > mesh->size * mesh->stride) {
|
||||
error("Mesh is not big enough");
|
||||
}
|
||||
|
||||
memcpy(mesh->data, vertices, size);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->size * mesh->stride, mesh->data, mesh->usage);
|
||||
}
|
||||
|
||||
unsigned int* lovrMeshGetVertexMap(Mesh* mesh, int* count) {
|
||||
*count = mesh->map.length;
|
||||
return mesh->map.data;
|
||||
}
|
||||
|
||||
void lovrMeshSetVertexMap(Mesh* mesh, unsigned int* map, int count) {
|
||||
if (count == 0 || !map) {
|
||||
vec_clear(&mesh->map);
|
||||
} else {
|
||||
vec_clear(&mesh->map);
|
||||
vec_pusharr(&mesh->map, map, count);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh->ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(unsigned int), mesh->map.data, GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
char lovrMeshIsRangeEnabled(Mesh* mesh) {
|
||||
return mesh->isRangeEnabled;
|
||||
}
|
||||
|
||||
void lovrMeshSetRangeEnabled(Mesh* mesh, char isEnabled) {
|
||||
mesh->isRangeEnabled = isEnabled;
|
||||
}
|
||||
|
||||
void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) {
|
||||
*start = mesh->rangeStart;
|
||||
*count = mesh->rangeCount;
|
||||
}
|
||||
|
||||
int lovrMeshSetDrawRange(Mesh* mesh, int start, int count) {
|
||||
if (start < 0 || count < 0 || start + count > mesh->size) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mesh->rangeStart = start;
|
||||
mesh->rangeCount = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Texture* lovrMeshGetTexture(Mesh* mesh) {
|
||||
return mesh->texture;
|
||||
}
|
||||
|
||||
void lovrMeshSetTexture(Mesh* mesh, Texture* texture) {
|
||||
if (mesh->texture) {
|
||||
lovrRelease(&mesh->texture->ref);
|
||||
}
|
||||
|
||||
mesh->texture = texture;
|
||||
|
||||
if (mesh->texture) {
|
||||
lovrRetain(&mesh->texture->ref);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
#include "glfw.h"
|
||||
#include "util.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "math/math.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum {
|
||||
MESH_POINTS = GL_POINTS,
|
||||
MESH_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
|
||||
MESH_TRIANGLES = GL_TRIANGLES,
|
||||
MESH_TRIANGLE_FAN = GL_TRIANGLE_FAN
|
||||
} MeshDrawMode;
|
||||
|
||||
typedef enum {
|
||||
MESH_STATIC = GL_STATIC_DRAW,
|
||||
MESH_DYNAMIC = GL_DYNAMIC_DRAW,
|
||||
MESH_STREAM = GL_STREAM_DRAW
|
||||
} MeshUsage;
|
||||
|
||||
typedef enum {
|
||||
MESH_FLOAT = GL_FLOAT,
|
||||
MESH_BYTE = GL_BYTE,
|
||||
MESH_INT = GL_INT
|
||||
} MeshAttributeType;
|
||||
|
||||
typedef struct {
|
||||
const char* name;
|
||||
MeshAttributeType type;
|
||||
int count;
|
||||
} MeshAttribute;
|
||||
|
||||
typedef vec_t(MeshAttribute) MeshFormat;
|
||||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
int size;
|
||||
int stride;
|
||||
void* data;
|
||||
void* scratchVertex;
|
||||
MeshFormat format;
|
||||
MeshDrawMode drawMode;
|
||||
MeshUsage usage;
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
GLuint ibo;
|
||||
vec_uint_t map;
|
||||
char isRangeEnabled;
|
||||
int rangeStart;
|
||||
int rangeCount;
|
||||
Texture* texture;
|
||||
} Mesh;
|
||||
|
||||
Mesh* lovrMeshCreate(int size, MeshFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
void lovrMeshDestroy(const Ref* ref);
|
||||
void lovrMeshDraw(Mesh* buffer, mat4 transform);
|
||||
MeshFormat lovrMeshGetVertexFormat(Mesh* buffer);
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* buffer);
|
||||
int lovrMeshSetDrawMode(Mesh* buffer, MeshDrawMode drawMode);
|
||||
int lovrMeshGetVertexCount(Mesh* buffer);
|
||||
int lovrMeshGetVertexSize(Mesh* buffer);
|
||||
void* lovrMeshGetScratchVertex(Mesh* buffer);
|
||||
void lovrMeshGetVertex(Mesh* buffer, int index, void* dest);
|
||||
void lovrMeshSetVertex(Mesh* buffer, int index, void* vertex);
|
||||
void lovrMeshSetVertices(Mesh* buffer, void* vertices, int size);
|
||||
unsigned int* lovrMeshGetVertexMap(Mesh* buffer, int* count);
|
||||
void lovrMeshSetVertexMap(Mesh* buffer, unsigned int* map, int count);
|
||||
char lovrMeshIsRangeEnabled(Mesh* buffer);
|
||||
void lovrMeshSetRangeEnabled(Mesh* buffer, char isEnabled);
|
||||
void lovrMeshGetDrawRange(Mesh* buffer, int* start, int* count);
|
||||
int lovrMeshSetDrawRange(Mesh* buffer, int start, int count);
|
||||
Texture* lovrMeshGetTexture(Mesh* buffer);
|
||||
void lovrMeshSetTexture(Mesh* buffer, Texture* texture);
|
|
@ -71,28 +71,28 @@ Model* lovrModelCreate(ModelData* modelData) {
|
|||
|
||||
visitNode(modelData, modelData->root, NULL, &vertices, &indices);
|
||||
|
||||
BufferFormat format;
|
||||
MeshFormat format;
|
||||
vec_init(&format);
|
||||
|
||||
int components = 3;
|
||||
BufferAttribute position = { .name = "lovrPosition", .type = BUFFER_FLOAT, .count = 3 };
|
||||
MeshAttribute position = { .name = "lovrPosition", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, position);
|
||||
|
||||
if (modelData->hasNormals) {
|
||||
BufferAttribute normal = { .name = "lovrNormal", .type = BUFFER_FLOAT, .count = 3 };
|
||||
MeshAttribute normal = { .name = "lovrNormal", .type = MESH_FLOAT, .count = 3 };
|
||||
vec_push(&format, normal);
|
||||
components += 3;
|
||||
}
|
||||
|
||||
if (modelData->hasTexCoords) {
|
||||
BufferAttribute texCoord = { .name = "lovrTexCoord", .type = BUFFER_FLOAT, .count = 2 };
|
||||
MeshAttribute texCoord = { .name = "lovrTexCoord", .type = MESH_FLOAT, .count = 2 };
|
||||
vec_push(&format, texCoord);
|
||||
components += 2;
|
||||
}
|
||||
|
||||
model->buffer = lovrBufferCreate(vertices.length / components, &format, BUFFER_TRIANGLES, BUFFER_STATIC);
|
||||
lovrBufferSetVertices(model->buffer, (void*) vertices.data, vertices.length * sizeof(float));
|
||||
lovrBufferSetVertexMap(model->buffer, indices.data, indices.length);
|
||||
model->mesh = lovrMeshCreate(vertices.length / components, &format, MESH_TRIANGLES, MESH_STATIC);
|
||||
lovrMeshSetVertices(model->mesh, (void*) vertices.data, vertices.length * sizeof(float));
|
||||
lovrMeshSetVertexMap(model->mesh, indices.data, indices.length);
|
||||
|
||||
model->texture = NULL;
|
||||
|
||||
|
@ -108,12 +108,12 @@ void lovrModelDestroy(const Ref* ref) {
|
|||
lovrRelease(&model->texture->ref);
|
||||
}
|
||||
lovrModelDataDestroy(model->modelData);
|
||||
lovrRelease(&model->buffer->ref);
|
||||
lovrRelease(&model->mesh->ref);
|
||||
free(model);
|
||||
}
|
||||
|
||||
void lovrModelDraw(Model* model, mat4 transform) {
|
||||
lovrBufferDraw(model->buffer, transform);
|
||||
lovrMeshDraw(model->mesh, transform);
|
||||
}
|
||||
|
||||
Texture* lovrModelGetTexture(Model* model) {
|
||||
|
@ -126,7 +126,7 @@ void lovrModelSetTexture(Model* model, Texture* texture) {
|
|||
}
|
||||
|
||||
model->texture = texture;
|
||||
lovrBufferSetTexture(model->buffer, model->texture);
|
||||
lovrMeshSetTexture(model->mesh, model->texture);
|
||||
|
||||
if (model->texture) {
|
||||
lovrRetain(&model->texture->ref);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "loaders/model.h"
|
||||
#include "graphics/buffer.h"
|
||||
#include "graphics/mesh.h"
|
||||
#include "graphics/texture.h"
|
||||
#include "math/math.h"
|
||||
#include "glfw.h"
|
||||
|
@ -10,7 +10,7 @@
|
|||
typedef struct {
|
||||
Ref ref;
|
||||
ModelData* modelData;
|
||||
Buffer* buffer;
|
||||
Mesh* mesh;
|
||||
Texture* texture;
|
||||
} Model;
|
||||
|
||||
|
|
Loading…
Reference in New Issue