mirror of https://github.com/bjornbytes/lovr.git
Opaque Mesh; Opaque OpenGL;
This commit is contained in:
parent
aabb8cb830
commit
f8b8d427d7
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in New Issue