| 3945 | } |
| 3946 | |
| 3947 | void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::Pixel& tint) |
| 3948 | { |
| 3949 | // Thanks Nathan Reed, a brilliant article explaining whats going on here |
| 3950 | // http://www.reedbeta.com/blog/quadrilateral-interpolation-part-1/ |
| 3951 | DecalInstance di; |
| 3952 | di.points = 4; |
| 3953 | di.decal = decal; |
| 3954 | di.tint = { tint, tint, tint, tint }; |
| 3955 | di.w = { 1, 1, 1, 1 }; |
| 3956 | di.pos.resize(4); |
| 3957 | di.uv = { { 0.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f} }; |
| 3958 | olc::vf2d center; |
| 3959 | float rd = ((pos[2].x - pos[0].x) * (pos[3].y - pos[1].y) - (pos[3].x - pos[1].x) * (pos[2].y - pos[0].y)); |
| 3960 | if (rd != 0) |
| 3961 | { |
| 3962 | rd = 1.0f / rd; |
| 3963 | float rn = ((pos[3].x - pos[1].x) * (pos[0].y - pos[1].y) - (pos[3].y - pos[1].y) * (pos[0].x - pos[1].x)) * rd; |
| 3964 | float sn = ((pos[2].x - pos[0].x) * (pos[0].y - pos[1].y) - (pos[2].y - pos[0].y) * (pos[0].x - pos[1].x)) * rd; |
| 3965 | if (!(rn < 0.f || rn > 1.f || sn < 0.f || sn > 1.f)) center = pos[0] + rn * (pos[2] - pos[0]); |
| 3966 | float d[4]; for (int i = 0; i < 4; i++) d[i] = (pos[i] - center).mag(); |
| 3967 | for (int i = 0; i < 4; i++) |
| 3968 | { |
| 3969 | float q = d[i] == 0.0f ? 1.0f : (d[i] + d[(i + 2) & 3]) / d[(i + 2) & 3]; |
| 3970 | di.uv[i] *= q; di.w[i] *= q; |
| 3971 | di.pos[i] = { (pos[i].x * vInvScreenSize.x) * 2.0f - 1.0f, ((pos[i].y * vInvScreenSize.y) * 2.0f - 1.0f) * -1.0f }; |
| 3972 | } |
| 3973 | di.mode = nDecalMode; |
| 3974 | di.structure = nDecalStructure; |
| 3975 | vLayers[nTargetLayer].vecDecalInstance.push_back(di); |
| 3976 | } |
| 3977 | } |
| 3978 | |
| 3979 | void PixelGameEngine::DrawWarpedDecal(olc::Decal* decal, const std::array<olc::vf2d, 4>& pos, const olc::Pixel& tint) |
| 3980 | { |