void Color::lerp(const Color& c1, const Color& c2, float t) { color_lerp(&c_, &c1.c_, &c2.c_, t); }
// returns true if further calls could possibly result in a mesh void LightCaster::add_triangle(Mesh* result, const Vector_& light, Wall* last_closest, float beginAngle, float nextAngle) { // within our angle bounds? float da1 = signed_angular_distance(angle, beginAngle); if(da1 > halfwidth) return; // swath begins after our cutoff float da2 = signed_angular_distance(angle, nextAngle); if(da2 < -halfwidth) return; // swath ends before our cutoff // clamp the values we did get float ada1 = ABS(da1); if(ada1 > halfwidth) { float fixup = halfwidth - ada1; beginAngle += fixup * sign(da1); } float ada2 = ABS(da2); if(ada2 > halfwidth) { float fixup = halfwidth - ada2; nextAngle += fixup * sign(da2); } int steps = ceilf(signed_angular_distance(beginAngle, nextAngle) / max_angle_step); float oldBegin = beginAngle; float oldNext = nextAngle; for(int ii = 0; ii < steps; ++ii) { beginAngle = oldBegin + ii * max_angle_step; float delta = signed_angular_distance(beginAngle, oldNext); nextAngle = beginAngle + MIN(delta, max_angle_step); // interset the discovered angle range with the previously // closest wall segment Vector_ a1; a1.x = light.x + cosf(beginAngle); a1.y = light.y + sinf(beginAngle); Vector_ a2; a2.x = light.x + cosf(nextAngle); a2.y = light.y + sinf(nextAngle); Vector_ i1, i2; line_intersection(&i1, &last_closest->start, &last_closest->end, &light, &a1); line_intersection(&i2, &last_closest->start, &last_closest->end, &light, &a2); Color c1, c2; float d1 = vector_dist(&i1, &light); float d2 = vector_dist(&i2, &light); color_lerp(&c1, &min_color, &max_color, MIN(1.0f, d1 / max_range)); color_lerp(&c2, &min_color, &max_color, MIN(1.0f, d2 / max_range)); if(d1 > max_range) { vector_direction_scaled(&i1, &i1, &light, max_range); vector_add(&i1, &i1, &light); } if(d2 > max_range) { vector_direction_scaled(&i2, &i2, &light, max_range); vector_add(&i2, &i2, &light); } // add a triangle to the mesh result->add_point(light, min_color); result->add_point(i1, c1); result->add_point(i2, c2); } }