mirror of https://github.com/bjornbytes/lovr.git
Implementation of mesh:attachAttributes(), with optional instance divisor
Some features remain to be implemented, these are marked with TODOs. Currently it is not allowed to attach a mesh which itself has attachments.
This commit is contained in:
parent
58e59d9772
commit
1732384262
|
@ -229,6 +229,20 @@ int l_lovrMeshSetMaterial(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int l_lovrMeshAttachAttributes(lua_State* L) {
|
||||
Mesh* attachTo = luax_checktype(L, 1, Mesh);
|
||||
Mesh* attachThis = luax_checktype(L, 2, Mesh);
|
||||
int instanceDivisor = luaL_optnumber(L, 3, 0);
|
||||
// TODO: Check attribute name(s) in 4th argument and if present only attach those
|
||||
|
||||
VertexFormat* format = &attachThis->vertexData->format;
|
||||
for(int c = 0; c < format->count; c++) {
|
||||
lovrMeshAttach(attachTo, attachThis, c, instanceDivisor);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lovrMesh[] = {
|
||||
{ "drawInstanced", l_lovrMeshDrawInstanced },
|
||||
{ "draw", l_lovrMeshDraw },
|
||||
|
@ -249,5 +263,6 @@ const luaL_Reg lovrMesh[] = {
|
|||
{ "setDrawRange", l_lovrMeshSetDrawRange },
|
||||
{ "getMaterial", l_lovrMeshGetMaterial },
|
||||
{ "setMaterial", l_lovrMeshSetMaterial },
|
||||
{ "attachAttributes", l_lovrMeshAttachAttributes },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
|
|
@ -4,6 +4,36 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static void lovrMeshBindAttribute(Shader* shader, Mesh *mesh, VertexFormat *format, int i, bool enabled, int divisor) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
int location = lovrShaderGetAttributeId(shader, attribute.name);
|
||||
|
||||
if (location >= 0) {
|
||||
if (enabled) {
|
||||
glEnableVertexAttribArray(location);
|
||||
|
||||
GLenum glType;
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: glType = GL_FLOAT; break;
|
||||
case ATTR_BYTE: glType = GL_UNSIGNED_BYTE; break;
|
||||
case ATTR_INT: glType = GL_UNSIGNED_INT; break;
|
||||
}
|
||||
|
||||
// Divisor lives in the VAO and the VAO is per-mesh, so the only reason we would need to set a zero divisor for an attribute is if a nonzero divisor attribute is attached then disabled, and a zero divisor attribute is enabled afterward in its place. Nonzero attachments length is used to determine there is a risk this has happened.
|
||||
if (divisor || mesh->attachments.length)
|
||||
glVertexAttribDivisor(location, divisor);
|
||||
|
||||
if (attribute.type == ATTR_INT) {
|
||||
glVertexAttribIPointer(location, attribute.count, glType, format->stride, (void*) attribute.offset);
|
||||
} else {
|
||||
glVertexAttribPointer(location, attribute.count, glType, GL_TRUE, format->stride, (void*) attribute.offset);
|
||||
}
|
||||
} else {
|
||||
glDisableVertexAttribArray(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lovrMeshBindAttributes(Mesh* mesh) {
|
||||
Shader* shader = lovrGraphicsGetActiveShader();
|
||||
if (shader == mesh->lastShader && !mesh->attributesDirty) {
|
||||
|
@ -14,28 +44,15 @@ static void lovrMeshBindAttributes(Mesh* mesh) {
|
|||
|
||||
VertexFormat* format = &mesh->vertexData->format;
|
||||
for (int i = 0; i < format->count; i++) {
|
||||
Attribute attribute = format->attributes[i];
|
||||
int location = lovrShaderGetAttributeId(shader, attribute.name);
|
||||
lovrMeshBindAttribute(shader, mesh, format, i, mesh->enabledAttributes & (1 << i), 0);
|
||||
}
|
||||
|
||||
if (location >= 0) {
|
||||
if (mesh->enabledAttributes & (1 << i)) {
|
||||
glEnableVertexAttribArray(location);
|
||||
|
||||
GLenum glType;
|
||||
switch (attribute.type) {
|
||||
case ATTR_FLOAT: glType = GL_FLOAT; break;
|
||||
case ATTR_BYTE: glType = GL_UNSIGNED_BYTE; break;
|
||||
case ATTR_INT: glType = GL_UNSIGNED_INT; break;
|
||||
}
|
||||
|
||||
if (attribute.type == ATTR_INT) {
|
||||
glVertexAttribIPointer(location, attribute.count, glType, format->stride, (void*) attribute.offset);
|
||||
} else {
|
||||
glVertexAttribPointer(location, attribute.count, glType, GL_TRUE, format->stride, (void*) attribute.offset);
|
||||
}
|
||||
} else {
|
||||
glDisableVertexAttribArray(location);
|
||||
}
|
||||
{
|
||||
int i; MeshAttachment attachment;
|
||||
vec_foreach(&mesh->attachments, attachment, i) {
|
||||
lovrGraphicsBindVertexBuffer(attachment.mesh->vbo);
|
||||
// TODO: Allow disabling of attached attributes?
|
||||
lovrMeshBindAttribute(shader, attachment.mesh, &attachment.mesh->vertexData->format, attachment.attribute, true, attachment.instanceDivisor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,8 +87,11 @@ Mesh* lovrMeshCreate(uint32_t count, VertexFormat* format, MeshDrawMode drawMode
|
|||
mesh->vbo = 0;
|
||||
mesh->ibo = 0;
|
||||
mesh->material = NULL;
|
||||
vec_init(&mesh->attachments);
|
||||
mesh->lastShader = NULL;
|
||||
|
||||
mesh->isAnAttachment = false;
|
||||
|
||||
glGenBuffers(1, &mesh->vbo);
|
||||
glGenBuffers(1, &mesh->ibo);
|
||||
lovrGraphicsBindVertexBuffer(mesh->vbo);
|
||||
|
@ -88,6 +108,15 @@ void lovrMeshDestroy(void* ref) {
|
|||
glDeleteBuffers(1, &mesh->vbo);
|
||||
glDeleteBuffers(1, &mesh->ibo);
|
||||
glDeleteVertexArrays(1, &mesh->vao);
|
||||
|
||||
{
|
||||
int i; MeshAttachment attachment;
|
||||
vec_foreach(&mesh->attachments, attachment, i) {
|
||||
lovrRelease(attachment.mesh);
|
||||
}
|
||||
}
|
||||
vec_deinit(&mesh->attachments);
|
||||
|
||||
free(mesh->indices.raw);
|
||||
free(mesh);
|
||||
}
|
||||
|
@ -268,3 +297,14 @@ void lovrMeshUnmap(Mesh* mesh) {
|
|||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
#endif
|
||||
}
|
||||
|
||||
void lovrMeshAttach(Mesh *attachTo, Mesh* attachThis, int attribute, int instanceDivisor)
|
||||
{
|
||||
lovrAssert(!attachTo->isAnAttachment, "Attempted to attach to a mesh which is an attachment itself");
|
||||
lovrAssert(!attachThis->attachments.length, "Attempted to attach a mesh which has attachments itself");
|
||||
|
||||
MeshAttachment attachment = {attachThis, attribute, instanceDivisor};
|
||||
attachThis->isAnAttachment = true;
|
||||
lovrRetain(attachThis);
|
||||
vec_push(&attachTo->attachments, attachment);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,17 @@ typedef enum {
|
|||
MESH_STREAM = GL_STREAM_DRAW
|
||||
} MeshUsage;
|
||||
|
||||
typedef struct Mesh Mesh;
|
||||
|
||||
typedef struct {
|
||||
Mesh *mesh;
|
||||
int attribute;
|
||||
int instanceDivisor;
|
||||
} MeshAttachment;
|
||||
|
||||
typedef vec_t(MeshAttachment) vec_meshattachment_t;
|
||||
|
||||
struct Mesh {
|
||||
Ref ref;
|
||||
VertexData* vertexData;
|
||||
IndexPointer indices;
|
||||
|
@ -43,7 +53,9 @@ typedef struct {
|
|||
GLuint ibo;
|
||||
Material* material;
|
||||
Shader* lastShader;
|
||||
} Mesh;
|
||||
vec_meshattachment_t attachments;
|
||||
bool isAnAttachment;
|
||||
};
|
||||
|
||||
Mesh* lovrMeshCreate(uint32_t count, VertexFormat* format, MeshDrawMode drawMode, MeshUsage usage);
|
||||
void lovrMeshDestroy(void* ref);
|
||||
|
@ -64,3 +76,4 @@ Material* lovrMeshGetMaterial(Mesh* mesh);
|
|||
void lovrMeshSetMaterial(Mesh* mesh, Material* material);
|
||||
VertexPointer lovrMeshMap(Mesh* mesh, int start, size_t count, bool read, bool write);
|
||||
void lovrMeshUnmap(Mesh* mesh);
|
||||
void lovrMeshAttach(Mesh *attachTo, Mesh* attachThis, int attribute, int instanceDivisor);
|
||||
|
|
Loading…
Reference in New Issue