2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.texturedpolygon;
7 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
9 import static java.lang.Math.abs;
12 * Interpolator for textured polygon edges with perspective correction.
14 * This class maps screen coordinates to texture coordinates while maintaining
15 * perspective accuracy.
16 * It's used to create texture-mapped scanlines that adjust for depth (z) to
17 * prevent texture distortion.
19 * The comparison logic ensures proper scanline ordering based on vertical
20 * coverage and horizontal span.
22 public class PolygonBorderInterpolator implements
23 Comparable<PolygonBorderInterpolator> {
25 // on-screen coordinates
26 Point2D onScreenPoint1;
27 Point2D onScreenPoint2;
29 double distanceFromY1;
30 private int onScreenHeight;
31 private int onScreenWidth;
32 private int onscreenAbsoluteHeight;
33 private double textureWidth;
34 private double textureHeight;
35 // texture coordinates
36 private Point2D texturePoint1;
37 private Point2D texturePoint2;
41 public boolean equals(final Object o) {
42 if (o == null) return false;
44 return o instanceof PolygonBorderInterpolator && compareTo((PolygonBorderInterpolator) o) == 0;
48 public int hashCode() {
49 int result = onScreenWidth;
50 result = 31 * result + onscreenAbsoluteHeight;
55 public int compareTo(final PolygonBorderInterpolator otherInterpolator) {
56 if (onscreenAbsoluteHeight < otherInterpolator.onscreenAbsoluteHeight)
58 if (onscreenAbsoluteHeight > otherInterpolator.onscreenAbsoluteHeight)
61 if (onScreenWidth < otherInterpolator.onScreenWidth)
63 if (onScreenWidth > otherInterpolator.onScreenWidth)
69 public boolean containsY(final int y) {
71 if (onScreenPoint1.y < onScreenPoint2.y) {
72 if (y >= onScreenPoint1.y)
73 return y <= onScreenPoint2.y;
74 } else if (y >= onScreenPoint2.y)
75 return y <= onScreenPoint1.y;
80 public double getTX() {
82 if (onScreenHeight == 0)
83 return (texturePoint2.x + texturePoint1.x) / 2d;
85 return texturePoint1.x + ((textureWidth * distanceFromY1) / onScreenHeight);
88 public double getTY() {
90 if (onScreenHeight == 0)
91 return (texturePoint2.y + texturePoint1.y) / 2d;
93 return texturePoint1.y + ((textureHeight * distanceFromY1) / onScreenHeight);
98 if (onScreenHeight == 0)
99 return (int) ((onScreenPoint2.x + onScreenPoint1.x) / 2d);
101 return (int) (onScreenPoint1.x + ((onScreenWidth * distanceFromY1) / onScreenHeight));
104 public void setCurrentY(final int y) {
105 distanceFromY1 = y - onScreenPoint1.y;
108 public void setPoints(final Point2D onScreenPoint1, final Point2D onScreenPoint2,
109 final Point2D texturePoint1, final Point2D texturePoint2) {
111 this.onScreenPoint1 = onScreenPoint1;
112 this.onScreenPoint2 = onScreenPoint2;
113 this.texturePoint1 = texturePoint1;
114 this.texturePoint2 = texturePoint2;
116 onScreenHeight = (int) (onScreenPoint2.y - onScreenPoint1.y);
117 onScreenWidth = (int) (onScreenPoint2.x - onScreenPoint1.x);
118 onscreenAbsoluteHeight = abs(onScreenHeight);
120 textureWidth = texturePoint2.x - texturePoint1.x;
121 textureHeight = texturePoint2.y - texturePoint1.y;