Last active
May 22, 2018 18:24
-
-
Save bit-hack/5a62af7ea5df839186756893372e3467 to your computer and use it in GitHub Desktop.
derive triangle interpolation edge functions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // triangle setup | |
| // | |
| struct tri_setup_t { | |
| tri_setup_t(const std::array<float2, 3> & t) | |
| : _t(t) | |
| , _i(tri_calc(t)) | |
| { | |
| } | |
| // calculate scaled edge function | |
| // | |
| // - scale the normals so points on the edge would be 0.f distance | |
| // and the prime vertex would be at 1.f | |
| // | |
| std::array<float2, 3> | |
| static tri_calc(const std::array<float2, 3> &t) { | |
| // find edges | |
| const float2 e01 = t[1] - t[0]; // 01 | |
| const float2 e12 = t[2] - t[1]; // 12 | |
| const float2 e20 = t[0] - t[2]; // 20 | |
| // edge normals | |
| float2 n01 = float2::cross(e01); | |
| float2 n12 = float2::cross(e12); | |
| float2 n20 = float2::cross(e20); | |
| // distance between edge and opposite vertex | |
| const float d01 = float2::dot(n01, t[2] - t[0]); | |
| const float d12 = float2::dot(n12, t[0] - t[1]); | |
| const float d20 = float2::dot(n20, t[1] - t[2]); | |
| // normalize to get interpolants | |
| n01 /= d01; | |
| n12 /= d12; | |
| n20 /= d20; | |
| // return interpolants for each vertex | |
| return std::array<float2, 3>{n12, n20, n01}; | |
| } | |
| // evaluate edge functions as point 'p' | |
| // | |
| std::array<float, 3> eval(const float2 &p) const { | |
| // vector to point on edge | |
| const float2 d0 = p - _t[1]; | |
| const float2 d1 = p - _t[2]; | |
| const float2 d2 = p - _t[0]; | |
| // distance from edge | |
| const float e0 = float2::dot(d0, _i[0]); // n12 | |
| const float e1 = float2::dot(d1, _i[1]); // n20 | |
| const float e2 = float2::dot(d2, _i[2]); // n01 | |
| // return | |
| return std::array<float, 3>{e0, e1, e2}; | |
| } | |
| const std::array<float2, 3> _t; // vertices | |
| const std::array<float2, 3> _i; // edge functions | |
| const std::array<float, 3> _d; // plane distance | |
| }; | |
| void raster(SDL_Surface *surf, const std::array<float2, 3> &v, const tri_setup_t &setup) { | |
| const std::array<float2, 3> &i = setup._i; | |
| std::array<float, 3> jy = setup.eval(v, i, float2{0, 0}); | |
| uint32_t *p = (uint32_t *)surf->pixels; | |
| for (uint32_t y = 0; y < uint32_t(surf->h); ++y) { | |
| std::array<float, 3> jx = jy; | |
| for (uint32_t x = 0; x < uint32_t(surf->w); ++x) { | |
| p[x] = 0x101010; | |
| if (jx[0] > 0.f && jx[1] > 0.f && jx[2] > 0.f) { | |
| const int cr = 0xff & int(jx[0] * 255.f); | |
| const int cg = 0xff & int(jx[1] * 255.f); | |
| const int cb = 0xff & int(jx[2] * 255.f); | |
| p[x] = (cr << 16) | (cg << 8) | cb; | |
| } | |
| jx[0] += i[0].x; | |
| jx[1] += i[1].x; | |
| jx[2] += i[2].x; | |
| } | |
| p += surf->pitch / 4; | |
| jy[0] += i[0].y; | |
| jy[1] += i[1].y; | |
| jy[2] += i[2].y; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment