Refactor Mesh attributes;

This commit is contained in:
bjorn 2018-12-07 19:11:14 -08:00
parent 40454d1380
commit 7f333ce956
3 changed files with 75 additions and 58 deletions

View File

@ -11,19 +11,36 @@ int l_lovrMeshAttachAttributes(lua_State* L) {
if (lua_isnoneornil(L, 4)) { if (lua_isnoneornil(L, 4)) {
VertexFormat* format = lovrMeshGetVertexFormat(other); VertexFormat* format = lovrMeshGetVertexFormat(other);
for (int i = 0; i < format->count; i++) { for (int i = 0; i < format->count; i++) {
lovrMeshAttachAttribute(mesh, other, format->attributes[i].name, instanceDivisor); const char* name = format->attributes[i].name;
MeshAttribute* attribute = lovrMeshGetAttribute(other, name);
MeshAttribute attachment = *attribute;
attachment.divisor = instanceDivisor;
attachment.enabled = true;
lovrMeshAttachAttribute(mesh, name, &attachment);
} }
} else if (lua_istable(L, 4)) { } else if (lua_istable(L, 4)) {
int length = lua_objlen(L, 4); int length = lua_objlen(L, 4);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
lua_rawgeti(L, 4, i + 1); lua_rawgeti(L, 4, i + 1);
lovrMeshAttachAttribute(mesh, other, lua_tostring(L, -1), instanceDivisor); const char* name = lua_tostring(L, -1);
MeshAttribute* attribute = lovrMeshGetAttribute(other, name);
lovrAssert(attribute, "Tried to attach non-existent attribute %s", name);
MeshAttribute attachment = *attribute;
attachment.divisor = instanceDivisor;
attachment.enabled = true;
lovrMeshAttachAttribute(mesh, name, &attachment);
lua_pop(L, 1); lua_pop(L, 1);
} }
} else { } else {
int top = lua_gettop(L); int top = lua_gettop(L);
for (int i = 4; i <= top; i++) { for (int i = 4; i <= top; i++) {
lovrMeshAttachAttribute(mesh, other, lua_tostring(L, i), instanceDivisor); const char* name = lua_tostring(L, i);
MeshAttribute* attribute = lovrMeshGetAttribute(other, name);
lovrAssert(attribute, "Tried to attach non-existent attribute %s", name);
MeshAttribute attachment = *attribute;
attachment.divisor = instanceDivisor;
attachment.enabled = true;
lovrMeshAttachAttribute(mesh, name, &attachment);
} }
} }

View File

@ -1,11 +1,24 @@
#include "graphics/material.h" #include "graphics/material.h"
#include "graphics/shader.h" #include "graphics/shader.h"
#include "data/vertexData.h" #include "data/vertexData.h"
#include "lib/map/map.h"
#include <stdbool.h> #include <stdbool.h>
#pragma once #pragma once
#define MAX_ATTACHMENTS 16 #define MAX_ATTRIBUTES 16
typedef struct {
Buffer* buffer;
AttributeType type;
int components;
size_t offset;
int stride;
int divisor;
bool enabled;
} MeshAttribute;
typedef map_t(MeshAttribute) map_attribute_t;
typedef enum { typedef enum {
MESH_POINTS, MESH_POINTS,
@ -21,8 +34,9 @@ typedef struct Mesh Mesh;
Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage, bool readable); Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode, BufferUsage usage, bool readable);
void lovrMeshDestroy(void* ref); void lovrMeshDestroy(void* ref);
void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor); void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute);
void lovrMeshDetachAttribute(Mesh* mesh, const char* name); void lovrMeshDetachAttribute(Mesh* mesh, const char* name);
MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, const char* name);
void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier); void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier);
void lovrMeshDraw(Mesh* mesh, int instances); void lovrMeshDraw(Mesh* mesh, int instances);
VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh); VertexFormat* lovrMeshGetVertexFormat(Mesh* mesh);

View File

