RNClassID R3Span:: Clip(const R3Plane& plane) { // Characterize endpoints with respect to plane RNScalar d1 = R3SignedDistance(plane, Start()); RNScalar d2 = R3SignedDistance(plane, End()); // Clip span to plane if (RNIsNegative(d1)) { if (RNIsNegative(d2)) { // Both points are below plane ??? Reset(Start(), Start()); return RN_NULL_CLASS_ID; } else if (RNIsPositive(d2)) { // Start is below, end is above -- move start to plane Reset((Start() * d2 + End() * -d1) / (d2 - d1), End()); return R3_SPAN_CLASS_ID; } else { // Start is below, end is on -- move start to end Reset(End(), End()); return R3_POINT_CLASS_ID; } } else if (RNIsPositive(d1)) { if (RNIsNegative(d2)) { // Start is above, end is below -- move end to plane Reset(Start(), (Start() * -d2 + End() * d1) / (d1 - d2)); return R3_SPAN_CLASS_ID; } else { // Start is above, end is on or above return R3_SPAN_CLASS_ID; } } else { if (RNIsNegative(d2)) { // Start is on, end is below -- move end to start Reset(Start(), Start()); return R3_POINT_CLASS_ID; } else { // Start is on, end is on or above return R3_SPAN_CLASS_ID; } } }
RNRgb R3PointLight:: Reflection(const R3Brdf& brdf, const R3Point& eye, const R3Point& point, const R3Vector& normal) const { // Check if light is active if (!IsActive()) return RNblack_rgb; // Get material properties const RNRgb& Dc = brdf.Diffuse(); const RNRgb& Sc = brdf.Specular(); RNScalar s = brdf.Shininess(); // Get light properties RNScalar I = IntensityAtPoint(point); R3Vector L = DirectionFromPoint(point); const RNRgb& Ic = Color(); // Compute geometric stuff RNScalar NL = normal.Dot(L); if (RNIsNegativeOrZero(NL)) return RNblack_rgb; R3Vector R = (2.0 * NL) * normal - L; R3Vector V = eye - point; V.Normalize(); RNScalar VR = V.Dot(R); // Compute diffuse reflection RNRgb rgb = (I * NL) * Dc * Ic; // Compute specular reflection if (RNIsPositive(VR)) rgb += (I * pow(VR,s)) * Sc * Ic; // Return total reflection return rgb; }
RNLength R2Distance(const R2Line& line, const R2Span& span) { // Return distance from span to line RNScalar d = R2SignedDistance(line, span); if (RNIsPositive(d)) return d; else if (RNIsNegative(d)) return -d; else return 0.0; }
RNLength R2SignedDistance(const R2Line& line, const R2Span& span) { // Return signed distance from line to span RNLength d1 = R2SignedDistance(line, span.Start()); if (RNIsPositive(d1)) { // Start point is above line RNLength d2 = R2SignedDistance(line, span.End()); if (RNIsPositive(d2)) return ((d1 > d2) ? d2 : d1); else return 0.0; } else if (RNIsNegative(d1)) { // Start point is below line RNLength d2 = R2SignedDistance(line, span.End()); if (RNIsNegative(d2)) return ((d1 > d2) ? d1 : d2); else return 0.0; } else { // Start point is on line return 0.0; } }
RNLength R2Distance(const R2Point& point, const R2Span& span) { // Check span if (RNIsZero(span.Length())) return R2Distance(point, span.Start()); // Check if start point is closest R2Vector v1 = point - span.Start(); RNScalar dir1 = v1.Dot(span.Vector()); if (RNIsNegative(dir1)) return v1.Length(); // Check if end point is closest R2Vector v2 = point - span.End(); RNScalar dir2 = v2.Dot(span.Vector()); if (RNIsPositive(dir2)) return v2.Length(); // Return distance from point to span line return R2Distance(point, span.Line()); }