Compare commits

...

2 Commits

Author SHA1 Message Date
bjorn 159352770f Model:getTriangles;
Doesn't 100% work, Buffers are kind of a mess, ugh.
2022-07-09 18:30:36 -07:00
bjorn 40cbb18346 Ugly Pass:capsule; 2022-07-09 16:38:25 -07:00
7 changed files with 242 additions and 26 deletions

View File

@ -759,7 +759,7 @@ static int l_lovrGraphicsNewBuffer(lua_State* L) {
switch (lua_type(L, 1)) {
case LUA_TNUMBER: info.length = lua_tointeger(L, 1); break;
case LUA_TTABLE: info.length = luax_len(L, -1); break;
case LUA_TTABLE: info.length = luax_len(L, 1); break;
default: {
Blob* blob = luax_totype(L, 1, Blob);
if (blob) {

View File

@ -117,17 +117,18 @@ static int l_lovrModelGetIndexBuffer(lua_State* L) {
return 1;
}
/*
static int l_lovrModelGetTriangles(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
ModelData* data = lovrModelGetInfo(model)->data;
float* vertices = NULL;
uint32_t* indices = NULL;
uint32_t vertexCount;
uint32_t indexCount;
lovrModelGetTriangles(model, &vertices, &vertexCount, &indices, &indexCount);
uint32_t vertexCount = 0;
uint32_t indexCount = 0;
lovrModelDataGetTriangles(data, &vertices, &indices, &vertexCount, &indexCount);
lua_createtable(L, vertexCount * 3, 0);
for (uint32_t i = 0; i < vertexCount; i++) {
for (uint32_t i = 0; i < vertexCount * 3; i++) {
lua_pushnumber(L, vertices[i]);
lua_rawseti(L, -2, i + 1);
}
@ -143,18 +144,21 @@ static int l_lovrModelGetTriangles(lua_State* L) {
static int l_lovrModelGetTriangleCount(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t count = lovrModelGetTriangleCount(model);
lua_pushinteger(L, count);
ModelData* data = lovrModelGetInfo(model)->data;
uint32_t vertexCount, indexCount;
lovrModelDataGetTriangles(data, NULL, NULL, &vertexCount, &indexCount);
lua_pushinteger(L, indexCount / 3);
return 1;
}
static int l_lovrModelGetVertexCount(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
uint32_t count = lovrModelGetVertexCount(model);
lua_pushinteger(L, count);
ModelData* data = lovrModelGetInfo(model)->data;
uint32_t vertexCount, indexCount;
lovrModelDataGetTriangles(data, NULL, NULL, &vertexCount, &indexCount);
lua_pushinteger(L, vertexCount);
return 1;
}
*/
static int l_lovrModelGetWidth(lua_State* L) {
Model* model = luax_checktype(L, 1, Model);
@ -241,9 +245,9 @@ const luaL_Reg lovrModel[] = {
{ "getMaterial", l_lovrModelGetMaterial },
{ "getVertexBuffer", l_lovrModelGetVertexBuffer },
{ "getIndexBuffer", l_lovrModelGetIndexBuffer },
/*{ "getTriangles", l_lovrModelGetTriangles },
{ "getTriangles", l_lovrModelGetTriangles },
{ "getTriangleCount", l_lovrModelGetTriangleCount },
{ "getVertexCount", l_lovrModelGetVertexCount },*/
{ "getVertexCount", l_lovrModelGetVertexCount },
{ "getWidth", l_lovrModelGetWidth },
{ "getHeight", l_lovrModelGetHeight },
{ "getDepth", l_lovrModelGetDepth },

View File

@ -529,16 +529,6 @@ static int l_lovrPassSphere(lua_State* L) {
return 0;
}
static int l_lovrPassTorus(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
float transform[16];
int index = luax_readmat4(L, 2, transform, -2);
uint32_t segmentsT = luax_optu32(L, index++, 64);
uint32_t segmentsP = luax_optu32(L, index++, 32);
lovrPassTorus(pass, transform, segmentsT, segmentsP);
return 0;
}
static int l_lovrPassCylinder(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
float transform[16];
@ -552,6 +542,25 @@ static int l_lovrPassCylinder(lua_State* L) {
return 0;
}
static int l_lovrPassCapsule(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
float transform[16];
int index = luax_readmat4(L, 2, transform, -2);
uint32_t segments = luax_optu32(L, index, 32);
lovrPassCapsule(pass, transform, segments);
return 0;
}
static int l_lovrPassTorus(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
float transform[16];
int index = luax_readmat4(L, 2, transform, -2);
uint32_t segmentsT = luax_optu32(L, index++, 64);
uint32_t segmentsP = luax_optu32(L, index++, 32);
lovrPassTorus(pass, transform, segmentsT, segmentsP);
return 0;
}
static int l_lovrPassText(lua_State* L) {
Pass* pass = luax_checktype(L, 1, Pass);
Font* font = luax_totype(L, 2, Font);
@ -868,8 +877,9 @@ const luaL_Reg lovrPass[] = {
{ "box", l_lovrPassBox },
{ "circle", l_lovrPassCircle },
{ "sphere", l_lovrPassSphere },
{ "torus", l_lovrPassTorus },
{ "cylinder", l_lovrPassCylinder },
{ "capsule", l_lovrPassCapsule },
{ "torus", l_lovrPassTorus },
{ "text", l_lovrPassText },
{ "skybox", l_lovrPassSkybox },
{ "fill", l_lovrPassFill },

View File

@ -103,6 +103,8 @@ void lovrModelDataDestroy(void* ref) {
map_free(&model->animationMap);
map_free(&model->materialMap);
map_free(&model->nodeMap);
free(model->vertices);
free(model->indices);
free(model->data);
free(model);
}
@ -402,3 +404,105 @@ void lovrModelDataGetBoundingSphere(ModelData* model, float sphere[4]) {
memcpy(sphere, model->boundingSphere, sizeof(model->boundingSphere));
}
static void countVertices(ModelData* model, uint32_t nodeIndex, uint32_t* vertexCount, uint32_t* indexCount) {
ModelNode* node = &model->nodes[nodeIndex];
for (uint32_t i = 0; i < node->primitiveCount; i++) {
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
ModelAttribute* indices = primitive->indices;
uint32_t count = positions ? positions->count : 0;
*vertexCount += count;
*indexCount += indices ? indices->count : count;
}
for (uint32_t i = 0; i < node->childCount; i++) {
countVertices(model, node->children[i], vertexCount, indexCount);
}
}
static void collectVertices(ModelData* model, uint32_t nodeIndex, float** vertices, uint32_t** indices, uint32_t* baseIndex, float* parentTransform) {
ModelNode* node = &model->nodes[nodeIndex];
float m[16];
mat4_init(m, parentTransform);
if (node->matrix) {
mat4_mul(m, node->transform.matrix);
} else {
float* T = node->transform.properties.translation;
float* R = node->transform.properties.rotation;
float* S = node->transform.properties.scale;
mat4_translate(m, T[0], T[1], T[2]);
mat4_rotateQuat(m, R);
mat4_scale(m, S[0], S[1], S[2]);
}
for (uint32_t i = 0; i < node->primitiveCount; i++) {
ModelPrimitive* primitive = &model->primitives[node->primitiveIndex + i];
ModelAttribute* positions = primitive->attributes[ATTR_POSITION];
ModelAttribute* index = primitive->indices;
if (!positions) continue;
char* data = (char*) model->buffers[positions->buffer].data + positions->offset;
size_t stride = positions->stride == 0 ? 3 * sizeof(float) : positions->stride;
for (uint32_t j = 0; j < positions->count; j++) {
float v[4];
memcpy(v, data, 3 * sizeof(float));
mat4_transform(m, v);
memcpy(*vertices, v, 3 * sizeof(float));
*vertices += 3;
data += stride;
}
if (index) {
lovrAssert(index->type == U16 || index->type == U32, "Unreachable");
data = (char*) model->buffers[index->buffer].data + index->offset;
size_t stride = index->stride == 0 ? (index->type == U16 ? 2 : 4) : index->stride;
for (uint32_t j = 0; j < index->count; j++) {
**indices = (index->type == U16 ? ((uint32_t) *(uint16_t*) data) : *(uint32_t*) data) + *baseIndex;
*indices += 1;
data += stride;
}
} else {
for (uint32_t j = 0; j < positions->count; j++) {
**indices = j + *baseIndex;
*indices += 1;
}
}
*baseIndex += positions->count;
}
for (uint32_t i = 0; i < node->childCount; i++) {
collectVertices(model, node->children[i], vertices, indices, baseIndex, m);
}
}
void lovrModelDataGetTriangles(ModelData* model, float** vertices, uint32_t** indices, uint32_t* vertexCount, uint32_t* indexCount) {
if (model->totalVertexCount == 0) {
countVertices(model, model->rootNode, &model->totalVertexCount, &model->totalIndexCount);
}
if (vertices && !model->vertices) {
uint32_t baseIndex = 0;
model->vertices = malloc(model->totalVertexCount * 3 * sizeof(float));
model->indices = malloc(model->totalIndexCount * sizeof(uint32_t));
lovrAssert(model->vertices && model->indices, "Out of memory");
*vertices = model->vertices;
*indices = model->indices;
collectVertices(model, model->rootNode, vertices, indices, &baseIndex, (float[16]) MAT4_IDENTITY);
}
*vertexCount = model->totalVertexCount;
*indexCount = model->totalIndexCount;
if (vertices) {
*vertices = model->vertices;
*indices = model->indices;
}
}

View File

@ -217,6 +217,11 @@ typedef struct ModelData {
float boundingBox[6];
float boundingSphere[4];
float* vertices;
uint32_t* indices;
uint32_t totalVertexCount;
uint32_t totalIndexCount;
map_t animationMap;
map_t materialMap;
map_t nodeMap;
@ -233,3 +238,4 @@ void lovrModelDataAllocate(ModelData* model);
void lovrModelDataCopyAttribute(ModelData* data, ModelAttribute* attribute, char* dst, AttributeType type, uint32_t components, bool normalized, uint32_t count, size_t stride, uint8_t clear);
void lovrModelDataGetBoundingBox(ModelData* data, float box[6]);
void lovrModelDataGetBoundingSphere(ModelData* data, float sphere[4]);
void lovrModelDataGetTriangles(ModelData* data, float** vertices, uint32_t** indices, uint32_t* vertexCount, uint32_t* indexCount);

View File

@ -4018,6 +4018,93 @@ void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, f
}
}
void lovrPassCapsule(Pass* pass, float* transform, uint32_t segments) {
float sx = vec3_length(transform + 0);
float sy = vec3_length(transform + 4);
float sz = vec3_length(transform + 8);
vec3_scale(transform + 0, 1.f / sx);
vec3_scale(transform + 4, 1.f / sy);
vec3_scale(transform + 8, 1.f / sz);
float radius = sx;
float length = sz * .5f;
uint32_t rings = segments / 2;
uint32_t vertexCount = 2 * (1 + rings * (segments + 1));
uint32_t indexCount = 2 * (3 * segments + 6 * segments * (rings - 1)) + 6 * segments;
ShapeVertex* vertices;
uint16_t* indices;
lovrPassDraw(pass, &(Draw) {
.mode = VERTEX_TRIANGLES,
.transform = transform,
.vertex.pointer = (void**) &vertices,
.vertex.count = vertexCount,
.index.pointer = (void**) &indices,
.index.count = indexCount
});
float tip = length + radius;
uint32_t h = vertexCount / 2;
vertices[0] = (ShapeVertex) { { 0.f, 0.f, -tip }, { 0.f, 0.f, -1.f }, { .5f, 0.f } };
vertices[h] = (ShapeVertex) { { 0.f, 0.f, tip }, { 0.f, 0.f, 1.f }, { .5f, 1.f } };
vertices++;
for (uint32_t i = 1; i <= rings; i++) {
float v = i / (float) rings;
float phi = v * (float) M_PI / 2.f;
float sinphi = sinf(phi);
float cosphi = cosf(phi);
for (uint32_t j = 0; j <= segments; j++) {
float u = j / (float) segments;
float theta = u * (float) M_PI * 2.f;
float sintheta = sinf(theta);
float costheta = cosf(theta);
float x = costheta * sinphi;
float y = sintheta * sinphi;
float z = cosphi;
vertices[0] = (ShapeVertex) { { x * radius, y * radius, -(length + z * radius) }, { x, y, -z }, { u, v } };
vertices[h] = (ShapeVertex) { { x * radius, y * radius, (length + z * radius) }, { x, y, z }, { u, 1.f - v } };
vertices++;
}
}
uint16_t* i1 = indices;
uint16_t* i2 = indices + (indexCount - 6 * segments) / 2;
for (uint32_t i = 0; i < segments; i++) {
uint16_t wedge1[] = { 0, 0 + i + 2, 0 + i + 1 };
uint16_t wedge2[] = { h, h + i + 1, h + i + 2 };
memcpy(i1, wedge1, sizeof(wedge1));
memcpy(i2, wedge2, sizeof(wedge2));
i1 += COUNTOF(wedge1);
i2 += COUNTOF(wedge2);
}
for (uint32_t i = 0; i < rings - 1; i++) {
for (uint32_t j = 0; j < segments; j++) {
uint16_t a = 1 + i * (segments + 1) + 0 + j;
uint16_t b = 1 + i * (segments + 1) + 1 + j;
uint16_t c = 1 + i * (segments + 1) + 0 + segments + 1 + j;
uint16_t d = 1 + i * (segments + 1) + 1 + segments + 1 + j;
uint16_t quad1[] = { a, b, c, c, b, d };
uint16_t quad2[] = { h + a, h + c, h + b, h + b, h + c, h + d };
memcpy(i1, quad1, sizeof(quad1));
memcpy(i2, quad2, sizeof(quad2));
i1 += COUNTOF(quad1);
i2 += COUNTOF(quad2);
}
}
for (uint32_t i = 0; i < segments; i++) {
uint16_t a = h - segments - 1 + i;
uint16_t b = h - segments - 1 + i + 1;
uint16_t c = vertexCount - segments - 1 + i;
uint16_t d = vertexCount - segments - 1 + i + 1;
uint16_t quad[] = { a, b, c, c, b, d };
memcpy(i2, quad, sizeof(quad));
i2 += COUNTOF(quad);
}
}
void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t segmentsP) {
float sx = vec3_length(transform + 0);
float sy = vec3_length(transform + 4);
@ -4310,12 +4397,16 @@ void lovrPassDrawModel(Pass* pass, Model* model, float* transform, uint32_t node
void lovrPassMesh(Pass* pass, Buffer* vertices, Buffer* indices, float* transform, uint32_t start, uint32_t count, uint32_t instances) {
if (count == ~0u) {
count = (indices ? indices : vertices)->info.length - start;
if (indices || vertices) {
count = (indices ? indices : vertices)->info.length - start;
} else {
count = 0;
}
}
if (indices) {
lovrCheck(count <= indices->info.length - start, "Mesh draw range exceeds index buffer size");
} else {
} else if (vertices) {
lovrCheck(count <= vertices->info.length - start, "Mesh draw range exceeds vertex buffer size");
}

View File

@ -540,6 +540,7 @@ void lovrPassBox(Pass* pass, float* transform, DrawStyle style);
void lovrPassCircle(Pass* pass, float* transform, DrawStyle style, float angle1, float angle2, uint32_t segments);
void lovrPassSphere(Pass* pass, float* transform, uint32_t segmentsH, uint32_t segmentsV);
void lovrPassCylinder(Pass* pass, float* transform, bool capped, float angle1, float angle2, uint32_t segments);
void lovrPassCapsule(Pass* pass, float* transform, uint32_t segments);
void lovrPassTorus(Pass* pass, float* transform, uint32_t segmentsT, uint32_t segmentsP);
void lovrPassText(Pass* pass, Font* font, ColoredString* strings, uint32_t count, float* transform, float wrap, HorizontalAlign halign, VerticalAlign valign);
void lovrPassSkybox(Pass* pass, Texture* texture);