mirror of https://github.com/bjornbytes/lovr.git
Add VertexData object;
This commit is contained in:
parent
1d0ca6b763
commit
8ad882e7a4
|
@ -57,6 +57,7 @@ extern const luaL_Reg lovrSphereShape[];
|
|||
extern const luaL_Reg lovrTexture[];
|
||||
extern const luaL_Reg lovrTextureData[];
|
||||
extern const luaL_Reg lovrTransform[];
|
||||
extern const luaL_Reg lovrVertexData[];
|
||||
extern const luaL_Reg lovrWorld[];
|
||||
|
||||
// Enums
|
||||
|
@ -90,8 +91,12 @@ extern map_int_t VerticalAligns;
|
|||
extern map_int_t WrapModes;
|
||||
|
||||
// Shared helpers
|
||||
void luax_checkvertexformat(lua_State* L, int index, VertexFormat* format);
|
||||
int luax_pushvertexformat(lua_State* L, VertexFormat* format);
|
||||
int luax_pushvertex(lua_State* L, VertexData* vertex, VertexFormat* format);
|
||||
int luax_pushvertexattribute(lua_State* L, VertexPointer* vertex, Attribute attribute);
|
||||
int luax_pushvertex(lua_State* L, VertexPointer* vertex, VertexFormat* format);
|
||||
void luax_setvertexattribute(lua_State* L, int index, VertexPointer* vertex, Attribute attribute);
|
||||
void luax_setvertex(lua_State* L, int index, VertexPointer* vertex, VertexFormat* format);
|
||||
int luax_readtransform(lua_State* L, int index, mat4 transform, bool uniformScale);
|
||||
Blob* luax_readblob(lua_State* L, int index, const char* debug);
|
||||
int luax_pushshape(lua_State* L, Shape* shape);
|
||||
|
|
|
@ -12,6 +12,7 @@ int l_lovrDataInit(lua_State* L) {
|
|||
luax_registertype(L, "ModelData", lovrModelData);
|
||||
luax_registertype(L, "Rasterizer", lovrRasterizer);
|
||||
luax_registertype(L, "TextureData", lovrTextureData);
|
||||
luax_registertype(L, "VertexData", lovrVertexData);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -34,23 +35,6 @@ int l_lovrDataNewModelData(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrDataNewTextureData(lua_State* L) {
|
||||
TextureData* textureData = NULL;
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) {
|
||||
int width = luaL_checknumber(L, 1);
|
||||
int height = luaL_checknumber(L, 2);
|
||||
textureData = lovrTextureDataGetBlank(width, height, 0x0, FORMAT_RGBA);
|
||||
} else {
|
||||
Blob* blob = luax_readblob(L, 1, "Texture");
|
||||
textureData = lovrTextureDataFromBlob(blob);
|
||||
lovrRelease(&blob->ref);
|
||||
}
|
||||
|
||||
luax_pushtype(L, TextureData, textureData);
|
||||
lovrRelease(&textureData->ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrDataNewRasterizer(lua_State* L) {
|
||||
Blob* blob = NULL;
|
||||
float size;
|
||||
|
@ -73,10 +57,39 @@ int l_lovrDataNewRasterizer(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrDataNewTextureData(lua_State* L) {
|
||||
TextureData* textureData = NULL;
|
||||
if (lua_type(L, 1) == LUA_TNUMBER) {
|
||||
int width = luaL_checknumber(L, 1);
|
||||
int height = luaL_checknumber(L, 2);
|
||||
textureData = lovrTextureDataGetBlank(width, height, 0x0, FORMAT_RGBA);
|
||||
} else {
|
||||
Blob* blob = luax_readblob(L, 1, "Texture");
|
||||
textureData = lovrTextureDataFromBlob(blob);
|
||||
lovrRelease(&blob->ref);
|
||||
}
|
||||
|
||||
luax_pushtype(L, TextureData, textureData);
|
||||
lovrRelease(&textureData->ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrDataNewVertexData(lua_State* L) {
|
||||
uint32_t count = luaL_checkinteger(L, 1);
|
||||
VertexFormat format;
|
||||
vertexFormatInit(&format);
|
||||
luax_checkvertexformat(L, 2, &format);
|
||||
VertexData* vertexData = lovrVertexDataCreate(count, format.count > 0 ? &format : NULL, true);
|
||||
luax_pushtype(L, VertexData, vertexData);
|
||||
lovrRelease(&vertexData->ref);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrData[] = {
|
||||
{ "newAudioStream", l_lovrDataNewAudioStream },
|
||||
{ "newModelData", l_lovrDataNewModelData },
|
||||
{ "newRasterizer", l_lovrDataNewRasterizer },
|
||||
{ "newTextureData", l_lovrDataNewTextureData },
|
||||
{ "newVertexData", l_lovrDataNewVertexData },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
#include "data/model.h"
|
||||
#include "data/rasterizer.h"
|
||||
#include "data/texture.h"
|
||||
#include "data/vertexData.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
#include "lib/vertex.h"
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
|
@ -79,33 +79,6 @@ static void stencilCallback(void* userdata) {
|
|||
lua_call(L, 0, 0);
|
||||
}
|
||||
|
||||
static void luax_checkvertexformat(lua_State* L, int index, VertexFormat* format) {
|
||||
if (!lua_istable(L, index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int length = lua_objlen(L, index);
|
||||
lovrAssert(length <= 8, "Only 8 vertex attributes are supported");
|
||||
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);
|
||||
AttributeType* type = (AttributeType*) luax_checkenum(L, -2, &AttributeTypes, "mesh attribute type");
|
||||
int count = lua_tointeger(L, -1);
|
||||
vertexFormatAppend(format, name, *type, count);
|
||||
lua_pop(L, 4);
|
||||
}
|
||||
}
|
||||
|
||||
static TextureData* luax_checktexturedata(lua_State* L, int index) {
|
||||
void** type;
|
||||
if ((type = luax_totype(L, index, TextureData)) != NULL) {
|
||||
|
@ -978,7 +951,7 @@ int l_lovrGraphicsNewMesh(lua_State* L) {
|
|||
if (dataIndex) {
|
||||
int count = lua_objlen(L, dataIndex);
|
||||
format = *lovrMeshGetVertexFormat(mesh);
|
||||
VertexData vertices = lovrMeshMap(mesh, 0, count, false, true);
|
||||
VertexPointer vertices = lovrMeshMap(mesh, 0, count, false, true);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, dataIndex, i + 1);
|
||||
|
|
|
@ -1,46 +1,5 @@
|
|||
#include "api.h"
|
||||
|
||||
int luax_pushvertexformat(lua_State* L, VertexFormat* format) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
lua_newtable(L);
|
||||
|
||||
// Name
|
||||
lua_pushstring(L, attribute.name);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
// Type
|
||||
luax_pushenum(L, &AttributeTypes, 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 luax_pushvertex(lua_State* L, VertexData* vertex, VertexFormat* format) {
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
count += attribute.count;
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: lua_pushnumber(L, *vertex->floats++); break;
|
||||
case ATTR_BYTE: lua_pushnumber(L, *vertex->bytes++); break;
|
||||
case ATTR_INT: lua_pushnumber(L, *vertex->ints++); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int l_lovrMeshDrawInstanced(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int instances = luaL_checkinteger(L, 2);
|
||||
|
@ -56,12 +15,6 @@ int l_lovrMeshDraw(lua_State* L) {
|
|||
return l_lovrMeshDrawInstanced(L);
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexFormat(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
return luax_pushvertexformat(L, format);
|
||||
}
|
||||
|
||||
int l_lovrMeshGetDrawMode(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
luax_pushenum(L, &MeshDrawModes, lovrMeshGetDrawMode(mesh));
|
||||
|
@ -75,16 +28,22 @@ int l_lovrMeshSetDrawMode(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexFormat(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
return luax_pushvertexformat(L, format);
|
||||
}
|
||||
|
||||
int l_lovrMeshGetVertexCount(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
lua_pushnumber(L, lovrMeshGetVertexCount(mesh));
|
||||
lua_pushinteger(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;
|
||||
VertexData vertex = lovrMeshMap(mesh, index, 1, true, false);
|
||||
VertexPointer vertex = lovrMeshMap(mesh, index, 1, true, false);
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
return luax_pushvertex(L, &vertex, format);
|
||||
}
|
||||
|
@ -92,34 +51,10 @@ int l_lovrMeshGetVertex(lua_State* L) {
|
|||
int l_lovrMeshSetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
|
||||
if (index < 0 || index >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", index + 1);
|
||||
}
|
||||
|
||||
lovrAssert(index >= 0 && index < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex index: %d", index + 1);
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
VertexData vertex = lovrMeshMap(mesh, index, 1, false, true);
|
||||
|
||||
// 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->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: *vertex.floats++ = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case ATTR_BYTE: *vertex.bytes++ = luaL_optint(L, arg++, 255); break;
|
||||
case ATTR_INT: *vertex.ints++ = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VertexPointer vertex = lovrMeshMap(mesh, index, 1, false, true);
|
||||
luax_setvertex(L, 3, &vertex, format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -128,25 +63,12 @@ int l_lovrMeshGetVertexAttribute(lua_State* L) {
|
|||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format->count) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
lovrAssert(vertexIndex >= 0 && vertexIndex < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex: %d", vertexIndex + 1);
|
||||
lovrAssert(attributeIndex >= 0 && attributeIndex < format->count, "Invalid mesh attribute: %d", attributeIndex + 1);
|
||||
Attribute attribute = format->attributes[attributeIndex];
|
||||
VertexData vertex = lovrMeshMap(mesh, vertexIndex, 1, true, false);
|
||||
VertexPointer vertex = lovrMeshMap(mesh, vertexIndex, 1, true, false);
|
||||
vertex.bytes += attribute.offset;
|
||||
for (int i = 0; i < attribute.count; i++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: lua_pushnumber(L, *vertex.floats++); break;
|
||||
case ATTR_BYTE: lua_pushinteger(L, *vertex.bytes++); break;
|
||||
case ATTR_INT: lua_pushinteger(L, *vertex.ints++); break;
|
||||
}
|
||||
}
|
||||
|
||||
return attribute.count;
|
||||
return luax_pushvertexattribute(L, &vertex, attribute);
|
||||
}
|
||||
|
||||
int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
||||
|
@ -154,25 +76,12 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
|||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
|
||||
if (vertexIndex < 0 || vertexIndex >= lovrMeshGetVertexCount(mesh)) {
|
||||
return luaL_error(L, "Invalid mesh vertex index: %d", vertexIndex + 1);
|
||||
} else if (attributeIndex < 0 || attributeIndex >= format->count) {
|
||||
return luaL_error(L, "Invalid mesh attribute index: %d", attributeIndex + 1);
|
||||
}
|
||||
|
||||
int arg = 4;
|
||||
VertexData vertex = lovrMeshMap(mesh, vertexIndex, 1, false, true);
|
||||
lovrAssert(vertexIndex >= 0 && vertexIndex < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex: %d", vertexIndex + 1);
|
||||
lovrAssert(attributeIndex >= 0 && attributeIndex < format->count, "Invalid mesh attribute: %d", attributeIndex + 1);
|
||||
Attribute attribute = format->attributes[attributeIndex];
|
||||
VertexPointer vertex = lovrMeshMap(mesh, vertexIndex, 1, false, true);
|
||||
vertex.bytes += attribute.offset;
|
||||
for (int i = 0; i < attribute.count; i++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: *vertex.floats++ = luaL_optnumber(L, arg++, 0.f); break;
|
||||
case ATTR_BYTE: *vertex.bytes++ = luaL_optint(L, arg++, 255); break;
|
||||
case ATTR_INT: *vertex.ints++ = luaL_optint(L, arg++, 0); break;
|
||||
}
|
||||
}
|
||||
|
||||
luax_setvertexattribute(L, 4, &vertex, attribute);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -183,28 +92,13 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
int vertexCount = lua_objlen(L, 2);
|
||||
int start = luaL_optnumber(L, 3, 1) - 1;
|
||||
int maxVertices = lovrMeshGetVertexCount(mesh);
|
||||
|
||||
if (start + vertexCount > maxVertices) {
|
||||
return luaL_error(L, "Mesh can only hold %d vertices", maxVertices);
|
||||
}
|
||||
|
||||
VertexData vertices = lovrMeshMap(mesh, start, vertexCount, false, true);
|
||||
lovrAssert(start + vertexCount <= maxVertices, "Overflow in Mesh:setVertices: Mesh can only hold %d vertices", maxVertices);
|
||||
VertexPointer vertices = lovrMeshMap(mesh, start, vertexCount, false, true);
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
int component = 0;
|
||||
for (int j = 0; j < format->count; j++) {
|
||||
Attribute attribute = format->attributes[j];
|
||||
for (int k = 0; k < attribute.count; k++) {
|
||||
lua_rawgeti(L, -1, ++component);
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: *vertices.floats++ = luaL_optnumber(L, -1, 0.f); break;
|
||||
case ATTR_BYTE: *vertices.bytes++ = luaL_optint(L, -1, 255); break;
|
||||
case ATTR_INT: *vertices.ints++ = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
luax_setvertex(L, -1, &vertices, format);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
|
@ -214,7 +108,7 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
int l_lovrMeshGetVertexMap(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
size_t count;
|
||||
IndexData indices = lovrMeshGetVertexMap(mesh, &count);
|
||||
IndexPointer indices = lovrMeshGetVertexMap(mesh, &count);
|
||||
|
||||
if (count == 0) {
|
||||
lua_pushnil(L);
|
||||
|
@ -243,8 +137,8 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
int count = lua_objlen(L, 2);
|
||||
int vertexCount = lovrMeshGetVertexCount(mesh);
|
||||
int indexSize = mesh->indexSize;
|
||||
IndexData indices = lovrMeshGetVertexMap(mesh, NULL);
|
||||
indices.data = realloc(indices.data, indexSize * count);
|
||||
IndexPointer indices = lovrMeshGetVertexMap(mesh, NULL);
|
||||
indices.raw = realloc(indices.raw, indexSize * count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
|
@ -266,7 +160,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
lovrMeshSetVertexMap(mesh, indices.data, count);
|
||||
lovrMeshSetVertexMap(mesh, indices.raw, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,21 +21,13 @@ int l_lovrModelDataGetMaterialCount(lua_State* L) {
|
|||
|
||||
int l_lovrModelDataGetVertexCount(lua_State* L) {
|
||||
ModelData* modelData = luax_checktype(L, 1, ModelData);
|
||||
lua_pushinteger(L, modelData->vertexCount);
|
||||
lua_pushinteger(L, modelData->vertexData->count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrModelDataGetVertexFormat(lua_State* L) {
|
||||
ModelData* modelData = luax_checktype(L, 1, ModelData);
|
||||
return luax_pushvertexformat(L, &modelData->format);
|
||||
}
|
||||
|
||||
int l_lovrModelDataGetVertex(lua_State* L) {
|
||||
ModelData* modelData = luax_checktype(L, 1, ModelData);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
VertexData vertex = modelData->vertices;
|
||||
vertex.bytes += index * modelData->format.stride;
|
||||
return luax_pushvertex(L, &vertex, &modelData->format);
|
||||
return luax_pushvertexformat(L, &modelData->vertexData->format);
|
||||
}
|
||||
|
||||
int l_lovrModelDataGetTriangleCount(lua_State* L) {
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
#include "api.h"
|
||||
|
||||
void luax_checkvertexformat(lua_State* L, int index, VertexFormat* format) {
|
||||
if (!lua_istable(L, index)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int length = lua_objlen(L, index);
|
||||
lovrAssert(length <= 8, "Only 8 vertex attributes are supported");
|
||||
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);
|
||||
AttributeType* type = (AttributeType*) luax_checkenum(L, -2, &AttributeTypes, "mesh attribute type");
|
||||
int count = lua_tointeger(L, -1);
|
||||
vertexFormatAppend(format, name, *type, count);
|
||||
lua_pop(L, 4);
|
||||
}
|
||||
}
|
||||
|
||||
int luax_pushvertexformat(lua_State* L, VertexFormat* format) {
|
||||
lua_newtable(L);
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
lua_newtable(L);
|
||||
|
||||
// Name
|
||||
lua_pushstring(L, attribute.name);
|
||||
lua_rawseti(L, -2, 1);
|
||||
|
||||
// Type
|
||||
luax_pushenum(L, &AttributeTypes, 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 luax_pushvertexattribute(lua_State* L, VertexPointer* vertex, Attribute attribute) {
|
||||
for (int i = 0; i < attribute.count; i++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: lua_pushnumber(L, *vertex->floats++); break;
|
||||
case ATTR_BYTE: lua_pushnumber(L, *vertex->bytes++); break;
|
||||
case ATTR_INT: lua_pushnumber(L, *vertex->ints++); break;
|
||||
}
|
||||
}
|
||||
return attribute.count;
|
||||
}
|
||||
|
||||
int luax_pushvertex(lua_State* L, VertexPointer* vertex, VertexFormat* format) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
count += luax_pushvertexattribute(L, vertex, format->attributes[i]);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void luax_setvertexattribute(lua_State* L, int index, VertexPointer* vertex, Attribute attribute) {
|
||||
for (int i = 0; i < attribute.count; i++) {
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: *vertex->floats++ = luaL_optnumber(L, index++, 0.f); break;
|
||||
case ATTR_BYTE: *vertex->bytes++ = luaL_optint(L, index++, 255); break;
|
||||
case ATTR_INT: *vertex->ints++ = luaL_optint(L, index++, 0); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void luax_setvertex(lua_State* L, int index, VertexPointer* vertex, VertexFormat* format) {
|
||||
if (lua_istable(L, index)) {
|
||||
int component = 0;
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
for (int j = 0; j < attribute.count; j++) {
|
||||
lua_rawgeti(L, index, ++component);
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: *vertex->floats++ = luaL_optnumber(L, -1, 0.f); break;
|
||||
case ATTR_BYTE: *vertex->bytes++ = luaL_optint(L, -1, 255); break;
|
||||
case ATTR_INT: *vertex->ints++ = luaL_optint(L, -1, 0); break;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
luax_setvertexattribute(L, index, vertex, format->attributes[i]);
|
||||
index += format->attributes[i].count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
int l_lovrVertexDataGetPointer(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
lua_pushlightuserdata(L, vertexData->data.raw);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetSize(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
lua_pushinteger(L, vertexData->count * vertexData->format.stride);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetString(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
lua_pushlstring(L, vertexData->data.raw, vertexData->count * vertexData->format.stride);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetCount(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
uint32_t count = vertexData->count;
|
||||
lua_pushinteger(L, count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetFormat(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
return luax_pushvertexformat(L, &vertexData->format);
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetVertex(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
uint32_t index = (uint32_t) luaL_checkint(L, 2) - 1;
|
||||
VertexPointer vertex = { .raw = vertexData->data.bytes + index * vertexData->format.stride };
|
||||
return luax_pushvertex(L, &vertex, &vertexData->format);
|
||||
}
|
||||
|
||||
int l_lovrVertexDataSetVertex(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
uint32_t index = (uint32_t) luaL_checkint(L, 2) - 1;
|
||||
lovrAssert(index < vertexData->count, "Invalid vertex index: %d", index + 1);
|
||||
VertexFormat* format = &vertexData->format;
|
||||
VertexPointer* vertex = &vertexData->data;
|
||||
vertex->bytes += index * format->stride;
|
||||
luax_setvertex(L, 3, vertex, format);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataGetVertexAttribute(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
uint32_t vertexIndex = (uint32_t) luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
VertexFormat* format = &vertexData->format;
|
||||
lovrAssert(vertexIndex < vertexData->count, "Invalid vertex index: %d", vertexIndex + 1);
|
||||
lovrAssert(attributeIndex >= 0 && attributeIndex < format->count, "Invalid attribute index: %d", attributeIndex + 1);
|
||||
Attribute attribute = format->attributes[attributeIndex];
|
||||
VertexPointer vertex = vertexData->data;
|
||||
vertex.bytes += vertexIndex * format->stride + attribute.offset;
|
||||
return luax_pushvertexattribute(L, &vertex, attribute);
|
||||
}
|
||||
|
||||
int l_lovrVertexDataSetVertexAttribute(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
uint32_t vertexIndex = (uint32_t) luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
VertexFormat* format = &vertexData->format;
|
||||
lovrAssert(vertexIndex < vertexData->count, "Invalid vertex index: %d", vertexIndex + 1);
|
||||
lovrAssert(attributeIndex >= 0 && attributeIndex < format->count, "Invalid attribute index: %d", attributeIndex + 1);
|
||||
Attribute attribute = format->attributes[attributeIndex];
|
||||
VertexPointer vertex = vertexData->data;
|
||||
vertex.bytes += vertexIndex * format->stride + attribute.offset;
|
||||
luax_setvertexattribute(L, 4, &vertex, attribute);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrVertexDataSetVertices(lua_State* L) {
|
||||
VertexData* vertexData = luax_checktype(L, 1, VertexData);
|
||||
VertexFormat* format = &vertexData->format;
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
uint32_t vertexCount = lua_objlen(L, 2);
|
||||
int start = luaL_optnumber(L, 3, 1) - 1;
|
||||
lovrAssert(start + vertexCount <= vertexData->count, "VertexData can only hold %d vertices", vertexData->count);
|
||||
VertexPointer vertices = vertexData->data;
|
||||
vertices.bytes += start * format->stride;
|
||||
|
||||
for (uint32_t i = 0; i < vertexCount; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
luax_setvertex(L, -1, &vertices, format);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrVertexData[] = {
|
||||
{ "getPointer", l_lovrVertexDataGetPointer },
|
||||
{ "getSize", l_lovrVertexDataGetSize },
|
||||
{ "getString", l_lovrVertexDataGetString },
|
||||
{ "getCount", l_lovrVertexDataGetCount },
|
||||
{ "getFormat", l_lovrVertexDataGetFormat },
|
||||
{ "getVertex", l_lovrVertexDataGetVertex },
|
||||
{ "setVertex", l_lovrVertexDataSetVertex },
|
||||
{ "getVertexAttribute", l_lovrVertexDataGetVertexAttribute },
|
||||
{ "setVertexAttribute", l_lovrVertexDataSetVertexAttribute },
|
||||
{ "setVertices", l_lovrVertexDataSetVertices },
|
||||
{ NULL, NULL }
|
||||
};
|
|
@ -255,9 +255,9 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
}
|
||||
|
||||
modelData->nodeCount = 0;
|
||||
modelData->vertexCount = 0;
|
||||
modelData->indexCount = 0;
|
||||
|
||||
uint32_t vertexCount = 0;
|
||||
bool hasNormals = false;
|
||||
bool hasUVs = false;
|
||||
bool hasVertexColors = false;
|
||||
|
@ -265,7 +265,7 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
|
||||
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
||||
struct aiMesh* assimpMesh = scene->mMeshes[m];
|
||||
modelData->vertexCount += assimpMesh->mNumVertices;
|
||||
vertexCount += assimpMesh->mNumVertices;
|
||||
modelData->indexCount += assimpMesh->mNumFaces * 3;
|
||||
hasNormals |= assimpMesh->mNormals != NULL;
|
||||
hasUVs |= assimpMesh->mTextureCoords[0] != NULL;
|
||||
|
@ -273,26 +273,26 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
isSkinned |= assimpMesh->mNumBones > 0;
|
||||
}
|
||||
|
||||
vertexFormatInit(&modelData->format);
|
||||
vertexFormatAppend(&modelData->format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
VertexFormat format;
|
||||
vertexFormatInit(&format);
|
||||
vertexFormatAppend(&format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
|
||||
if (hasNormals) vertexFormatAppend(&modelData->format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
if (hasUVs) vertexFormatAppend(&modelData->format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
if (hasVertexColors) vertexFormatAppend(&modelData->format, "lovrVertexColor", ATTR_BYTE, 4);
|
||||
size_t boneByteOffset = modelData->format.stride;
|
||||
if (isSkinned) vertexFormatAppend(&modelData->format, "lovrBones", ATTR_INT, 4);
|
||||
if (isSkinned) vertexFormatAppend(&modelData->format, "lovrBoneWeights", ATTR_FLOAT, 4);
|
||||
if (hasNormals) vertexFormatAppend(&format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
if (hasUVs) vertexFormatAppend(&format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
if (hasVertexColors) vertexFormatAppend(&format, "lovrVertexColor", ATTR_BYTE, 4);
|
||||
size_t boneByteOffset = format.stride;
|
||||
if (isSkinned) vertexFormatAppend(&format, "lovrBones", ATTR_INT, 4);
|
||||
if (isSkinned) vertexFormatAppend(&format, "lovrBoneWeights", ATTR_FLOAT, 4);
|
||||
|
||||
// Allocate
|
||||
modelData->vertexData = lovrVertexDataCreate(vertexCount, &format, true);
|
||||
modelData->indexSize = vertexCount > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||
modelData->indices.raw = malloc(modelData->indexCount * modelData->indexSize);
|
||||
modelData->primitiveCount = scene->mNumMeshes;
|
||||
modelData->primitives = malloc(modelData->primitiveCount * sizeof(ModelPrimitive));
|
||||
modelData->indexSize = modelData->vertexCount > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||
modelData->vertices.data = malloc(modelData->format.stride * modelData->vertexCount);
|
||||
modelData->indices.data = malloc(modelData->indexCount * modelData->indexSize);
|
||||
memset(modelData->vertices.data, 0, modelData->format.stride * modelData->vertexCount);
|
||||
|
||||
// Load vertices
|
||||
IndexData indices = modelData->indices;
|
||||
IndexPointer indices = modelData->indices;
|
||||
uint32_t vertex = 0;
|
||||
uint32_t index = 0;
|
||||
for (unsigned int m = 0; m < scene->mNumMeshes; m++) {
|
||||
|
@ -323,8 +323,8 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
|
||||
// Vertices
|
||||
for (unsigned int v = 0; v < assimpMesh->mNumVertices; v++) {
|
||||
VertexData vertices = modelData->vertices;
|
||||
vertices.bytes += vertex * modelData->format.stride;
|
||||
VertexPointer vertices = modelData->vertexData->data;
|
||||
vertices.bytes += vertex * modelData->vertexData->format.stride;
|
||||
|
||||
*vertices.floats++ = assimpMesh->mVertices[v].x;
|
||||
*vertices.floats++ = assimpMesh->mVertices[v].y;
|
||||
|
@ -384,8 +384,8 @@ ModelData* lovrModelDataCreate(Blob* blob) {
|
|||
for (unsigned int w = 0; w < assimpBone->mNumWeights; w++) {
|
||||
uint32_t vertexIndex = baseVertex + assimpBone->mWeights[w].mVertexId;
|
||||
float weight = assimpBone->mWeights[w].mWeight;
|
||||
VertexData vertices = modelData->vertices;
|
||||
vertices.bytes += vertexIndex * modelData->format.stride;
|
||||
VertexPointer vertices = modelData->vertexData->data;
|
||||
vertices.bytes += vertexIndex * modelData->vertexData->format.stride;
|
||||
uint32_t* bones = (uint32_t*) (vertices.bytes + boneByteOffset);
|
||||
float* weights = (float*) (bones + MAX_BONES_PER_VERTEX);
|
||||
|
||||
|
@ -515,12 +515,13 @@ void lovrModelDataDestroy(const Ref* ref) {
|
|||
vec_deinit(&modelData->textures);
|
||||
map_deinit(&modelData->nodeMap);
|
||||
|
||||
lovrRelease(&modelData->vertexData->ref);
|
||||
|
||||
free(modelData->nodes);
|
||||
free(modelData->primitives);
|
||||
free(modelData->animations);
|
||||
free(modelData->materials);
|
||||
free(modelData->vertices.data);
|
||||
free(modelData->indices.data);
|
||||
free(modelData->indices.raw);
|
||||
free(modelData);
|
||||
}
|
||||
|
||||
|
@ -537,7 +538,7 @@ static void aabbIterator(ModelData* modelData, ModelNode* node, float aabb[6], m
|
|||
} else {
|
||||
index = modelData->indices.ints[primitive->drawStart + j];
|
||||
}
|
||||
vec3_init(vertex, (float*) (modelData->vertices.bytes + index * modelData->format.stride));
|
||||
vec3_init(vertex, (float*) (modelData->vertexData->data.bytes + index * modelData->vertexData->format.stride));
|
||||
mat4_transform(transform, vertex);
|
||||
aabb[0] = MIN(aabb[0], vertex[0]);
|
||||
aabb[1] = MAX(aabb[1], vertex[0]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#include "filesystem/blob.h"
|
||||
#include "data/vertexData.h"
|
||||
#include "util.h"
|
||||
#include "lib/vertex.h"
|
||||
#include "lib/map/map.h"
|
||||
#include "lib/vec/vec.h"
|
||||
|
||||
|
@ -61,22 +61,20 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
VertexData* vertexData;
|
||||
IndexPointer indices;
|
||||
int indexCount;
|
||||
size_t indexSize;
|
||||
ModelNode* nodes;
|
||||
map_int_t nodeMap;
|
||||
ModelPrimitive* primitives;
|
||||
Animation* animations;
|
||||
ModelMaterial* materials;
|
||||
vec_void_t textures;
|
||||
VertexFormat format;
|
||||
VertexData vertices;
|
||||
IndexData indices;
|
||||
int nodeCount;
|
||||
int primitiveCount;
|
||||
int animationCount;
|
||||
int materialCount;
|
||||
int vertexCount;
|
||||
int indexCount;
|
||||
size_t indexSize;
|
||||
} ModelData;
|
||||
|
||||
ModelData* lovrModelDataCreate(Blob* blob);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
#include "data/vertexData.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static size_t attributeTypeSizes[3] = { 4, 1, 4 };
|
||||
|
||||
void vertexFormatInit(VertexFormat* format) {
|
||||
memset(format, 0, sizeof(*format));
|
||||
}
|
||||
|
||||
void vertexFormatAppend(VertexFormat* format, const char* name, AttributeType type, int count) {
|
||||
size_t size = attributeTypeSizes[type];
|
||||
Attribute attribute = { name, type, count, size, format->stride };
|
||||
format->attributes[format->count++] = attribute;
|
||||
format->stride += size * count;
|
||||
}
|
||||
|
||||
VertexData* lovrVertexDataCreate(uint32_t count, VertexFormat* format, bool allocate) {
|
||||
VertexData* vertexData = lovrAlloc(sizeof(VertexData), lovrVertexDataDestroy);
|
||||
if (!vertexData) return NULL;
|
||||
|
||||
if (format) {
|
||||
vertexData->format = *format;
|
||||
} else {
|
||||
format = &vertexData->format;
|
||||
vertexFormatInit(&vertexData->format);
|
||||
vertexFormatAppend(&vertexData->format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&vertexData->format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&vertexData->format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
vertexFormatAppend(&vertexData->format, "lovrVertexColor", ATTR_BYTE, 4);
|
||||
}
|
||||
|
||||
vertexData->count = count;
|
||||
vertexData->data.raw = NULL;
|
||||
|
||||
if (allocate) {
|
||||
vertexData->data.raw = malloc(format->stride * count);
|
||||
memset(vertexData->data.raw, 0, format->stride * count);
|
||||
}
|
||||
|
||||
return vertexData;
|
||||
}
|
||||
|
||||
void lovrVertexDataDestroy(const Ref* ref) {
|
||||
VertexData* vertexData = containerof(ref, VertexData);
|
||||
if (vertexData->data.raw) {
|
||||
free(vertexData->data.raw);
|
||||
}
|
||||
free(vertexData);
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
#include "util.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -24,17 +26,27 @@ typedef struct {
|
|||
} VertexFormat;
|
||||
|
||||
typedef union {
|
||||
void* data;
|
||||
void* raw;
|
||||
float* floats;
|
||||
uint8_t* bytes;
|
||||
int* ints;
|
||||
} VertexData;
|
||||
} VertexPointer;
|
||||
|
||||
typedef union {
|
||||
void* data;
|
||||
void* raw;
|
||||
uint16_t* shorts;
|
||||
uint32_t* ints;
|
||||
} IndexData;
|
||||
} IndexPointer;
|
||||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
VertexFormat format;
|
||||
VertexPointer data;
|
||||
uint32_t count;
|
||||
} VertexData;
|
||||
|
||||
void vertexFormatInit(VertexFormat* format);
|
||||
void vertexFormatAppend(VertexFormat* format, const char* name, AttributeType type, int count);
|
||||
|
||||
VertexData* lovrVertexDataCreate(uint32_t count, VertexFormat* format, bool allocate);
|
||||
void lovrVertexDataDestroy(const Ref* ref);
|
|
@ -12,8 +12,9 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
|
|||
|
||||
lovrGraphicsBindVertexBuffer(mesh->vbo);
|
||||
|
||||
for (int i = 0; i < mesh->format.count; i++) {
|
||||
Attribute attribute = mesh->format.attributes[i];
|
||||
VertexFormat* format = &mesh->vertexData->format;
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
int location = lovrShaderGetAttributeId(shader, attribute.name);
|
||||
|
||||
if (location >= 0) {
|
||||
|
@ -28,9 +29,9 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
|
|||
}
|
||||
|
||||
if (attribute.type == ATTR_INT) {
|
||||
glVertexAttribIPointer(location, attribute.count, glType, mesh->format.stride, (void*) attribute.offset);
|
||||
glVertexAttribIPointer(location, attribute.count, glType, format->stride, (void*) attribute.offset);
|
||||
} else {
|
||||
glVertexAttribPointer(location, attribute.count, glType, GL_TRUE, mesh->format.stride, (void*) attribute.offset);
|
||||
glVertexAttribPointer(location, attribute.count, glType, GL_TRUE, format->stride, (void*) attribute.offset);
|
||||
}
|
||||
} else {
|
||||
glDisableVertexAttribArray(location);
|
||||
|
@ -42,23 +43,17 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
|
|||
mesh->attributesDirty = false;
|
||||
}
|
||||
|
||||
Mesh* lovrMeshCreate(size_t count, VertexFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat* format, MeshDrawMode drawMode, MeshUsage usage) {
|
||||
Mesh* mesh = lovrAlloc(sizeof(Mesh), lovrMeshDestroy);
|
||||
if (!mesh) return NULL;
|
||||
|
||||
if (format) {
|
||||
mesh->format = *format;
|
||||
} else {
|
||||
vertexFormatInit(&mesh->format);
|
||||
vertexFormatAppend(&mesh->format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&mesh->format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&mesh->format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
vertexFormatAppend(&mesh->format, "lovrVertexColor", ATTR_BYTE, 4);
|
||||
}
|
||||
#ifdef EMSCRIPTEN
|
||||
mesh->vertexData = lovrVertexDataCreate(count, format, false);
|
||||
#else
|
||||
mesh->vertexData = lovrVertexDataCreate(count, format, true);
|
||||
#endif
|
||||
|
||||
mesh->vertexCount = count;
|
||||
mesh->vertices.data = NULL;
|
||||
mesh->indices.data = NULL;
|
||||
mesh->indices.raw = NULL;
|
||||
mesh->indexCount = 0;
|
||||
mesh->indexSize = count > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||
mesh->enabledAttributes = ~0;
|
||||
|
@ -80,13 +75,9 @@ Mesh* lovrMeshCreate(size_t count, VertexFormat* format, MeshDrawMode drawMode,
|
|||
glGenBuffers(1, &mesh->vbo);
|
||||
glGenBuffers(1, &mesh->ibo);
|
||||
lovrGraphicsBindVertexBuffer(mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->vertexCount * mesh->format.stride, NULL, mesh->usage);
|
||||
glBufferData(GL_ARRAY_BUFFER, count * mesh->vertexData->format.stride, NULL, mesh->usage);
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
mesh->vertices.data = malloc(mesh->vertexCount * mesh->format.stride);
|
||||
#endif
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
@ -95,13 +86,11 @@ void lovrMeshDestroy(const Ref* ref) {
|
|||
if (mesh->material) {
|
||||
lovrRelease(&mesh->material->ref);
|
||||
}
|
||||
lovrRelease(&mesh->vertexData->ref);
|
||||
glDeleteBuffers(1, &mesh->vbo);
|
||||
glDeleteBuffers(1, &mesh->ibo);
|
||||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
free(mesh->indices.data);
|
||||
#ifdef EMSCRIPTEN
|
||||
free(mesh->vertices.data);
|
||||
#endif
|
||||
free(mesh->indices.raw);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
|
@ -135,7 +124,7 @@ void lovrMeshDraw(Mesh* mesh, mat4 transform, float* pose, int instances) {
|
|||
}
|
||||
|
||||
VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh) {
|
||||
return &mesh->format;
|
||||
return &mesh->vertexData->format;
|
||||
}
|
||||
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh) {
|
||||
|
@ -147,10 +136,10 @@ void lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode) {
|
|||
}
|
||||
|
||||
int lovrMeshGetVertexCount(Mesh* mesh) {
|
||||
return mesh->vertexCount;
|
||||
return mesh->vertexData->count;
|
||||
}
|
||||
|
||||
IndexData lovrMeshGetVertexMap(Mesh* mesh, size_t* count) {
|
||||
IndexPointer lovrMeshGetVertexMap(Mesh* mesh, size_t* count) {
|
||||
if (count) {
|
||||
*count = mesh->indexCount;
|
||||
}
|
||||
|
@ -165,19 +154,19 @@ void lovrMeshSetVertexMap(Mesh* mesh, void* data, size_t count) {
|
|||
}
|
||||
|
||||
if (mesh->indexCount < count) {
|
||||
mesh->indices.data = realloc(mesh->indices.data, count * mesh->indexSize);
|
||||
mesh->indices.raw = realloc(mesh->indices.raw, count * mesh->indexSize);
|
||||
}
|
||||
|
||||
mesh->indexCount = count;
|
||||
memcpy(mesh->indices.data, data, mesh->indexCount * mesh->indexSize);
|
||||
memcpy(mesh->indices.raw, data, mesh->indexCount * mesh->indexSize);
|
||||
lovrGraphicsBindVertexArray(mesh->vao);
|
||||
lovrGraphicsBindIndexBuffer(mesh->ibo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->indexCount * mesh->indexSize, mesh->indices.data, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->indexCount * mesh->indexSize, mesh->indices.raw, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) {
|
||||
for (int i = 0; i < mesh->format.count; i++) {
|
||||
if (!strcmp(mesh->format.attributes[i].name, name)) {
|
||||
for (int i = 0; i < mesh->vertexData->format.count; i++) {
|
||||
if (!strcmp(mesh->vertexData->format.attributes[i].name, name)) {
|
||||
return mesh->enabledAttributes & (1 << i);
|
||||
}
|
||||
}
|
||||
|
@ -186,8 +175,8 @@ bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) {
|
|||
}
|
||||
|
||||
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enable) {
|
||||
for (int i = 0; i < mesh->format.count; i++) {
|
||||
if (!strcmp(mesh->format.attributes[i].name, name)) {
|
||||
for (int i = 0; i < mesh->vertexData->format.count; i++) {
|
||||
if (!strcmp(mesh->vertexData->format.attributes[i].name, name)) {
|
||||
int mask = 1 << i;
|
||||
if (enable && !(mesh->enabledAttributes & mask)) {
|
||||
mesh->enabledAttributes |= mask;
|
||||
|
@ -209,7 +198,7 @@ void lovrMeshSetRangeEnabled(Mesh* mesh, char isEnabled) {
|
|||
|
||||
if (!isEnabled) {
|
||||
mesh->rangeStart = 0;
|
||||
mesh->rangeCount = mesh->vertexCount;
|
||||
mesh->rangeCount = mesh->vertexData->count;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +208,7 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count) {
|
|||
}
|
||||
|
||||
void lovrMeshSetDrawRange(Mesh* mesh, int start, int count) {
|
||||
size_t limit = mesh->indexCount > 0 ? mesh->indexCount : mesh->vertexCount;
|
||||
size_t limit = mesh->indexCount > 0 ? mesh->indexCount : mesh->vertexData->count;
|
||||
bool isValidRange = start >= 0 && count >= 0 && (size_t) start + count <= limit;
|
||||
lovrAssert(isValidRange, "Invalid mesh draw range [%d, %d]", start + 1, start + count + 1);
|
||||
mesh->rangeStart = start;
|
||||
|
@ -244,12 +233,13 @@ void lovrMeshSetMaterial(Mesh* mesh, Material* material) {
|
|||
}
|
||||
}
|
||||
|
||||
VertexData lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool write) {
|
||||
VertexPointer lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool write) {
|
||||
#ifdef EMSCRIPTEN
|
||||
mesh->isMapped = true;
|
||||
mesh->mapStart = start;
|
||||
mesh->mapCount = count;
|
||||
return (VertexData) { .data = mesh->vertices.bytes + start * mesh->format.stride };
|
||||
void* p = mesh->vertexData->data.bytes + start * mesh->vertexData->format.stride;
|
||||
return (VertexPointer) { .raw = p };
|
||||
#else
|
||||
if (mesh->isMapped) {
|
||||
lovrMeshUnmap(mesh);
|
||||
|
@ -258,12 +248,14 @@ VertexData lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool writ
|
|||
mesh->isMapped = true;
|
||||
mesh->mapStart = start;
|
||||
mesh->mapCount = count;
|
||||
size_t stride = mesh->vertexData->format.stride;
|
||||
GLbitfield access = 0;
|
||||
access |= read ? GL_MAP_READ_BIT : 0;
|
||||
access |= write ? GL_MAP_WRITE_BIT : 0;
|
||||
access |= (write && start == 0 && count == mesh->vertexCount) ? GL_MAP_INVALIDATE_BUFFER_BIT : 0;
|
||||
access |= (write && start == 0 && count == mesh->vertexData->count) ? GL_MAP_INVALIDATE_BUFFER_BIT : 0;
|
||||
lovrGraphicsBindVertexBuffer(mesh->vbo);
|
||||
return (VertexData) { .data = glMapBufferRange(GL_ARRAY_BUFFER, start * mesh->format.stride, count * mesh->format.stride, access) };
|
||||
mesh->vertexData->data.raw = glMapBufferRange(GL_ARRAY_BUFFER, start * stride, count * stride, access);
|
||||
return mesh->vertexData->data;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -276,9 +268,10 @@ void lovrMeshUnmap(Mesh* mesh) {
|
|||
lovrGraphicsBindVertexBuffer(mesh->vbo);
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
size_t start = mesh->mapStart * mesh->format.stride;
|
||||
size_t count = mesh->mapCount * mesh->format.stride;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, start, count, mesh->vertices.bytes + start);
|
||||
size_t stride = mesh->vertexData->format.stride;
|
||||
size_t start = mesh->mapStart * stride;
|
||||
size_t count = mesh->mapCount * stride;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, start, count, mesh->vertexData->data.bytes + start);
|
||||
#else
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
#include "util.h"
|
||||
#include "graphics/shader.h"
|
||||
#include "graphics/material.h"
|
||||
#include "data/vertexData.h"
|
||||
#include "math/math.h"
|
||||
#include "lib/glfw.h"
|
||||
#include "lib/vertex.h"
|
||||
#include "util.h"
|
||||
|
||||
#pragma once
|
||||
|
||||
|
@ -24,10 +24,8 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
Ref ref;
|
||||
size_t vertexCount;
|
||||
VertexFormat format;
|
||||
VertexData vertices;
|
||||
IndexData indices;
|
||||
VertexData* vertexData;
|
||||
IndexPointer indices;
|
||||
size_t indexCount;
|
||||
size_t indexSize;
|
||||
int enabledAttributes;
|
||||
|
@ -47,14 +45,14 @@ typedef struct {
|
|||
Shader* lastShader;
|
||||
} Mesh;
|
||||
|
||||
Mesh* lovrMeshCreate(size_t count, VertexFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
void lovrMeshDestroy(const Ref* ref);
|
||||
void lovrMeshDraw(Mesh* mesh, mat4 transform, float* pose, int instances);
|
||||
VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh);
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);
|
||||
void lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode);
|
||||
int lovrMeshGetVertexCount(Mesh* mesh);
|
||||
IndexData lovrMeshGetVertexMap(Mesh* mesh, size_t* count);
|
||||
IndexPointer lovrMeshGetVertexMap(Mesh* mesh, size_t* count);
|
||||
void lovrMeshSetVertexMap(Mesh* mesh, void* data, size_t count);
|
||||
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name);
|
||||
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enabled);
|
||||
|
@ -64,5 +62,5 @@ void lovrMeshGetDrawRange(Mesh* mesh, int* start, int* count);
|
|||
void lovrMeshSetDrawRange(Mesh* mesh, int start, int count);
|
||||
Material* lovrMeshGetMaterial(Mesh* mesh);
|
||||
void lovrMeshSetMaterial(Mesh* mesh, Material* material);
|
||||
VertexData lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool write);
|
||||
VertexPointer lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool write);
|
||||
void lovrMeshUnmap(Mesh* mesh);
|
||||
|
|
|
@ -59,11 +59,11 @@ Model* lovrModelCreate(ModelData* modelData) {
|
|||
model->animator = NULL;
|
||||
model->material = NULL;
|
||||
|
||||
model->mesh = lovrMeshCreate(modelData->vertexCount, &modelData->format, MESH_TRIANGLES, MESH_STATIC);
|
||||
VertexData vertices = lovrMeshMap(model->mesh, 0, modelData->vertexCount, false, true);
|
||||
memcpy(vertices.data, modelData->vertices.data, modelData->vertexCount * modelData->format.stride);
|
||||
model->mesh = lovrMeshCreate(modelData->vertexData->count, &modelData->vertexData->format, MESH_TRIANGLES, MESH_STATIC);
|
||||
VertexPointer vertices = lovrMeshMap(model->mesh, 0, modelData->vertexData->count, false, true);
|
||||
memcpy(vertices.raw, modelData->vertexData->data.raw, modelData->vertexData->count * modelData->vertexData->format.stride);
|
||||
lovrMeshUnmap(model->mesh);
|
||||
lovrMeshSetVertexMap(model->mesh, modelData->indices.data, modelData->indexCount);
|
||||
lovrMeshSetVertexMap(model->mesh, modelData->indices.raw, modelData->indexCount);
|
||||
lovrMeshSetRangeEnabled(model->mesh, true);
|
||||
|
||||
if (modelData->textures.length > 0) {
|
||||
|
|
|
@ -639,20 +639,15 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
|
|||
ModelData* modelData = malloc(sizeof(ModelData));
|
||||
if (!modelData) return NULL;
|
||||
|
||||
vertexFormatInit(&modelData->format);
|
||||
vertexFormatAppend(&modelData->format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&modelData->format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&modelData->format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
VertexFormat format;
|
||||
vertexFormatInit(&format);
|
||||
vertexFormatAppend(&format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
|
||||
modelData->vertexCount = vrModel->unVertexCount;
|
||||
modelData->vertices.data = malloc(modelData->vertexCount * modelData->format.stride);
|
||||
modelData->vertexData = lovrVertexDataCreate(vrModel->unVertexCount, &format, true);
|
||||
|
||||
modelData->indexCount = vrModel->unTriangleCount * 3;
|
||||
modelData->indexSize = sizeof(uint16_t);
|
||||
modelData->indices.data = malloc(modelData->indexCount * modelData->indexSize);
|
||||
memcpy(modelData->indices.data, vrModel->rIndexData, modelData->indexCount * modelData->indexSize);
|
||||
|
||||
float* vertices = modelData->vertices.floats;
|
||||
float* vertices = modelData->vertexData->data.floats;
|
||||
int vertex = 0;
|
||||
for (size_t i = 0; i < vrModel->unVertexCount; i++) {
|
||||
float* position = vrModel->rVertexData[i].vPosition.v;
|
||||
|
@ -671,6 +666,11 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
|
|||
vertices[vertex++] = texCoords[1];
|
||||
}
|
||||
|
||||
modelData->indexCount = vrModel->unTriangleCount * 3;
|
||||
modelData->indexSize = sizeof(uint16_t);
|
||||
modelData->indices.raw = malloc(modelData->indexCount * modelData->indexSize);
|
||||
memcpy(modelData->indices.raw, vrModel->rIndexData, modelData->indexCount * modelData->indexSize);
|
||||
|
||||
modelData->nodeCount = 1;
|
||||
modelData->primitiveCount = 1;
|
||||
modelData->animationCount = 0;
|
||||
|
@ -681,7 +681,7 @@ static ModelData* openvrControllerNewModelData(Controller* controller) {
|
|||
modelData->animations = NULL;
|
||||
modelData->materials = malloc(1 * sizeof(ModelMaterial));
|
||||
|
||||
// Geometry
|
||||
// Nodes
|
||||
map_init(&modelData->nodeMap);
|
||||
ModelNode* root = &modelData->nodes[0];
|
||||
root->parent = -1;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
#include "lib/vertex.h"
|
||||
#include <string.h>
|
||||
|
||||
static size_t attributeTypeSizes[3] = { 4, 1, 4 };
|
||||
|
||||
void vertexFormatInit(VertexFormat* format) {
|
||||
memset(format, 0, sizeof(*format));
|
||||
}
|
||||
|
||||
void vertexFormatAppend(VertexFormat* format, const char* name, AttributeType type, int count) {
|
||||
size_t size = attributeTypeSizes[type];
|
||||
Attribute attribute = { name, type, count, size, format->stride };
|
||||
format->attributes[format->count++] = attribute;
|
||||
format->stride += size * count;
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
#include "lib/map/map.h"
|
||||
#include "lib/vertex.h"
|
||||
#include "util.h"
|
||||
|
||||
#pragma once
|
||||
|
|
Loading…
Reference in New Issue