@ -146,18 +146,6 @@ struct Canvas {
bool immortal; bool immortal;
}; };
typedef struct {
Buffer* buffer;
AttributeType type;
int components;
size_t offset;
int stride;
int divisor;
bool enabled;
} MeshAttachment;
typedef map_t(MeshAttachment) map_attachment_t;
struct Mesh { struct Mesh {
Ref ref; Ref ref;
uint32_t vao; uint32_t vao;
@ -174,8 +162,8 @@ struct Mesh {
uint32_t rangeStart; uint32_t rangeStart;
uint32_t rangeCount; uint32_t rangeCount;
Material* material; Material* material;
map_attachment_t attachments; map_attribute_t attributes;
MeshAttachment layout[MAX_ATTACHMENTS]; MeshAttribute layout[MAX_ATTRIBUTES];
}; };
// Helper functions // Helper functions
@ -2284,10 +2272,10 @@ Mesh* lovrMeshCreate(uint32_t count, VertexFormat format, MeshDrawMode drawMode,
mesh->vbo = lovrBufferCreate(count * format.stride, NULL, usage, readable); mesh->vbo = lovrBufferCreate(count * format.stride, NULL, usage, readable);
glGenVertexArrays(1, &mesh->vao); glGenVertexArrays(1, &mesh->vao);
map_init(&mesh->attachments); map_init(&mesh->attributes);
for (int i = 0; i < format.count; i++) { for (int i = 0; i < format.count; i++) {
lovrRetain(mesh->vbo); lovrRetain(mesh->vbo);
map_set(&mesh->attachments, format.attributes[i].name, ((MeshAttachment) { map_set(&mesh->attributes, format.attributes[i].name, ((MeshAttribute) {
.buffer = mesh->vbo, .buffer = mesh->vbo,
.type = format.attributes[i].type, .type = format.attributes[i].type,
.components = format.attributes[i].count, .components = format.attributes[i].count,
@ -2305,64 +2293,62 @@ void lovrMeshDestroy(void* ref) {
lovrRelease(mesh->material); lovrRelease(mesh->material);
glDeleteVertexArrays(1, &mesh->vao); glDeleteVertexArrays(1, &mesh->vao);
const char* key; const char* key;
map_iter_t iter = map_iter(&mesh->attachments); map_iter_t iter = map_iter(&mesh->attributes);
while ((key = map_next(&mesh->attachments, &iter)) != NULL) { while ((key = map_next(&mesh->attributes, &iter)) != NULL) {
MeshAttachment* attachment = map_get(&mesh->attachments, key); MeshAttribute* attribute = map_get(&mesh->attributes, key);
lovrRelease(attachment->buffer); lovrRelease(attribute->buffer);
} }
map_deinit(&mesh->attributes);
lovrRelease(mesh->vbo); lovrRelease(mesh->vbo);
lovrRelease(mesh->ibo); lovrRelease(mesh->ibo);
map_deinit(&mesh->attachments);
free(mesh); free(mesh);
} }
void lovrMeshAttachAttribute(Mesh* mesh, Mesh* other, const char* name, int divisor) { void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute) {
MeshAttachment* otherAttachment = map_get(&other->attachments, name); lovrAssert(!map_get(&mesh->attributes, name), "Mesh already has an attribute named '%s'", name);
lovrAssert(otherAttachment, "No attribute named '%s' exists", name); lovrAssert(attribute->divisor >= 0, "Divisor can't be negative");
lovrAssert(!map_get(&mesh->attachments, name), "Mesh already has an attribute named '%s'", name); map_set(&mesh->attributes, name, *attribute);
lovrAssert(divisor >= 0, "Divisor can't be negative"); lovrRetain(attribute->buffer);
MeshAttachment attachment = *otherAttachment;
attachment.divisor = divisor;
attachment.enabled = true;
map_set(&mesh->attachments, name, attachment);
lovrRetain(attachment.buffer);
} }
void lovrMeshDetachAttribute(Mesh* mesh, const char* name) { void lovrMeshDetachAttribute(Mesh* mesh, const char* name) {
MeshAttachment* attachment = map_get(&mesh->attachments, name); MeshAttribute* attribute = map_get(&mesh->attributes, name);
lovrAssert(attachment, "No attached attribute '%s' was found", name); lovrAssert(attribute, "No attached attribute '%s' was found", name);
lovrAssert(attachment->buffer != mesh->vbo, "Attribute '%s' was not attached from another Mesh", name); lovrAssert(attribute->buffer != mesh->vbo, "Attribute '%s' was not attached from another Mesh", name);
lovrRelease(attachment->buffer); lovrRelease(attribute->buffer);
map_remove(&mesh->attachments, name); map_remove(&mesh->attributes, name);
}
MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, const char* name) {
return map_get(&mesh->attributes, name);
} }
void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) { void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) {
const char* key; const char* key;
map_iter_t iter = map_iter(&mesh->attachments); map_iter_t iter = map_iter(&mesh->attachments);
MeshAttachment layout[MAX_ATTACHMENTS]; MeshAttribute layout[MAX_ATTRIBUTES];
memset(layout, 0, MAX_ATTACHMENTS * sizeof(MeshAttachment)); memset(layout, 0, MAX_ATTRIBUTES * sizeof(MeshAttribute));
lovrGpuBindVertexArray(mesh->vao); lovrGpuBindVertexArray(mesh->vao);
if (mesh->indexCount > 0) { if (mesh->indexCount > 0) {
lovrGpuBindIndexBuffer(mesh->ibo->id); lovrGpuBindIndexBuffer(mesh->ibo->id);
} }
while ((key = map_next(&mesh->attachments, &iter)) != NULL) { while ((key = map_next(&mesh->attributes, &iter)) != NULL) {
int location = lovrShaderGetAttributeId(shader, key); int location = lovrShaderGetAttributeId(shader, key);
if (location >= 0) { if (location >= 0) {
MeshAttachment* attachment = map_get(&mesh->attachments, key); MeshAttribute* attribute = map_get(&mesh->attributes, key);
layout[location] = *attachment; layout[location] = *attribute;
} }
} }
for (int i = 0; i < MAX_ATTACHMENTS; i++) { for (int i = 0; i < MAX_ATTRIBUTES; i++) {
MeshAttachment previous = mesh->layout[i]; MeshAttribute previous = mesh->layout[i];
MeshAttachment current = layout[i]; MeshAttribute current = layout[i];
if (!memcmp(&previous, &current, sizeof(MeshAttachment))) { if (!memcmp(&previous, &current, sizeof(MeshAttribute))) {
continue; continue;
} }
@ -2400,7 +2386,7 @@ void lovrMeshBind(Mesh* mesh, Shader* shader, int divisorMultiplier) {
} }
} }
memcpy(mesh->layout, layout, MAX_ATTACHMENTS * sizeof(MeshAttachment)); memcpy(mesh->layout, layout, MAX_ATTRIBUTES * sizeof(MeshAttribute));
} }
void lovrMeshDraw(Mesh* mesh, int instances) { void lovrMeshDraw(Mesh* mesh, int instances) {
@ -2448,15 +2434,15 @@ int lovrMeshGetVertexCount(Mesh* mesh) {
} }
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) { bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) {
MeshAttachment* attachment = map_get(&mesh->attachments, name); MeshAttribute* attribute = map_get(&mesh->attributes, name);
lovrAssert(attachment, "Mesh does not have an attribute named '%s'", name); lovrAssert(attribute, "Mesh does not have an attribute named '%s'", name);
return attachment->enabled; return attribute->enabled;
} }
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enable) { void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enable) {
MeshAttachment* attachment = map_get(&mesh->attachments, name); MeshAttribute* attribute = map_get(&mesh->attributes, name);
lovrAssert(attachment, "Mesh does not have an attribute named '%s'", name); lovrAssert(attribute, "Mesh does not have an attribute named '%s'", name);
attachment->enabled = enable; attribute->enabled = enable;
} }
void lovrMeshGetDrawRange(Mesh* mesh, uint32_t* start, uint32_t* count) { void lovrMeshGetDrawRange(Mesh* mesh, uint32_t* start, uint32_t* count) {