diff --git a/dev/src/graphics.cpp b/dev/src/graphics.cpp index e860bc31..d78c2654 100644 --- a/dev/src/graphics.cpp +++ b/dev/src/graphics.cpp @@ -1344,13 +1344,16 @@ nfr("light", "pos,params", "F}:3F}:2", "", lights.push_back(l); }); -nfr("render_tiles", "positions,tilecoords,mapsize", "F}:2]I}:2]I}:2", "", - "Renders a list of tiles from a tilemap. Each tile rendered is 1x1 in size." +nfr("render_tiles", "positions,tilecoords,mapsize,sizes,rotations", "F}:2]I}:2]I}:2F]F]", "", + "Renders a list of tiles from a tilemap. Each tile rendered is 0.5 in radius (1x1 square around pos) unless the optional sizes vector is specified (may be empty)." " Positions may be anywhere. tilecoords are indices into the map (0..mapsize-1), mapsize is" - " the amount of tiles in the texture. Tiles may overlap, they are drawn in order." - " Before calling this, make sure to have the texture set and a textured shader", + " the amount of tiles in the texture. rotations are optional (may be empty, faster if not specified). Tiles may overlap, they are drawn in order." + " Before calling this, make sure to have the texture set and a textured shader." + " If you want tile to use top-left as position, wrap this call in gl.translate float2_h:", [](StackPtr &sp, VM &vm) { TestGL(vm); + auto rotations = Pop(sp).vval(); + auto sizes = Pop(sp).vval(); auto msize = float2(PopVec(sp)); auto tile = Pop(sp).vval(); auto pos = Pop(sp).vval(); @@ -1361,12 +1364,24 @@ nfr("render_tiles", "positions,tilecoords,mapsize", "F}:2]I}:2]I}:2", "", for (iint i = 0; i < len; i++) { auto p = ValueToFLT<2>(pos->AtSt(i), pos->width); auto t = float2(ValueToI<2>(tile->AtSt(i), tile->width)) / msize; - vbuf[i * 6 + 0].pos = p; - vbuf[i * 6 + 1].pos = p + float2_y; - vbuf[i * 6 + 2].pos = p + float2_1; - vbuf[i * 6 + 3].pos = p; - vbuf[i * 6 + 4].pos = p + float2_1; - vbuf[i * 6 + 5].pos = p + float2_x; + auto size = i < sizes->len ? sizes->At(i).fltval() : 0.5f; + auto c1 = float2(-size); + auto c2 = float2(-size, size); + auto c3 = float2(size); + auto c4 = float2(size, -size); + if (i < rotations->len) { + auto rot = rotations->At(i).fltval(); + c1 = rotate2(c1, rot * RAD); + c2 = float2(c1.y, -c1.x); + c3 = float2(c2.y, -c2.x); + c4 = float2(c3.y, -c3.x); + } + vbuf[i * 6 + 0].pos = p + c1; + vbuf[i * 6 + 1].pos = p + c2; + vbuf[i * 6 + 2].pos = p + c3; + vbuf[i * 6 + 3].pos = p + c1; + vbuf[i * 6 + 4].pos = p + c3; + vbuf[i * 6 + 5].pos = p + c4; vbuf[i * 6 + 0].tc = t; vbuf[i * 6 + 1].tc = t + float2_y / msize; vbuf[i * 6 + 2].tc = t + float2_1 / msize; diff --git a/dev/src/lobster/geom.h b/dev/src/lobster/geom.h index c27c479d..788c10e0 100644 --- a/dev/src/lobster/geom.h +++ b/dev/src/lobster/geom.h @@ -556,6 +556,12 @@ template inline float3 random_point_in_sphere(RandomNumberGenerator< } } + +inline float2 rotate2(const float2 &v, const float2 &a) { + return float2(v.x * a.x - v.y * a.y, v.x * a.y + v.y * a.x); +} + + inline float3 rotateX(const float3 &v, const float2 &a) { return float3(v.x, v.y * a.x - v.z * a.y, v.y * a.y + v.z * a.x); } @@ -566,9 +572,13 @@ inline float3 rotateZ(const float3 &v, const float2 &a) { return float3(v.x * a.x - v.y * a.y, v.x * a.y + v.y * a.x, v.z); } -inline float3 rotateX(const float3 &v, float a) { return rotateX(v, float2(cosf(a), sinf(a))); } -inline float3 rotateY(const float3 &v, float a) { return rotateY(v, float2(cosf(a), sinf(a))); } -inline float3 rotateZ(const float3 &v, float a) { return rotateZ(v, float2(cosf(a), sinf(a))); } +inline float2 rotvec(float a) { return float2(cosf(a), sinf(a)); } + +inline float2 rotate2(const float2 &v, float a) { return rotate2(v, rotvec(a)); } + +inline float3 rotateX(const float3 &v, float a) { return rotateX(v, rotvec(a)); } +inline float3 rotateY(const float3 &v, float a) { return rotateY(v, rotvec(a)); } +inline float3 rotateZ(const float3 &v, float a) { return rotateZ(v, rotvec(a)); } struct quat : float4 { quat() {} diff --git a/docs/builtin_functions_reference.html b/docs/builtin_functions_reference.html index 91be0f2b..2bc7e2c0 100644 --- a/docs/builtin_functions_reference.html +++ b/docs/builtin_functions_reference.html @@ -1141,7 +1141,7 @@ gl.light(pos: float3, params: float2)sets up a light at the given position for this frame. make sure to call this after your camera transforms but before any object transforms (i.e. defined in "worldspace"). params contains specular exponent in x (try 32/64/128 for different material looks) and the specular scale in y (try 1 for full intensity) -gl.render_tiles(positions: [float2], tilecoords: [int2], mapsize: int2)Renders a list of tiles from a tilemap. Each tile rendered is 1x1 in size. Positions may be anywhere. tilecoords are indices into the map (0..mapsize-1), mapsize is the amount of tiles in the texture. Tiles may overlap, they are drawn in order. Before calling this, make sure to have the texture set and a textured shader +gl.render_tiles(positions: [float2], tilecoords: [int2], mapsize: int2, sizes: [float], rotations: [float])Renders a list of tiles from a tilemap. Each tile rendered is 0.5 in radius (1x1 square around pos) unless the optional sizes vector is specified (may be empty). Positions may be anywhere. tilecoords are indices into the map (0..mapsize-1), mapsize is the amount of tiles in the texture. rotations are optional (may be empty, faster if not specified). Tiles may overlap, they are drawn in order. Before calling this, make sure to have the texture set and a textured shader. If you want tile to use top-left as position, wrap this call in gl.translate float2_h: gl.debug_grid(num: int3, dist: float3, thickness: float)renders a grid in space for debugging purposes. num is the number of lines in all 3 directions, and dist their spacing. thickness of the lines in the same units