Opaque Mesh; Opaque OpenGL;

This commit is contained in:
bjorn 2020-02-22 23:18:54 -08:00
parent aabb8cb830
commit f8b8d427d7
6 changed files with 218 additions and 205 deletions

View File

@ -12,20 +12,22 @@ static int l_lovrMeshAttachAttributes(lua_State* L) {
Mesh* other = luax_checktype(L, 2, Mesh);
int instanceDivisor = luaL_optinteger(L, 3, 0);
if (lua_isnoneornil(L, 4)) {
for (uint32_t i = 0; i < other->attributeCount; i++) {
MeshAttribute attachment = other->attributes[i];
if (attachment.buffer != other->vertexBuffer) {
uint32_t count = lovrMeshGetAttributeCount(other);
for (uint32_t i = 0; i < count; i++) {
MeshAttribute attachment = *lovrMeshGetAttribute(other, i);
if (attachment.buffer != lovrMeshGetVertexBuffer(other)) {
break;
}
attachment.divisor = instanceDivisor;
lovrMeshAttachAttribute(mesh, other->attributeNames[i], &attachment);
lovrMeshAttachAttribute(mesh, lovrMeshGetAttributeName(other, i), &attachment);
}
} else if (lua_istable(L, 4)) {
int length = luax_len(L, 4);
for (int i = 0; i < length; i++) {
lua_rawgeti(L, 4, i + 1);
const char* name = lua_tostring(L, -1);
const MeshAttribute* attribute = lovrMeshGetAttribute(other, name);
uint32_t index = lovrMeshGetAttributeIndex(other, name);
const MeshAttribute* attribute = lovrMeshGetAttribute(other, index);
lovrAssert(attribute, "Tried to attach non-existent attribute %s", name);
MeshAttribute attachment = *attribute;
attachment.divisor = instanceDivisor;
@ -36,7 +38,8 @@ static int l_lovrMeshAttachAttributes(lua_State* L) {
int top = lua_gettop(L);
for (int i = 4; i <= top; i++) {
const char* name = lua_tostring(L, i);
const MeshAttribute* attribute = lovrMeshGetAttribute(other, name);
uint32_t index = lovrMeshGetAttributeIndex(other, name);
const MeshAttribute* attribute = lovrMeshGetAttribute(other, index);
lovrAssert(attribute, "Tried to attach non-existent attribute %s", name);
MeshAttribute attachment = *attribute;
attachment.divisor = instanceDivisor;
@ -51,12 +54,13 @@ static int l_lovrMeshDetachAttributes(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
if (lua_isuserdata(L, 2)) {
Mesh* other = luax_checktype(L, 2, Mesh);
for (uint32_t i = 0; i < other->attributeCount; i++) {
const MeshAttribute* attachment = &other->attributes[i];
if (attachment->buffer != other->vertexBuffer) {
uint32_t count = lovrMeshGetAttributeCount(other);
for (uint32_t i = 0; i < count; i++) {
const MeshAttribute* attachment = lovrMeshGetAttribute(other, i);
if (attachment->buffer != lovrMeshGetVertexBuffer(other)) {
break;
}
lovrMeshDetachAttribute(mesh, other->attributeNames[i]);
lovrMeshDetachAttribute(mesh, lovrMeshGetAttributeName(other, i));
}
} else if (lua_istable(L, 2)) {
int length = luax_len(L, 2);
@ -98,14 +102,15 @@ static int l_lovrMeshSetDrawMode(lua_State* L) {
static int l_lovrMeshGetVertexFormat(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
lua_createtable(L, mesh->attributeCount, 0);
for (uint32_t i = 0; i < mesh->attributeCount; i++) {
const MeshAttribute* attribute = &mesh->attributes[i];
if (attribute->buffer != mesh->vertexBuffer) {
uint32_t attributeCount = lovrMeshGetAttributeCount(mesh);
lua_createtable(L, attributeCount, 0);
for (uint32_t i = 0; i < attributeCount; i++) {
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, i);
if (attribute->buffer != lovrMeshGetVertexBuffer(mesh)) {
break;
}
lua_createtable(L, 3, 0);
lua_pushstring(L, mesh->attributeNames[i]);
lua_pushstring(L, lovrMeshGetAttributeName(mesh, i));
lua_rawseti(L, -2, 1);
luax_pushenum(L, AttributeTypes, attribute->type);
lua_rawseti(L, -2, 2);
@ -125,18 +130,21 @@ static int l_lovrMeshGetVertexCount(lua_State* L) {
static int l_lovrMeshGetVertex(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
int index = luaL_checkinteger(L, 2) - 1;
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
uint32_t attributeCount = lovrMeshGetAttributeCount(mesh);
const MeshAttribute* firstAttribute = lovrMeshGetAttribute(mesh, 0);
if (!mesh->vertexBuffer || mesh->attributeCount == 0 || mesh->attributes[0].buffer != mesh->vertexBuffer) {
if (!buffer || attributeCount == 0 || firstAttribute->buffer != buffer) {
lovrThrow("Mesh does not have a vertex buffer");
}
lovrAssert(lovrBufferIsReadable(mesh->vertexBuffer), "Mesh:getVertex can only be used if the Mesh was created with the readable flag");
AttributeData data = { .raw = lovrBufferMap(mesh->vertexBuffer, index * mesh->attributes[0].stride) };
lovrAssert(lovrBufferIsReadable(buffer), "Mesh:getVertex can only be used if the Mesh was created with the readable flag");
AttributeData data = { .raw = lovrBufferMap(buffer, index * firstAttribute->stride) };
int components = 0;
for (uint32_t i = 0; i < mesh->attributeCount; i++) {
const MeshAttribute* attribute = &mesh->attributes[i];
if (attribute->buffer != mesh->vertexBuffer) {
for (uint32_t i = 0; i < attributeCount; i++) {
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, i);
if (attribute->buffer != buffer) {
break;
}
for (unsigned j = 0; j < attribute->components; j++, components++) {
@ -156,20 +164,23 @@ static int l_lovrMeshGetVertex(lua_State* L) {
static int l_lovrMeshSetVertex(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
uint32_t index = luaL_checkinteger(L, 2) - 1;
lovrAssert(index < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex index: %d", index + 1);
bool table = lua_istable(L, 3);
uint32_t attributeCount = lovrMeshGetAttributeCount(mesh);
const MeshAttribute* firstAttribute = lovrMeshGetAttribute(mesh, 0);
if (!mesh->vertexBuffer || mesh->attributeCount == 0 || mesh->attributes[0].buffer != mesh->vertexBuffer) {
if (!buffer || attributeCount == 0 || firstAttribute->buffer != buffer) {
lovrThrow("Mesh does not have a vertex buffer");
}
size_t stride = mesh->attributes[0].stride;
AttributeData data = { .raw = lovrBufferMap(mesh->vertexBuffer, index * stride) };
size_t stride = firstAttribute->stride;
AttributeData data = { .raw = lovrBufferMap(buffer, index * stride) };
int component = 0;
for (uint32_t i = 0; i < mesh->attributeCount; i++) {
const MeshAttribute* attribute = &mesh->attributes[i];
if (attribute->buffer != mesh->vertexBuffer) {
for (uint32_t i = 0; i < attributeCount; i++) {
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, i);
if (attribute->buffer != buffer) {
break;
}
@ -195,7 +206,7 @@ static int l_lovrMeshSetVertex(lua_State* L) {
}
}
}
lovrBufferFlush(mesh->vertexBuffer, index * stride, stride);
lovrBufferFlush(buffer, index * stride, stride);
return 0;
}
@ -206,9 +217,8 @@ static int l_lovrMeshGetVertexAttribute(lua_State* L) {
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
lovrAssert(lovrBufferIsReadable(buffer), "Mesh:getVertex can only be used if the Mesh was created with the readable flag");
lovrAssert(vertexIndex < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex: %d", vertexIndex + 1);
lovrAssert(attributeIndex < mesh->attributeCount, "Invalid mesh attribute: %d", attributeIndex + 1);
lovrAssert(mesh->attributes[attributeIndex].buffer == mesh->vertexBuffer, "Invalid mesh attribute: %d", attributeIndex + 1);
MeshAttribute* attribute = &mesh->attributes[attributeIndex];
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, attributeIndex);
lovrAssert(attribute && attribute->buffer == buffer, "Invalid mesh attribute: %d", attributeIndex + 1);
AttributeData data = { .raw = lovrBufferMap(buffer, vertexIndex * attribute->stride + attribute->offset) };
for (unsigned i = 0; i < attribute->components; i++) {
switch (attribute->type) {
@ -226,14 +236,14 @@ static int l_lovrMeshGetVertexAttribute(lua_State* L) {
static int l_lovrMeshSetVertexAttribute(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
uint32_t vertexIndex = luaL_checkinteger(L, 2) - 1;
uint32_t attributeIndex = luaL_checkinteger(L, 3) - 1;
bool table = lua_istable(L, 4);
lovrAssert(vertexIndex < lovrMeshGetVertexCount(mesh), "Invalid mesh vertex: %d", vertexIndex + 1);
lovrAssert(attributeIndex < mesh->attributeCount, "Invalid mesh attribute: %d", attributeIndex + 1);
lovrAssert(mesh->attributes[attributeIndex].buffer == mesh->vertexBuffer, "Invalid mesh attribute: %d", attributeIndex + 1);
MeshAttribute* attribute = &mesh->attributes[attributeIndex];
AttributeData data = { .raw = lovrBufferMap(mesh->vertexBuffer, vertexIndex * attribute->stride + attribute->offset) };
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, attributeIndex);
lovrAssert(attribute && attribute->buffer == buffer, "Invalid mesh attribute: %d", attributeIndex + 1);
AttributeData data = { .raw = lovrBufferMap(buffer, vertexIndex * attribute->stride + attribute->offset) };
for (unsigned i = 0; i < attribute->components; i++) {
int index = 4 + i;
if (table) {
@ -265,29 +275,32 @@ static int l_lovrMeshSetVertexAttribute(lua_State* L) {
case U32: attributeSize = attribute->components * sizeof(uint32_t); break;
case F32: attributeSize = attribute->components * sizeof(float); break;
}
lovrBufferFlush(mesh->vertexBuffer, vertexIndex * attribute->stride + attribute->offset, attributeSize);
lovrBufferFlush(buffer, vertexIndex * attribute->stride + attribute->offset, attributeSize);
return 0;
}
static int l_lovrMeshSetVertices(lua_State* L) {
Mesh* mesh = luax_checktype(L, 1, Mesh);
Buffer* buffer = lovrMeshGetVertexBuffer(mesh);
uint32_t attributeCount = lovrMeshGetAttributeCount(mesh);
const MeshAttribute* firstAttribute = lovrMeshGetAttribute(mesh, 0);
if (!mesh->vertexBuffer || mesh->attributeCount == 0 || mesh->attributes[0].buffer != mesh->vertexBuffer) {
if (!buffer || attributeCount == 0 || firstAttribute->buffer != buffer) {
lovrThrow("Mesh:setVertices does not work when the Mesh does not have a vertex buffer");
}
uint32_t capacity = lovrMeshGetVertexCount(mesh);
uint32_t start = luaL_optinteger(L, 3, 1) - 1;
uint32_t count = luaL_optinteger(L, 4, capacity - start);
size_t stride = mesh->attributes[0].stride;
size_t stride = firstAttribute->stride;
Blob* blob = luax_totype(L, 2, Blob);
if (blob) {
count = MIN(count, blob->size / stride);
lovrAssert(start + count <= capacity, "Overflow in Mesh:setVertices: Mesh can only hold %d vertices", capacity);
void* data = lovrBufferMap(mesh->vertexBuffer, start * stride);
void* data = lovrBufferMap(buffer, start * stride);
memcpy(data, blob->data, count * stride);
lovrBufferFlush(mesh->vertexBuffer, start * stride, count * stride);
lovrBufferFlush(buffer, start * stride, count * stride);
return 0;
}
@ -295,15 +308,15 @@ static int l_lovrMeshSetVertices(lua_State* L) {
count = MIN(count, lua_objlen(L, 2));
lovrAssert(start + count <= capacity, "Overflow in Mesh:setVertices: Mesh can only hold %d vertices", capacity);
AttributeData data = { .raw = lovrBufferMap(mesh->vertexBuffer, start * stride) };
AttributeData data = { .raw = lovrBufferMap(buffer, start * stride) };
for (uint32_t i = 0; i < count; i++) {
lua_rawgeti(L, 2, i + 1);
luaL_checktype(L, -1, LUA_TTABLE);
int component = 0;
for (uint32_t j = 0; j < mesh->attributeCount; j++) {
const MeshAttribute* attribute = &mesh->attributes[j];
if (attribute->buffer != mesh->vertexBuffer) {
for (uint32_t j = 0; j < attributeCount; j++) {
const MeshAttribute* attribute = lovrMeshGetAttribute(mesh, i);
if (attribute->buffer != buffer) {
break;
}
@ -326,7 +339,7 @@ static int l_lovrMeshSetVertices(lua_State* L) {
lua_pop(L, 1);
}
lovrBufferFlush(mesh->vertexBuffer, start * stride, count * stride);
lovrBufferFlush(buffer, start * stride, count * stride);
return 0;
}

View File

@ -1,115 +0,0 @@
#include "graphics/mesh.h"
#include "graphics/buffer.h"
#include "graphics/graphics.h"
#include "graphics/material.h"
#include "core/hash.h"
#include "core/ref.h"
#include <stdlib.h>
Buffer* lovrMeshGetVertexBuffer(Mesh* mesh) {
return mesh->vertexBuffer;
}
Buffer* lovrMeshGetIndexBuffer(Mesh* mesh) {
return mesh->indexBuffer;
}
uint32_t lovrMeshGetVertexCount(Mesh* mesh) {
return mesh->vertexCount;
}
uint32_t lovrMeshGetIndexCount(Mesh* mesh) {
return mesh->indexCount;
}
size_t lovrMeshGetIndexSize(Mesh* mesh) {
return mesh->indexSize;
}
void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute) {
uint64_t hash = hash64(name, strlen(name));
lovrAssert(map_get(&mesh->attributeMap, hash) == MAP_NIL, "Mesh already has an attribute named '%s'", name);
lovrAssert(mesh->attributeCount < MAX_ATTRIBUTES, "Mesh already has the max number of attributes (%d)", MAX_ATTRIBUTES);
lovrAssert(strlen(name) < MAX_ATTRIBUTE_NAME_LENGTH, "Mesh attribute name '%s' is too long (max is %d)", name, MAX_ATTRIBUTE_NAME_LENGTH);
lovrGraphicsFlushMesh(mesh);
uint64_t index = mesh->attributeCount++;
mesh->attributes[index] = *attribute;
strcpy(mesh->attributeNames[index], name);
map_set(&mesh->attributeMap, hash, index);
lovrRetain(attribute->buffer);
}
void lovrMeshDetachAttribute(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "No attached attribute named '%s' was found", name);
MeshAttribute* attribute = &mesh->attributes[index];
lovrGraphicsFlushMesh(mesh);
lovrRelease(Buffer, attribute->buffer);
map_remove(&mesh->attributeMap, hash);
mesh->attributeNames[index][0] = '\0';
memmove(mesh->attributeNames + index, mesh->attributeNames + index + 1, (mesh->attributeCount - index - 1) * MAX_ATTRIBUTE_NAME_LENGTH * sizeof(char));
memmove(mesh->attributes + index, mesh->attributes + index + 1, (mesh->attributeCount - index - 1) * sizeof(MeshAttribute));
mesh->attributeCount--;
for (uint32_t i = 0; i < MAX_ATTRIBUTES; i++) {
if (mesh->locations[i] > index) {
mesh->locations[i]--;
} else if (mesh->locations[i] == index) {
mesh->locations[i] = 0xff;
}
}
}
const MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
return index == MAP_NIL ? NULL : &mesh->attributes[index];
}
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "Mesh does not have an attribute named '%s'", name);
return !mesh->attributes[index].disabled;
}
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enable) {
bool disable = !enable;
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "Mesh does not have an attribute named '%s'", name);
if (mesh->attributes[index].disabled != disable) {
lovrGraphicsFlushMesh(mesh);
mesh->attributes[index].disabled = disable;
}
}
DrawMode lovrMeshGetDrawMode(Mesh* mesh) {
return mesh->mode;
}
void lovrMeshSetDrawMode(Mesh* mesh, DrawMode mode) {
mesh->mode = mode;
}
void lovrMeshGetDrawRange(Mesh* mesh, uint32_t* start, uint32_t* count) {
*start = mesh->drawStart;
*count = mesh->drawCount;
}
void lovrMeshSetDrawRange(Mesh* mesh, uint32_t start, uint32_t count) {
uint32_t limit = mesh->indexSize > 0 ? mesh->indexCount : mesh->vertexCount;
lovrAssert(start + count <= limit, "Invalid mesh draw range [%d, %d]", start + 1, start + count + 1);
mesh->drawStart = start;
mesh->drawCount = count;
}
Material* lovrMeshGetMaterial(Mesh* mesh) {
return mesh->material;
}
void lovrMeshSetMaterial(Mesh* mesh, Material* material) {
lovrRetain(material);
lovrRelease(Material, mesh->material);
mesh->material = material;
}

View File

@ -1,6 +1,4 @@
#include "data/modelData.h"
#include "graphics/opengl.h"
#include "core/map.h"
#include <stdbool.h>
#pragma once
@ -23,29 +21,8 @@ typedef struct {
unsigned disabled : 1;
} MeshAttribute;
typedef struct Mesh {
DrawMode mode;
char attributeNames[MAX_ATTRIBUTES][MAX_ATTRIBUTE_NAME_LENGTH];
MeshAttribute attributes[MAX_ATTRIBUTES];
uint8_t locations[MAX_ATTRIBUTES];
uint16_t enabledLocations;
uint16_t divisors[MAX_ATTRIBUTES];
map_t attributeMap;
uint32_t attributeCount;
struct Buffer* vertexBuffer;
struct Buffer* indexBuffer;
uint32_t vertexCount;
uint32_t indexCount;
size_t indexSize;
size_t indexOffset;
uint32_t drawStart;
uint32_t drawCount;
struct Material* material;
GPU_MESH_FIELDS
} Mesh;
Mesh* lovrMeshInit(Mesh* mesh, DrawMode mode, struct Buffer* vertexBuffer, uint32_t vertexCount);
#define lovrMeshCreate(...) lovrMeshInit(lovrAlloc(Mesh), __VA_ARGS__)
typedef struct Mesh Mesh;
Mesh* lovrMeshCreate(DrawMode mode, struct Buffer* vertexBuffer, uint32_t vertexCount);
void lovrMeshDestroy(void* ref);
struct Buffer* lovrMeshGetVertexBuffer(Mesh* mesh);
struct Buffer* lovrMeshGetIndexBuffer(Mesh* mesh);
@ -53,9 +30,12 @@ void lovrMeshSetIndexBuffer(Mesh* mesh, struct Buffer* buffer, uint32_t indexCou
uint32_t lovrMeshGetVertexCount(Mesh* mesh);
uint32_t lovrMeshGetIndexCount(Mesh* mesh);
size_t lovrMeshGetIndexSize(Mesh* mesh);
uint32_t lovrMeshGetAttributeCount(Mesh* mesh);
void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute);
void lovrMeshDetachAttribute(Mesh* mesh, const char* name);
const MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, const char* name);
const MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, uint32_t index);
uint32_t lovrMeshGetAttributeIndex(Mesh* mesh, const char* name);
const char* lovrMeshGetAttributeName(Mesh* mesh, uint32_t index);
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name);
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enabled);
DrawMode lovrMeshGetDrawMode(Mesh* mesh);

View File

@ -1,4 +1,3 @@
#include "graphics/opengl.h"
#include "graphics/graphics.h"
#include "graphics/buffer.h"
#include "graphics/canvas.h"
@ -17,6 +16,15 @@
#include <stdlib.h>
#include <stdio.h>
#ifdef LOVR_WEBGL
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include <GL/gl.h>
#include <GL/glext.h>
#else
#include "lib/glad/glad.h"
#endif
// Types
#define MAX_TEXTURES 16
@ -99,6 +107,28 @@ struct Shader {
bool multiview;
};
struct Mesh {
uint32_t vao;
uint32_t ibo;
DrawMode mode;
char attributeNames[MAX_ATTRIBUTES][MAX_ATTRIBUTE_NAME_LENGTH];
MeshAttribute attributes[MAX_ATTRIBUTES];
uint8_t locations[MAX_ATTRIBUTES];
uint16_t enabledLocations;
uint16_t divisors[MAX_ATTRIBUTES];
map_t attributeMap;
uint32_t attributeCount;
struct Buffer* vertexBuffer;
struct Buffer* indexBuffer;
uint32_t vertexCount;
uint32_t indexCount;
size_t indexSize;
size_t indexOffset;
uint32_t drawStart;
uint32_t drawCount;
struct Material* material;
};
typedef enum {
BARRIER_BLOCK,
BARRIER_UNIFORM_TEXTURE,
@ -2797,7 +2827,8 @@ Buffer* lovrShaderBlockGetBuffer(ShaderBlock* block) {
// Mesh
Mesh* lovrMeshInit(Mesh* mesh, DrawMode mode, Buffer* vertexBuffer, uint32_t vertexCount) {
Mesh* lovrMeshCreate(DrawMode mode, Buffer* vertexBuffer, uint32_t vertexCount) {
Mesh* mesh = lovrAlloc(Mesh);
mesh->mode = mode;
mesh->vertexBuffer = vertexBuffer;
mesh->vertexCount = vertexCount;
@ -2832,3 +2863,123 @@ void lovrMeshSetIndexBuffer(Mesh* mesh, Buffer* buffer, uint32_t indexCount, siz
mesh->indexOffset = offset;
}
}
Buffer* lovrMeshGetVertexBuffer(Mesh* mesh) {
return mesh->vertexBuffer;
}
Buffer* lovrMeshGetIndexBuffer(Mesh* mesh) {
return mesh->indexBuffer;
}
uint32_t lovrMeshGetVertexCount(Mesh* mesh) {
return mesh->vertexCount;
}
uint32_t lovrMeshGetIndexCount(Mesh* mesh) {
return mesh->indexCount;
}
size_t lovrMeshGetIndexSize(Mesh* mesh) {
return mesh->indexSize;
}
uint32_t lovrMeshGetAttributeCount(Mesh* mesh) {
return mesh->attributeCount;
}
void lovrMeshAttachAttribute(Mesh* mesh, const char* name, MeshAttribute* attribute) {
uint64_t hash = hash64(name, strlen(name));
lovrAssert(map_get(&mesh->attributeMap, hash) == MAP_NIL, "Mesh already has an attribute named '%s'", name);
lovrAssert(mesh->attributeCount < MAX_ATTRIBUTES, "Mesh already has the max number of attributes (%d)", MAX_ATTRIBUTES);
lovrAssert(strlen(name) < MAX_ATTRIBUTE_NAME_LENGTH, "Mesh attribute name '%s' is too long (max is %d)", name, MAX_ATTRIBUTE_NAME_LENGTH);
lovrGraphicsFlushMesh(mesh);
uint64_t index = mesh->attributeCount++;
mesh->attributes[index] = *attribute;
strcpy(mesh->attributeNames[index], name);
map_set(&mesh->attributeMap, hash, index);
lovrRetain(attribute->buffer);
}
void lovrMeshDetachAttribute(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "No attached attribute named '%s' was found", name);
MeshAttribute* attribute = &mesh->attributes[index];
lovrGraphicsFlushMesh(mesh);
lovrRelease(Buffer, attribute->buffer);
map_remove(&mesh->attributeMap, hash);
mesh->attributeNames[index][0] = '\0';
memmove(mesh->attributeNames + index, mesh->attributeNames + index + 1, (mesh->attributeCount - index - 1) * MAX_ATTRIBUTE_NAME_LENGTH * sizeof(char));
memmove(mesh->attributes + index, mesh->attributes + index + 1, (mesh->attributeCount - index - 1) * sizeof(MeshAttribute));
mesh->attributeCount--;
for (uint32_t i = 0; i < MAX_ATTRIBUTES; i++) {
if (mesh->locations[i] > index) {
mesh->locations[i]--;
} else if (mesh->locations[i] == index) {
mesh->locations[i] = 0xff;
}
}
}
const MeshAttribute* lovrMeshGetAttribute(Mesh* mesh, uint32_t index) {
return index < mesh->attributeCount ? &mesh->attributes[index] : NULL;
}
uint32_t lovrMeshGetAttributeIndex(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
return index == MAP_NIL ? ~0u : index;
}
const char* lovrMeshGetAttributeName(Mesh* mesh, uint32_t index) {
return mesh->attributeNames[index];
}
bool lovrMeshIsAttributeEnabled(Mesh* mesh, const char* name) {
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "Mesh does not have an attribute named '%s'", name);
return !mesh->attributes[index].disabled;
}
void lovrMeshSetAttributeEnabled(Mesh* mesh, const char* name, bool enable) {
bool disable = !enable;
uint64_t hash = hash64(name, strlen(name));
uint64_t index = map_get(&mesh->attributeMap, hash);
lovrAssert(index != MAP_NIL, "Mesh does not have an attribute named '%s'", name);
if (mesh->attributes[index].disabled != disable) {
lovrGraphicsFlushMesh(mesh);
mesh->attributes[index].disabled = disable;
}
}
DrawMode lovrMeshGetDrawMode(Mesh* mesh) {
return mesh->mode;
}
void lovrMeshSetDrawMode(Mesh* mesh, DrawMode mode) {
mesh->mode = mode;
}
void lovrMeshGetDrawRange(Mesh* mesh, uint32_t* start, uint32_t* count) {
*start = mesh->drawStart;
*count = mesh->drawCount;
}
void lovrMeshSetDrawRange(Mesh* mesh, uint32_t start, uint32_t count) {
uint32_t limit = mesh->indexSize > 0 ? mesh->indexCount : mesh->vertexCount;
lovrAssert(start + count <= limit, "Invalid mesh draw range [%d, %d]", start + 1, start + count + 1);
mesh->drawStart = start;
mesh->drawCount = count;
}
Material* lovrMeshGetMaterial(Mesh* mesh) {
return mesh->material;
}
void lovrMeshSetMaterial(Mesh* mesh, Material* material) {
lovrRetain(material);
lovrRelease(Material, mesh->material);
mesh->material = material;
}

View File

@ -1,16 +0,0 @@
#ifdef LOVR_WEBGL
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include <GL/gl.h>
#include <GL/glext.h>
#else
#include "lib/glad/glad.h"
#endif
#include <stdint.h>
#pragma once
#define GPU_MESH_FIELDS \
uint32_t vao; \
uint32_t ibo;

View File

@ -4,7 +4,6 @@
#include "graphics/graphics.h"
#include "graphics/canvas.h"
#include "graphics/texture.h"
#include "graphics/opengl.h"
#include "core/ref.h"
#include "core/util.h"
#include <math.h>
@ -14,6 +13,7 @@
#endif
#define XR_USE_GRAPHICS_API_OPENGL
#define GL_SRGB8_ALPHA8 0x8C43
#include <openxr/openxr.h>
#include <openxr/openxr_platform.h>