From 40cbb18346fb2a2b56d5cf77583f359214ecd34f Mon Sep 17 00:00:00 2001 From: bjorn Date: Sat, 9 Jul 2022 16:38:25 -0700 Subject: [PATCH] Ugly Pass:capsule; --- src/api/l_graphics_pass.c | 32 +++++++----- src/modules/graphics/graphics.c | 87 +++++++++++++++++++++++++++++++++ src/modules/graphics/graphics.h | 1 + 3 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/api/l_graphics_pass.c b/src/api/l_graphics_pass.c index 9cd4a7fa..5c3b363b 100644 --- a/src/api/l_graphics_pass.c +++ b/src/api/l_graphics_pass.c @@ -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 }, diff --git a/src/modules/graphics/graphics.c b/src/modules/graphics/graphics.c index f4f4278f..2dead0b0 100644 --- a/src/modules/graphics/graphics.c +++ b/src/modules/graphics/graphics.c @@ -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); diff --git a/src/modules/graphics/graphics.h b/src/modules/graphics/graphics.h index 1d19fe55..e746ea27 100644 --- a/src/modules/graphics/graphics.h +++ b/src/modules/graphics/graphics.h @@ -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);