mirror of https://github.com/bjornbytes/lovr.git
Compare commits
2 Commits
b0c1dd5f12
...
159352770f
Author | SHA1 | Date |
---|---|---|
bjorn | 159352770f | |
bjorn | 40cbb18346 |
|
@ -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) {
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue