mirror of https://github.com/bjornbytes/lovr.git
Mesh uses Buffer;
This commit is contained in:
parent
9a0f7c919a
commit
e2886d3bb5
|
@ -203,24 +203,24 @@ static uint32_t luax_readvertices(lua_State* L, int index) {
|
|||
|
||||
if (lua_type(L, -1) == LUA_TNUMBER) {
|
||||
lua_pop(L, 1);
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(count / 3);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(count / 3);
|
||||
for (size_t i = 1; i <= count; i += 3) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
lua_rawgeti(L, index, i + j);
|
||||
vertices.floats[j] = lua_tonumber(L, -1);
|
||||
vertices[j] = lua_tonumber(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
vertices.floats += 8;
|
||||
vertices += 8;
|
||||
}
|
||||
return count / 3;
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(count);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(count);
|
||||
for (size_t i = 1; i <= count; i++) {
|
||||
lua_rawgeti(L, index, i);
|
||||
vec3_init(vertices.floats, luax_checkmathtype(L, -1, MATH_VEC3, NULL));
|
||||
vec3_init(vertices, luax_checkmathtype(L, -1, MATH_VEC3, NULL));
|
||||
lua_pop(L, 1);
|
||||
vertices.floats += 8;
|
||||
vertices += 8;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -229,12 +229,12 @@ static uint32_t luax_readvertices(lua_State* L, int index) {
|
|||
case LUA_TNUMBER: {
|
||||
int top = lua_gettop(L);
|
||||
uint32_t count = (top - index + 1) / 3;
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(count);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(count);
|
||||
for (int i = index; i <= top; i += 3) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
vertices.floats[j] = lua_tonumber(L, i + j);
|
||||
vertices[j] = lua_tonumber(L, i + j);
|
||||
}
|
||||
vertices.floats += 8;
|
||||
vertices += 8;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -242,10 +242,10 @@ static uint32_t luax_readvertices(lua_State* L, int index) {
|
|||
default: {
|
||||
int top = lua_gettop(L);
|
||||
uint32_t count = top - index + 1;
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(count);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(count);
|
||||
for (int i = index; i <= top; i++) {
|
||||
vec3_init(vertices.floats, luax_checkmathtype(L, i, MATH_VEC3, NULL));
|
||||
vertices.floats += 8;
|
||||
vec3_init(vertices, luax_checkmathtype(L, i, MATH_VEC3, NULL));
|
||||
vertices += 8;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
@ -1137,14 +1137,17 @@ static int l_lovrGraphicsNewMesh(lua_State* L) {
|
|||
|
||||
MeshDrawMode drawMode = luaL_checkoption(L, drawModeIndex, "fan", MeshDrawModes);
|
||||
BufferUsage usage = luaL_checkoption(L, drawModeIndex + 1, "dynamic", BufferUsages);
|
||||
Mesh* mesh = lovrMeshCreate(count, format, drawMode, usage);
|
||||
bool readable = lua_toboolean(L, drawModeIndex + 2);
|
||||
Mesh* mesh = lovrMeshCreate(count, format, drawMode, usage, readable);
|
||||
|
||||
if (dataIndex) {
|
||||
VertexPointer vertices = lovrMeshMapVertices(mesh, 0, lua_objlen(L, dataIndex), false, true);
|
||||
VertexPointer vertices = { .raw = lovrMeshMapVertices(mesh, 0) };
|
||||
luax_loadvertices(L, dataIndex, lovrMeshGetVertexFormat(mesh), vertices);
|
||||
lovrMeshFlushVertices(mesh, 0, count * format.stride);
|
||||
} else if (vertexData) {
|
||||
VertexPointer vertices = lovrMeshMapVertices(mesh, 0, count, false, true);
|
||||
memcpy(vertices.raw, vertexData->blob.data, vertexData->count * vertexData->format.stride);
|
||||
void* vertices = lovrMeshMapVertices(mesh, 0);
|
||||
memcpy(vertices, vertexData->blob.data, vertexData->count * vertexData->format.stride);
|
||||
lovrMeshFlushVertices(mesh, 0, count * format.stride);
|
||||
}
|
||||
|
||||
luax_pushobject(L, mesh);
|
||||
|
|
|
@ -102,8 +102,9 @@ int l_lovrMeshGetVertexCount(lua_State* L) {
|
|||
int l_lovrMeshGetVertex(lua_State* L) {
|
||||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
int index = luaL_checkint(L, 2) - 1;
|
||||
VertexPointer vertex = lovrMeshMapVertices(mesh, index, 1, true, false);
|
||||
lovrAssert(lovrMeshIsReadable(mesh), "Mesh:getVertex can only be used if the Mesh was created with the readable flag");
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
VertexPointer vertex = { .raw = lovrMeshMapVertices(mesh, index * format->stride) };
|
||||
return luax_pushvertex(L, &vertex, format);
|
||||
}
|
||||
|
||||
|
@ -112,8 +113,9 @@ int l_lovrMeshSetVertex(lua_State* L) {
|
|||
int index = luaL_checkint(L, 2) - 1;
|
||||
lovrAssert(index >= 0 && index < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex index: %d", index + 1);
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
VertexPointer vertex = lovrMeshMapVertices(mesh, index, 1, false, true);
|
||||
VertexPointer vertex = { .raw = lovrMeshMapVertices(mesh, index * format->stride) };
|
||||
luax_setvertex(L, 3, &vertex, format);
|
||||
lovrMeshFlushVertices(mesh, index * format->stride, format->stride);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -122,11 +124,11 @@ int l_lovrMeshGetVertexAttribute(lua_State* L) {
|
|||
int vertexIndex = luaL_checkint(L, 2) - 1;
|
||||
int attributeIndex = luaL_checkint(L, 3) - 1;
|
||||
VertexFormat* format = lovrMeshGetVertexFormat(mesh);
|
||||
lovrAssert(lovrMeshIsReadable(mesh), "Mesh:getVertex can only be used if the Mesh was created with the readable flag");
|
||||
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 = lovrMeshMapVertices(mesh, vertexIndex, 1, true, false);
|
||||
vertex.bytes += attribute.offset;
|
||||
VertexPointer vertex = { .raw = lovrMeshMapVertices(mesh, vertexIndex * format->stride + attribute.offset) };
|
||||
return luax_pushvertexattribute(L, &vertex, attribute);
|
||||
}
|
||||
|
||||
|
@ -138,9 +140,9 @@ int l_lovrMeshSetVertexAttribute(lua_State* L) {
|
|||
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 = lovrMeshMapVertices(mesh, vertexIndex, 1, false, true);
|
||||
vertex.bytes += attribute.offset;
|
||||
VertexPointer vertex = { .raw = lovrMeshMapVertices(mesh, vertexIndex * format->stride + attribute.offset) };
|
||||
luax_setvertexattribute(L, 4, &vertex, attribute);
|
||||
lovrMeshFlushVertices(mesh, vertexIndex * format->stride + attribute.offset, attribute.size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -165,7 +167,7 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
lovrAssert(start + count <= capacity, "Overflow in Mesh:setVertices: Mesh can only hold %d vertices", capacity);
|
||||
lovrAssert(count <= sourceSize, "Cannot set %d vertices on Mesh: source only has %d vertices", count, sourceSize);
|
||||
|
||||
VertexPointer vertices = lovrMeshMapVertices(mesh, start, count, false, true);
|
||||
VertexPointer vertices = { .raw = lovrMeshMapVertices(mesh, start * format->stride) };
|
||||
|
||||
if (vertexData) {
|
||||
memcpy(vertices.raw, vertexData->blob.data, count * format->stride);
|
||||
|
@ -178,6 +180,8 @@ int l_lovrMeshSetVertices(lua_State* L) {
|
|||
}
|
||||
}
|
||||
|
||||
lovrMeshFlushVertices(mesh, start * format->stride, count * format->stride);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -185,7 +189,7 @@ int l_lovrMeshGetVertexMap(lua_State* L) {
|
|||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
uint32_t count;
|
||||
size_t size;
|
||||
IndexPointer indices = lovrMeshReadIndices(mesh, &count, &size);
|
||||
IndexPointer indices = { .raw = lovrMeshReadIndices(mesh, &count, &size) };
|
||||
|
||||
if (count == 0 || !indices.raw) {
|
||||
lua_pushnil(L);
|
||||
|
@ -217,7 +221,7 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
Mesh* mesh = luax_checktype(L, 1, Mesh);
|
||||
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
lovrMeshWriteIndices(mesh, 0, 0);
|
||||
lovrMeshMapIndices(mesh, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -226,14 +230,14 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
size_t size = luaL_optinteger(L, 3, 4);
|
||||
lovrAssert(size == 2 || size == 4, "Size of Mesh indices should be 2 bytes or 4 bytes");
|
||||
uint32_t count = blob->size / size;
|
||||
IndexPointer indices = lovrMeshWriteIndices(mesh, count, size);
|
||||
memcpy(indices.raw, blob->data, blob->size);
|
||||
void* indices = lovrMeshMapIndices(mesh, count, size);
|
||||
memcpy(indices, blob->data, blob->size);
|
||||
} else {
|
||||
luaL_checktype(L, 2, LUA_TTABLE);
|
||||
uint32_t count = lua_objlen(L, 2);
|
||||
uint32_t vertexCount = lovrMeshGetVertexCount(mesh);
|
||||
size_t size = vertexCount > USHRT_MAX ? sizeof(uint32_t) : sizeof(uint16_t);
|
||||
IndexPointer indices = lovrMeshWriteIndices(mesh, count, size);
|
||||
IndexPointer indices = { .raw = lovrMeshMapIndices(mesh, count, size) };
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
lua_rawgeti(L, 2, i + 1);
|
||||
|
@ -256,6 +260,8 @@ int l_lovrMeshSetVertexMap(lua_State* L) {
|
|||
}
|
||||
}
|
||||
|
||||
lovrMeshFlushIndices(mesh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ typedef enum {
|
|||
|
||||
typedef struct Buffer Buffer;
|
||||
|
||||
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage);
|
||||
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage, bool readable);
|
||||
void lovrBufferDestroy(void* ref);
|
||||
size_t lovrBufferGetSize(Buffer* buffer);
|
||||
BufferUsage lovrBufferGetUsage(Buffer* buffer);
|
||||
|
|
|
@ -75,7 +75,7 @@ void lovrGraphicsSetWindow(WindowFlags* flags) {
|
|||
vertexFormatAppend(&format, "lovrPosition", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&format, "lovrNormal", ATTR_FLOAT, 3);
|
||||
vertexFormatAppend(&format, "lovrTexCoord", ATTR_FLOAT, 2);
|
||||
state.defaultMesh = lovrMeshCreate(64, format, MESH_TRIANGLES, USAGE_STREAM);
|
||||
state.defaultMesh = lovrMeshCreate(65536, format, MESH_TRIANGLES, USAGE_STREAM, false);
|
||||
lovrGraphicsReset();
|
||||
state.initialized = true;
|
||||
}
|
||||
|
@ -331,9 +331,9 @@ void lovrGraphicsSetProjection(mat4 projection) {
|
|||
|
||||
// Rendering
|
||||
|
||||
VertexPointer lovrGraphicsGetVertexPointer(uint32_t count) {
|
||||
lovrMeshResize(state.defaultMesh, count);
|
||||
return lovrMeshMapVertices(state.defaultMesh, 0, count, false, true);
|
||||
float* lovrGraphicsGetVertexPointer(uint32_t count) {
|
||||
lovrAssert(count <= 65536, "Hey now! Up to 65536 vertices are allowed per-primitive...");
|
||||
return lovrMeshMapVertices(state.defaultMesh, 0);
|
||||
}
|
||||
|
||||
void lovrGraphicsClear(Color* color, float* depth, int* stencil) {
|
||||
|
@ -351,19 +351,29 @@ void lovrGraphicsDiscard(bool color, bool depth, bool stencil) {
|
|||
void lovrGraphicsDraw(DrawCommand* draw) {
|
||||
Mesh* mesh = draw->mesh;
|
||||
if (!mesh) {
|
||||
int drawCount = draw->range.count ? draw->range.count : (draw->index.count ? draw->index.count : draw->vertex.count);
|
||||
mesh = state.defaultMesh;
|
||||
lovrMeshSetDrawMode(mesh, draw->mode);
|
||||
lovrMeshSetDrawRange(mesh, draw->range.start, drawCount);
|
||||
if (draw->vertex.count) {
|
||||
VertexPointer vertexPointer = lovrGraphicsGetVertexPointer(draw->vertex.count);
|
||||
memcpy(vertexPointer.raw, draw->vertex.data, draw->vertex.count * 8 * sizeof(float));
|
||||
|
||||
if (draw->index.count) {
|
||||
IndexPointer indexPointer = lovrMeshWriteIndices(mesh, draw->index.count, sizeof(uint16_t));
|
||||
memcpy(indexPointer.shorts, draw->index.data, draw->index.count * sizeof(uint16_t));
|
||||
} else {
|
||||
lovrMeshWriteIndices(mesh, 0, 0);
|
||||
if (draw->index.data) {
|
||||
void* indices = lovrMeshMapIndices(mesh, draw->index.count, sizeof(uint16_t));
|
||||
memcpy(indices, draw->index.data, draw->index.count * sizeof(uint16_t));
|
||||
}
|
||||
lovrMeshSetDrawRange(mesh, 0, draw->index.count);
|
||||
lovrMeshFlushIndices(mesh);
|
||||
} else {
|
||||
lovrMeshSetDrawRange(mesh, 0, draw->vertex.count);
|
||||
lovrMeshMapIndices(mesh, 0, 0);
|
||||
}
|
||||
|
||||
if (draw->vertex.count) {
|
||||
if (draw->vertex.data) {
|
||||
void* vertices = lovrGraphicsGetVertexPointer(draw->vertex.count);
|
||||
memcpy(vertices, draw->vertex.data, draw->vertex.count * 8 * sizeof(float));
|
||||
}
|
||||
lovrMeshFlushVertices(state.defaultMesh, 0, draw->vertex.count * 8 * sizeof(float));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -478,14 +488,14 @@ void lovrGraphicsDraw(DrawCommand* draw) {
|
|||
void lovrGraphicsPoints(uint32_t count) {
|
||||
lovrGraphicsDraw(&(DrawCommand) {
|
||||
.mode = MESH_POINTS,
|
||||
.range = { 0, count }
|
||||
.vertex.count = count
|
||||
});
|
||||
}
|
||||
|
||||
void lovrGraphicsLine(uint32_t count) {
|
||||
lovrGraphicsDraw(&(DrawCommand) {
|
||||
.mode = MESH_LINE_STRIP,
|
||||
.range = { 0, count }
|
||||
.vertex.count = count
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -633,12 +643,12 @@ void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 tr
|
|||
|
||||
bool hasCenterPoint = arcMode == ARC_MODE_PIE && fabsf(theta1 - theta2) < 2 * M_PI;
|
||||
uint32_t count = segments + 1 + hasCenterPoint;
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(count);
|
||||
lovrMeshWriteIndices(state.defaultMesh, 0, 0);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(count);
|
||||
lovrMeshMapIndices(state.defaultMesh, 0, 0);
|
||||
|
||||
if (hasCenterPoint) {
|
||||
memcpy(vertices.floats, ((float[]) { 0, 0, 0, 0, 0, 1, .5, .5 }), 8 * sizeof(float));
|
||||
vertices.floats += 8;
|
||||
memcpy(vertices, ((float[]) { 0, 0, 0, 0, 0, 1, .5, .5 }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
|
||||
float theta = theta1;
|
||||
|
@ -647,8 +657,8 @@ void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 tr
|
|||
for (int i = 0; i <= segments; i++) {
|
||||
float x = cos(theta) * .5;
|
||||
float y = sin(theta) * .5;
|
||||
memcpy(vertices.floats, ((float[]) { x, y, 0, 0, 0, 1, x + .5, 1 - (y + .5) }), 8 * sizeof(float));
|
||||
vertices.floats += 8;
|
||||
memcpy(vertices, ((float[]) { x, y, 0, 0, 0, 1, x + .5, 1 - (y + .5) }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
theta += angleShift;
|
||||
}
|
||||
|
||||
|
@ -656,7 +666,7 @@ void lovrGraphicsArc(DrawMode mode, ArcMode arcMode, Material* material, mat4 tr
|
|||
.transform = transform,
|
||||
.material = material,
|
||||
.mode = mode == DRAW_MODE_LINE ? (arcMode == ARC_MODE_OPEN ? MESH_LINE_STRIP : MESH_LINE_LOOP) : MESH_TRIANGLE_FAN,
|
||||
.range = { 0, count }
|
||||
.vertex.count = count
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -673,9 +683,9 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
|
|||
uint32_t vertexCount = ((capped && r1) * (segments + 2) + (capped && r2) * (segments + 2) + 2 * (segments + 1));
|
||||
uint32_t indexCount = 3 * segments * ((capped && r1) + (capped && r2) + 2);
|
||||
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer(vertexCount);
|
||||
IndexPointer indices = lovrMeshWriteIndices(state.defaultMesh, indexCount, sizeof(uint32_t));
|
||||
float* baseVertex = vertices.floats;
|
||||
float* vertices = lovrGraphicsGetVertexPointer(vertexCount);
|
||||
uint16_t* indices = lovrMeshMapIndices(state.defaultMesh, indexCount, sizeof(uint32_t));
|
||||
float* baseVertex = vertices;
|
||||
|
||||
vec3_init(p, n);
|
||||
|
||||
|
@ -694,18 +704,18 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
|
|||
vec3_normalize(axis);
|
||||
|
||||
#define PUSH_CYLINDER_VERTEX(x, y, z, nx, ny, nz) \
|
||||
*vertices.floats++ = x; \
|
||||
*vertices.floats++ = y; \
|
||||
*vertices.floats++ = z; \
|
||||
*vertices.floats++ = nx; \
|
||||
*vertices.floats++ = ny; \
|
||||
*vertices.floats++ = nz; \
|
||||
*vertices.floats++ = 0; \
|
||||
*vertices.floats++ = 0;
|
||||
*vertices++ = x; \
|
||||
*vertices++ = y; \
|
||||
*vertices++ = z; \
|
||||
*vertices++ = nx; \
|
||||
*vertices++ = ny; \
|
||||
*vertices++ = nz; \
|
||||
*vertices++ = 0; \
|
||||
*vertices++ = 0;
|
||||
#define PUSH_CYLINDER_TRIANGLE(i1, i2, i3) \
|
||||
*indices.ints++ = i1; \
|
||||
*indices.ints++ = i2; \
|
||||
*indices.ints++ = i3; \
|
||||
*indices++ = i1; \
|
||||
*indices++ = i2; \
|
||||
*indices++ = i3; \
|
||||
|
||||
// Ring
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
|
@ -757,13 +767,16 @@ void lovrGraphicsCylinder(Material* material, float x1, float y1, float z1, floa
|
|||
lovrGraphicsDraw(&(DrawCommand) {
|
||||
.material = material,
|
||||
.mode = MESH_TRIANGLES,
|
||||
.range = { 0, indexCount }
|
||||
.vertex.count = vertexCount,
|
||||
.index.count = indexCount
|
||||
});
|
||||
}
|
||||
|
||||
void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
|
||||
VertexPointer vertices = lovrGraphicsGetVertexPointer((segments + 1) * (segments + 1));
|
||||
IndexPointer indices = lovrMeshWriteIndices(state.defaultMesh, segments * segments * 6, sizeof(uint32_t));
|
||||
uint32_t vertexCount = (segments + 1) * (segments + 1);
|
||||
uint32_t indexCount = segments * segments * 6;
|
||||
float* vertices = lovrGraphicsGetVertexPointer(vertexCount);
|
||||
uint16_t* indices = lovrMeshMapIndices(state.defaultMesh, indexCount, sizeof(uint16_t));
|
||||
|
||||
for (int i = 0; i <= segments; i++) {
|
||||
float v = i / (float) segments;
|
||||
|
@ -773,19 +786,19 @@ void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
|
|||
float x = sin(u * 2 * M_PI) * sin(v * M_PI);
|
||||
float y = cos(v * M_PI);
|
||||
float z = -cos(u * 2 * M_PI) * sin(v * M_PI);
|
||||
memcpy(vertices.floats, ((float[]) { x, y, z, x, y, z, u, 1 - v }), 8 * sizeof(float));
|
||||
vertices.floats += 8;
|
||||
memcpy(vertices, ((float[]) { x, y, z, x, y, z, u, 1 - v }), 8 * sizeof(float));
|
||||
vertices += 8;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < segments; i++) {
|
||||
unsigned int offset0 = i * (segments + 1);
|
||||
unsigned int offset1 = (i + 1) * (segments + 1);
|
||||
uint16_t offset0 = i * (segments + 1);
|
||||
uint16_t offset1 = (i + 1) * (segments + 1);
|
||||
for (int j = 0; j < segments; j++) {
|
||||
unsigned int i0 = offset0 + j;
|
||||
unsigned int i1 = offset1 + j;
|
||||
memcpy(indices.ints, ((uint32_t[]) { i0, i1, i0 + 1, i1, i1 + 1, i0 + 1 }), 6 * sizeof(uint32_t));
|
||||
indices.ints += 6;
|
||||
uint16_t i0 = offset0 + j;
|
||||
uint16_t i1 = offset1 + j;
|
||||
memcpy(indices, ((uint16_t[]) { i0, i1, i0 + 1, i1, i1 + 1, i0 + 1 }), 6 * sizeof(uint16_t));
|
||||
indices += 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,7 +806,8 @@ void lovrGraphicsSphere(Material* material, mat4 transform, int segments) {
|
|||
.transform = transform,
|
||||
.material = material,
|
||||
.mode = MESH_TRIANGLES,
|
||||
.range = { 0, segments * segments * 6 }
|
||||
.vertex.count = vertexCount,
|
||||
.index.count = indexCount
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -824,9 +838,9 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
|
|||
float offsety;
|
||||
uint32_t vertexCount;
|
||||
uint32_t maxVertices = strlen(str) * 6;
|
||||
VertexPointer vertexPointer = lovrGraphicsGetVertexPointer(maxVertices);
|
||||
lovrFontRender(font, str, wrap, halign, valign, vertexPointer.floats, &offsety, &vertexCount);
|
||||
lovrMeshWriteIndices(state.defaultMesh, 0, 0);
|
||||
float* vertices = lovrGraphicsGetVertexPointer(maxVertices);
|
||||
lovrFontRender(font, str, wrap, halign, valign, vertices, &offsety, &vertexCount);
|
||||
lovrMeshMapIndices(state.defaultMesh, 0, 0);
|
||||
|
||||
lovrGraphicsPush();
|
||||
lovrGraphicsMatrixTransform(transform);
|
||||
|
@ -837,7 +851,7 @@ void lovrGraphicsPrint(const char* str, mat4 transform, float wrap, HorizontalAl
|
|||
.shader = SHADER_FONT,
|
||||
.textures[TEXTURE_DIFFUSE] = font->texture,
|
||||
.mode = MESH_TRIANGLES,
|
||||
.range = { 0, vertexCount }
|
||||
.vertex.count = vertexCount
|
||||
});
|
||||
state.pipelines[state.pipeline].alphaCoverage = false;
|
||||
lovrGraphicsPop();
|
||||
|
|
|
@ -124,10 +124,6 @@ typedef struct {
|
|||
uint32_t count;
|
||||
uint16_t* data;
|
||||
} index;
|
||||
struct {
|
||||
int start;
|
||||
int count;
|
||||
} range;
|
||||
DefaultShader shader;
|
||||
Material* material;
|
||||
Texture* textures[MAX_MATERIAL_TEXTURES];
|
||||
|
@ -211,7 +207,7 @@ void lovrGraphicsMatrixTransform(mat4 transform);
|
|||
void lovrGraphicsSetProjection(mat4 projection);
|
||||
|
||||
// Rendering
|
||||
VertexPointer lovrGraphicsGetVertexPointer(uint32_t capacity);
|
||||
float* lovrGraphicsGetVertexPointer(uint32_t capacity);
|
||||
void lovrGraphicsClear(Color* color, float* depth, int* stencil);
|
||||
void lovrGraphicsDiscard(bool color, bool depth, bool stencil);
|
||||
void lovrGraphicsDraw(DrawCommand* draw);
|
||||
|
|
|
@ -19,13 +19,14 @@ typedef enum {
|
|||
|
||||
typedef struct Mesh Mesh;
|
||||
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage);
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage, bool readable);
|
||||
void lovrMeshDestroy(void* ref);
|
||||
void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor);
|
||||
void lovrMeshDetachAttribute(Mesh* mesh, const char* name);
|
||||
void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier);
|
||||
void lovrMeshDraw(Mesh* mesh, int instances);
|
||||
VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh);
|
||||
bool lovrMeshIsReadable(Mesh* mesh);
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh);
|
||||
void lovrMeshSetDrawMode(Mesh* mesh, MeshDrawMode drawMode);
|
||||
int lovrMeshGetVertexCount(Mesh* mesh);
|
||||
|
@ -35,9 +36,8 @@ void lovrMeshGetDrawRange(Mesh* mesh, uint32_t* start, uint32_t* count);
|
|||
void lovrMeshSetDrawRange(Mesh* mesh, uint32_t start, uint32_t count);
|
||||
Material* lovrMeshGetMaterial(Mesh* mesh);
|
||||
void lovrMeshSetMaterial(Mesh* mesh, Material* material);
|
||||
VertexPointer lovrMeshMapVertices(Mesh* mesh, uint32_t start, uint32_t count, bool read, bool write);
|
||||
void lovrMeshUnmapVertices(Mesh* mesh);
|
||||
IndexPointer lovrMeshReadIndices(Mesh* mesh, uint32_t* count, size_t* size);
|
||||
IndexPointer lovrMeshWriteIndices(Mesh* mesh, uint32_t count, size_t size);
|
||||
void lovrMeshUnmapIndices(Mesh* mesh);
|
||||
void lovrMeshResize(Mesh* mesh, uint32_t count);
|
||||
void* lovrMeshMapVertices(Mesh* mesh, size_t offset);
|
||||
void lovrMeshFlushVertices(Mesh* mesh, size_t offset, size_t size);
|
||||
void* lovrMeshMapIndices(Mesh* mesh, uint32_t count, size_t indexSize);
|
||||
void lovrMeshFlushIndices(Mesh* mesh);
|
||||
void* lovrMeshReadIndices(Mesh* mesh, uint32_t* count, size_t* indexSize);
|
||||
|
|
|
@ -62,12 +62,14 @@ Model* lovrModelCreate(ModelData* modelData) {
|
|||
model->modelData = modelData;
|
||||
model->aabbDirty = true;
|
||||
|
||||
model->mesh = lovrMeshCreate(modelData->vertexData->count, modelData->vertexData->format, MESH_TRIANGLES, USAGE_STATIC);
|
||||
VertexPointer vertices = lovrMeshMapVertices(model->mesh, 0, modelData->vertexData->count, false, true);
|
||||
memcpy(vertices.raw, modelData->vertexData->blob.data, modelData->vertexData->count * modelData->vertexData->format.stride);
|
||||
model->mesh = lovrMeshCreate(modelData->vertexData->count, modelData->vertexData->format, MESH_TRIANGLES, USAGE_STATIC, false);
|
||||
void* vertices = lovrMeshMapVertices(model->mesh, 0);
|
||||
memcpy(vertices, modelData->vertexData->blob.data, modelData->vertexData->count * modelData->vertexData->format.stride);
|
||||
lovrMeshFlushVertices(model->mesh, 0, modelData->vertexData->count * modelData->vertexData->format.stride);
|
||||
|
||||
IndexPointer indices = lovrMeshWriteIndices(model->mesh, modelData->indexCount, modelData->indexSize);
|
||||
memcpy(indices.raw, modelData->indices.raw, modelData->indexCount * modelData->indexSize);
|
||||
void* indices = lovrMeshMapIndices(model->mesh, modelData->indexCount, modelData->indexSize);
|
||||
memcpy(indices, modelData->indices.raw, modelData->indexCount * modelData->indexSize);
|
||||
lovrMeshFlushIndices(model->mesh);
|
||||
|
||||
if (modelData->textures.length > 0) {
|
||||
model->textures = calloc(modelData->textures.length, sizeof(Texture*));
|
||||
|
|
|
@ -147,8 +147,11 @@ struct Canvas {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
Mesh* mesh;
|
||||
int attributeIndex;
|
||||
Buffer* buffer;
|
||||
AttributeType type;
|
||||
int components;
|
||||
size_t offset;
|
||||
int stride;
|
||||
int divisor;
|
||||
bool enabled;
|
||||
} MeshAttachment;
|
||||
|
@ -157,27 +160,22 @@ typedef map_t(MeshAttachment) map_attachment_t;
|
|||
|
||||
struct Mesh {
|
||||
Ref ref;
|
||||
uint32_t vao;
|
||||
uint32_t count;
|
||||
VertexFormat format;
|
||||
MeshDrawMode drawMode;
|
||||
VertexFormat format;
|
||||
bool readable;
|
||||
BufferUsage usage;
|
||||
VertexPointer data;
|
||||
IndexPointer indices;
|
||||
Buffer* vbo;
|
||||
Buffer* ibo;
|
||||
uint32_t indexCount;
|
||||
size_t indexSize;
|
||||
size_t indexCapacity;
|
||||
bool mappedIndices;
|
||||
uint32_t dirtyStart;
|
||||
uint32_t dirtyEnd;
|
||||
uint32_t rangeStart;
|
||||
uint32_t rangeCount;
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
GLuint ibo;
|
||||
Material* material;
|
||||
map_attachment_t attachments;
|
||||
MeshAttachment layout[MAX_ATTACHMENTS];
|
||||
bool isAttachment;
|
||||
};
|
||||
|
||||
// Helper functions
|
||||
|
@ -1496,7 +1494,7 @@ TextureData* lovrCanvasNewTextureData(Canvas* canvas, int index) {
|
|||
|
||||
// Buffer
|
||||
|
||||
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage) {
|
||||
Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage, bool readable) {
|
||||
Buffer* buffer = lovrAlloc(Buffer, lovrBufferDestroy);
|
||||
if (!buffer) return NULL;
|
||||
|
||||
|
@ -1507,12 +1505,9 @@ Buffer* lovrBufferCreate(size_t size, void* data, BufferUsage usage) {
|
|||
|
||||
#ifndef EMSCRIPTEN
|
||||
if (GLAD_GL_ARB_buffer_storage) {
|
||||
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT;
|
||||
GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (readable ? GL_MAP_READ_BIT : 0);
|
||||
glBufferStorage(GL_COPY_WRITE_BUFFER, size, data, flags);
|
||||
|
||||
if (usage != USAGE_STATIC) {
|
||||
buffer->data = glMapBufferRange(GL_COPY_WRITE_BUFFER, 0, size, flags | GL_MAP_FLUSH_EXPLICIT_BIT);
|
||||
}
|
||||
} else {
|
||||
#endif
|
||||
buffer->data = calloc(1, size);
|
||||
|
@ -1550,7 +1545,6 @@ void* lovrBufferMap(Buffer* buffer, size_t offset) {
|
|||
}
|
||||
|
||||
void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size) {
|
||||
lovrAssert(buffer->usage != USAGE_STATIC, "Static buffers may not be updated");
|
||||
lovrGpuBindGenericBuffer(buffer->id);
|
||||
#ifndef EMSCRIPTEN
|
||||
if (GLAD_GL_ARB_buffer_storage) {
|
||||
|
@ -1565,7 +1559,7 @@ void lovrBufferFlush(Buffer* buffer, size_t offset, size_t size) {
|
|||
|
||||
void lovrBufferLock(Buffer* buffer) {
|
||||
#ifndef EMSCRIPTEN
|
||||
if (!GLAD_GL_ARB_buffer_storage || buffer->usage == USAGE_STATIC) {
|
||||
if (!GLAD_GL_ARB_buffer_storage) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1576,7 +1570,7 @@ void lovrBufferLock(Buffer* buffer) {
|
|||
|
||||
void lovrBufferUnlock(Buffer* buffer) {
|
||||
#ifndef EMSCRIPTEN
|
||||
if (!GLAD_GL_ARB_buffer_storage || buffer->usage == USAGE_STATIC || !buffer->lock) {
|
||||
if (!GLAD_GL_ARB_buffer_storage || !buffer->lock) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2206,7 +2200,7 @@ ShaderBlock* lovrShaderBlockCreate(vec_uniform_t* uniforms, BlockType type, Buff
|
|||
block->target = block->type == BLOCK_UNIFORM ? GL_UNIFORM_BUFFER : GL_SHADER_STORAGE_BUFFER;
|
||||
#endif
|
||||
block->type = type;
|
||||
block->buffer = lovrBufferCreate(size, NULL, usage);
|
||||
block->buffer = lovrBufferCreate(size, NULL, usage, false);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
@ -2278,69 +2272,68 @@ Buffer* lovrShaderBlockGetBuffer(ShaderBlock* block) {
|
|||
|
||||
// Mesh
|
||||
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage) {
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage, bool readable) {
|
||||
Mesh* mesh = lovrAlloc(Mesh, lovrMeshDestroy);
|
||||
if (!mesh) return NULL;
|
||||
|
||||
mesh->count = count;
|
||||
mesh->format = format;
|
||||
mesh->readable = readable;
|
||||
mesh->drawMode = drawMode;
|
||||
mesh->usage = usage;
|
||||
|
||||
glGenBuffers(1, &mesh->vbo);
|
||||
glGenBuffers(1, &mesh->ibo);
|
||||
lovrGpuBindVertexBuffer(mesh->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, count * format.stride, NULL, convertBufferUsage(mesh->usage));
|
||||
mesh->vbo = lovrBufferCreate(count * format.stride, NULL, usage, readable);
|
||||
glGenVertexArrays(1, &mesh->vao);
|
||||
|
||||
map_init(&mesh->attachments);
|
||||
for (int i = 0; i < format.count; i++) {
|
||||
map_set(&mesh->attachments, format.attributes[i].name, ((MeshAttachment) { mesh, i, 0, true }));
|
||||
lovrRetain(mesh->vbo);
|
||||
map_set(&mesh->attachments, format.attributes[i].name, ((MeshAttachment) {
|
||||
.buffer = mesh->vbo,
|
||||
.type = format.attributes[i].type,
|
||||
.components = format.attributes[i].count,
|
||||
.offset = format.attributes[i].offset,
|
||||
.stride = format.stride,
|
||||
.enabled = true
|
||||
}));
|
||||
}
|
||||
|
||||
mesh->data.raw = calloc(count, format.stride);
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void lovrMeshDestroy(void* ref) {
|
||||
Mesh* mesh = ref;
|
||||
lovrRelease(mesh->material);
|
||||
free(mesh->data.raw);
|
||||
free(mesh->indices.raw);
|
||||
glDeleteBuffers(1, &mesh->vbo);
|
||||
glDeleteBuffers(1, &mesh->ibo);
|
||||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
const char* key;
|
||||
map_iter_t iter = map_iter(&mesh->attachments);
|
||||
while ((key = map_next(&mesh->attachments, &iter)) != NULL) {
|
||||
MeshAttachment* attachment = map_get(&mesh->attachments, key);
|
||||
if (attachment->mesh != mesh) {
|
||||
lovrRelease(attachment->mesh);
|
||||
}
|
||||
lovrRelease(attachment->buffer);
|
||||
}
|
||||
lovrRelease(mesh->vbo);
|
||||
lovrRelease(mesh->ibo);
|
||||
map_deinit(&mesh->attachments);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor) {
|
||||
MeshAttachment* otherAttachment = map_get(&other->attachments, name);
|
||||
lovrAssert(!mesh->isAttachment, "Attempted to attach to a mesh which is an attachment itself");
|
||||
lovrAssert(otherAttachment, "No attribute named '%s' exists", name);
|
||||
lovrAssert(!map_get(&mesh->attachments, name), "Mesh already has an attribute named '%s'", name);
|
||||
lovrAssert(divisor >= 0, "Divisor can't be negative");
|
||||
|
||||
MeshAttachment attachment = { other, otherAttachment->attributeIndex, divisor, true };
|
||||
MeshAttachment attachment = *otherAttachment;
|
||||
attachment.divisor = divisor;
|
||||
attachment.enabled = true;
|
||||
map_set(&mesh->attachments, name, attachment);
|
||||
other->isAttachment = true;
|
||||
lovrRetain(other);
|
||||
lovrRetain(attachment.buffer);
|
||||
}
|
||||
|
||||
void lovrMeshDetachAttribute(Mesh* mesh, const char* name) {
|
||||
MeshAttachment* attachment = map_get(&mesh->attachments, name);
|
||||
lovrAssert(attachment, "No attached attribute '%s' was found", name);
|
||||
lovrAssert(attachment->mesh != mesh, "Attribute '%s' was not attached from another Mesh", name);
|
||||
lovrRelease(attachment->mesh);
|
||||
lovrAssert(attachment->buffer != mesh->vbo, "Attribute '%s' was not attached from another Mesh", name);
|
||||
lovrRelease(attachment->buffer);
|
||||
map_remove(&mesh->attachments, name);
|
||||
}
|
||||
|
||||
|
@ -2352,10 +2345,8 @@ void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) {
|
|||
memset(layout, 0, MAX_ATTACHMENTS * sizeof(MeshAttachment));
|
||||
|
||||
lovrGpuBindVertexArray(mesh->vao);
|
||||
lovrMeshUnmapVertices(mesh);
|
||||
lovrMeshUnmapIndices(mesh);
|
||||
if (mesh->indexCount > 0) {
|
||||
lovrGpuBindIndexBuffer(mesh->ibo);
|
||||
lovrGpuBindIndexBuffer(mesh->ibo->id);
|
||||
}
|
||||
|
||||
while ((key = map_next(&mesh->attachments, &iter)) != NULL) {
|
||||
|
@ -2364,8 +2355,6 @@ void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) {
|
|||
if (location >= 0) {
|
||||
MeshAttachment* attachment = map_get(&mesh->attachments, key);
|
||||
layout[location] = *attachment;
|
||||
lovrMeshUnmapVertices(attachment->mesh);
|
||||
lovrMeshUnmapIndices(attachment->mesh);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2391,31 +2380,31 @@ void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) {
|
|||
glVertexAttribDivisor(i, current.divisor * divisorMultiplier);
|
||||
}
|
||||
|
||||
if (previous.mesh != current.mesh || previous.attributeIndex != current.attributeIndex) {
|
||||
lovrGpuBindVertexBuffer(current.mesh->vbo);
|
||||
VertexFormat* format = ¤t.mesh->format;
|
||||
Attribute attribute = format->attributes[current.attributeIndex];
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT:
|
||||
glVertexAttribPointer(i, attribute.count, GL_FLOAT, GL_TRUE, format->stride, (void*) attribute.offset);
|
||||
break;
|
||||
bool changed =
|
||||
previous.buffer != current.buffer ||
|
||||
previous.type != current.type ||
|
||||
previous.components != current.components ||
|
||||
previous.offset != current.offset ||
|
||||
previous.stride != current.stride;
|
||||
|
||||
case ATTR_BYTE:
|
||||
glVertexAttribPointer(i, attribute.count, GL_UNSIGNED_BYTE, GL_TRUE, format->stride, (void*) attribute.offset);
|
||||
break;
|
||||
|
||||
case ATTR_INT:
|
||||
glVertexAttribIPointer(i, attribute.count, GL_INT, format->stride, (void*) attribute.offset);
|
||||
break;
|
||||
if (changed) {
|
||||
lovrGpuBindVertexBuffer(current.buffer->id);
|
||||
int count = current.components;
|
||||
int stride = current.stride;
|
||||
GLvoid* offset = (GLvoid*) current.offset;
|
||||
switch (current.type) {
|
||||
case ATTR_FLOAT: glVertexAttribPointer(i, count, GL_FLOAT, GL_TRUE, stride, offset); break;
|
||||
case ATTR_BYTE: glVertexAttribPointer(i, count, GL_UNSIGNED_BYTE, GL_TRUE, stride, offset); break;
|
||||
case ATTR_INT: glVertexAttribIPointer(i, count, GL_INT, stride, offset); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh->layout[i] = current;
|
||||
}
|
||||
memcpy(mesh->layout, layout, MAX_ATTACHMENTS * sizeof(MeshAttachment));
|
||||
}
|
||||
|
||||
void lovrMeshDraw(Mesh* mesh, int instances) {
|
||||
GLenum glDrawMode = convertMeshDrawMode(lovrMeshGetDrawMode(mesh));
|
||||
GLenum glDrawMode = convertMeshDrawMode(mesh->drawMode);
|
||||
|
||||
if (mesh->indexCount > 0) {
|
||||
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->indexCount;
|
||||
|
@ -2427,7 +2416,7 @@ void lovrMeshDraw(Mesh* mesh, int instances) {
|
|||
glDrawElements(glDrawMode, count, indexType, (GLvoid*) offset);
|
||||
}
|
||||
} else {
|
||||
size_t count = mesh->rangeCount ? mesh->rangeCount : lovrMeshGetVertexCount(mesh);
|
||||
size_t count = mesh->rangeCount ? mesh->rangeCount : mesh->count;
|
||||
if (instances > 1) {
|
||||
glDrawArraysInstanced(glDrawMode, mesh->rangeStart, count, instances);
|
||||
} else {
|
||||
|
@ -2442,6 +2431,10 @@ VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh) {
|
|||
return &mesh->format;
|
||||
}
|
||||
|
||||
bool lovrMeshIsReadable(Mesh* mesh) {
|
||||
return mesh->readable;
|
||||
}
|
||||
|
||||
MeshDrawMode lovrMeshGetDrawMode(Mesh* mesh) {
|
||||
return mesh->drawMode;
|
||||
}
|
||||
|
@ -2490,88 +2483,35 @@ void lovrMeshSetMaterial(Mesh* mesh, Material* material) {
|
|||
}
|
||||
}
|
||||
|
||||
VertexPointer lovrMeshMapVertices(Mesh* mesh, uint32_t start, uint32_t count, bool read, bool write) {
|
||||
if (write) {
|
||||
mesh->dirtyStart = MIN(mesh->dirtyStart, start);
|
||||
mesh->dirtyEnd = MAX(mesh->dirtyEnd, start + count);
|
||||
}
|
||||
|
||||
return (VertexPointer) { .bytes = mesh->data.bytes + start * mesh->format.stride };
|
||||
void* lovrMeshMapVertices(Mesh* mesh, size_t offset) {
|
||||
return lovrBufferMap(mesh->vbo, offset);
|
||||
}
|
||||
|
||||
void lovrMeshUnmapVertices(Mesh* mesh) {
|
||||
if (mesh->dirtyEnd == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t stride = mesh->format.stride;
|
||||
lovrGpuBindVertexBuffer(mesh->vbo);
|
||||
if (mesh->usage == USAGE_STREAM) {
|
||||
glBufferData(GL_ARRAY_BUFFER, mesh->count * stride, mesh->data.bytes, convertBufferUsage(mesh->usage));
|
||||
} else {
|
||||
size_t offset = mesh->dirtyStart * stride;
|
||||
size_t count = (mesh->dirtyEnd - mesh->dirtyStart) * stride;
|
||||
glBufferSubData(GL_ARRAY_BUFFER, offset, count, mesh->data.bytes + offset);
|
||||
}
|
||||
|
||||
mesh->dirtyStart = INT_MAX;
|
||||
mesh->dirtyEnd = 0;
|
||||
void lovrMeshFlushVertices(Mesh* mesh, size_t offset, size_t size) {
|
||||
lovrBufferFlush(mesh->vbo, offset, size);
|
||||
}
|
||||
|
||||
IndexPointer lovrMeshReadIndices(Mesh* mesh, uint32_t* count, size_t* size) {
|
||||
*size = mesh->indexSize;
|
||||
*count = mesh->indexCount;
|
||||
|
||||
if (mesh->indexCount == 0) {
|
||||
return (IndexPointer) { .raw = NULL };
|
||||
} else if (mesh->mappedIndices) {
|
||||
lovrMeshUnmapIndices(mesh);
|
||||
}
|
||||
|
||||
return mesh->indices;
|
||||
}
|
||||
|
||||
IndexPointer lovrMeshWriteIndices(Mesh* mesh, uint32_t count, size_t size) {
|
||||
if (mesh->mappedIndices) {
|
||||
lovrMeshUnmapIndices(mesh);
|
||||
}
|
||||
|
||||
mesh->indexSize = size;
|
||||
void* lovrMeshMapIndices(Mesh* mesh, uint32_t count, size_t indexSize) {
|
||||
mesh->indexSize = indexSize;
|
||||
mesh->indexCount = count;
|
||||
|
||||
if (count == 0) {
|
||||
return (IndexPointer) { .raw = NULL };
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lovrGpuBindVertexArray(mesh->vao);
|
||||
lovrGpuBindIndexBuffer(mesh->ibo);
|
||||
mesh->mappedIndices = true;
|
||||
|
||||
if (mesh->indexCapacity < size * count) {
|
||||
mesh->indexCapacity = nextPo2(size * count);
|
||||
mesh->indices.raw = realloc(mesh->indices.raw, mesh->indexCapacity);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->indexCapacity, NULL, convertBufferUsage(mesh->usage));
|
||||
if (mesh->indexCapacity < indexSize * count) {
|
||||
mesh->indexCapacity = nextPo2(indexSize * count);
|
||||
lovrRelease(mesh->ibo);
|
||||
mesh->ibo = lovrBufferCreate(mesh->indexCapacity, NULL, mesh->usage, mesh->readable);
|
||||
}
|
||||
|
||||
return mesh->indices;
|
||||
return lovrBufferMap(mesh->ibo, 0);
|
||||
}
|
||||
|
||||
void lovrMeshUnmapIndices(Mesh* mesh) {
|
||||
if (!mesh->mappedIndices) {
|
||||
return;
|
||||
}
|
||||
|
||||
mesh->mappedIndices = false;
|
||||
lovrGpuBindIndexBuffer(mesh->ibo);
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mesh->indexCount * mesh->indexSize, mesh->indices.raw);
|
||||
void lovrMeshFlushIndices(Mesh* mesh) {
|
||||
lovrBufferFlush(mesh->ibo, 0, mesh->indexCount * mesh->indexSize);
|
||||
}
|
||||
|
||||
void lovrMeshResize(Mesh* mesh, uint32_t count) {
|
||||
if (mesh->count < count) {
|
||||
count = nextPo2(count);
|
||||
mesh->count = count;
|
||||
lovrGpuBindVertexBuffer(mesh->vbo);
|
||||
mesh->data.raw = realloc(mesh->data.raw, count * mesh->format.stride);
|
||||
glBufferData(GL_ARRAY_BUFFER, count * mesh->format.stride, mesh->data.raw, convertBufferUsage(mesh->usage));
|
||||
}
|
||||
void* lovrMeshReadIndices(Mesh* mesh, uint32_t* count, size_t* indexSize) {
|
||||
return *count = mesh->indexCount, *indexSize = mesh->indexSize, lovrBufferMap(mesh->ibo, 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue