mirror of https://github.com/bjornbytes/lovr.git
Refactor Mesh attributes;
This commit is contained in:
parent
40454d1380
commit
7f333ce956
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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, ¤t, sizeof(MeshAttachment))) {
|
if (!memcmp(&previous, ¤t, 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) {
|
||||||
|
|
Loading…
Reference in New Issue