2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
8 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.texturedpolygon;
10 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
11 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
12 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
14 import eu.svjatoslav.sixth.e3d.renderer.raster.slicer.PolygonCoordinate;
15 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
16 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
20 import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
22 public class TexturedPolygon extends AbstractCoordinateShape {
24 public final Texture texture;
25 final PolygonBorderInterpolator[] is = new PolygonBorderInterpolator[]{
26 new PolygonBorderInterpolator(), new PolygonBorderInterpolator(),
27 new PolygonBorderInterpolator()};
29 * Polygon texture coordinates.
31 public Point2D texturePoint1, texturePoint2, texturePoint3;
32 private boolean showBorders = false;
33 private double totalTextureDistance = -1;
35 public TexturedPolygon(final Point3D p1, final Point3D p2,
36 final Point3D p3, final Point2D tp1, final Point2D tp2,
37 final Point2D tp3, final Texture texture) {
45 this.texture = texture;
48 public TexturedPolygon(final PolygonCoordinate pc1,
49 final PolygonCoordinate pc2, final PolygonCoordinate pc3,
50 final Texture texture) {
52 this(pc1.space, pc2.space, pc3.space, pc1.texture, pc2.texture,
53 pc3.texture, texture);
56 private void computeTotalTextureDistance() {
57 // compute total texture distance
58 totalTextureDistance = texturePoint1.getDistanceTo(texturePoint2);
59 totalTextureDistance += texturePoint1.getDistanceTo(texturePoint3);
60 totalTextureDistance += texturePoint2.getDistanceTo(texturePoint3);
63 private void drawHorizontalLine(final PolygonBorderInterpolator line1,
64 final PolygonBorderInterpolator line2, final int y,
65 final RenderingContext renderBuffer,
66 final TextureBitmap textureBitmap) {
71 int x1 = line1.getX();
72 int x2 = line2.getX();
74 final double tx2, ty2;
75 final double tx1, ty1;
79 tx1 = line1.getTX() * textureBitmap.multiplicationFactor;
80 ty1 = line1.getTY() * textureBitmap.multiplicationFactor;
82 tx2 = line2.getTX() * textureBitmap.multiplicationFactor;
83 ty2 = line2.getTY() * textureBitmap.multiplicationFactor;
90 tx1 = line2.getTX() * textureBitmap.multiplicationFactor;
91 ty1 = line2.getTY() * textureBitmap.multiplicationFactor;
93 tx2 = line1.getTX() * textureBitmap.multiplicationFactor;
94 ty2 = line1.getTY() * textureBitmap.multiplicationFactor;
97 final double realWidth = x2 - x1;
98 final double realX1 = x1;
103 if (x2 >= renderBuffer.width)
104 x2 = renderBuffer.width - 1;
106 int renderBufferOffset = ((y * renderBuffer.width) + x1) * 4;
107 final byte[] renderBufferBytes = renderBuffer.pixels;
109 final double twidth = tx2 - tx1;
110 final double theight = ty2 - ty1;
112 for (int x = x1; x < x2; x++) {
114 final double distance = x - realX1;
116 final double tx = tx1 + ((twidth * distance) / realWidth);
117 final double ty = ty1 + ((theight * distance) / realWidth);
119 final int textureOffset = textureBitmap.getAddress((int) tx,
122 textureBitmap.drawPixel(textureOffset, renderBufferBytes,
125 renderBufferOffset += 4;
131 public void paint(final RenderingContext renderBuffer) {
133 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
134 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
135 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
137 projectedPoint1.roundToInteger();
138 projectedPoint2.roundToInteger();
139 projectedPoint3.roundToInteger();
141 if (mouseInteractionController != null)
142 if (renderBuffer.getMouseEvent() != null)
143 if (pointWithinPolygon(
144 renderBuffer.getMouseEvent().coordinate, projectedPoint1,
145 projectedPoint2, projectedPoint3))
146 renderBuffer.setObjectUnderMouse(mouseInteractionController);
148 // Show polygon boundaries (for debugging)
150 showBorders(renderBuffer);
152 // find top-most point
153 int yTop = (int) projectedPoint1.y;
155 if (projectedPoint2.y < yTop)
156 yTop = (int) projectedPoint2.y;
158 if (projectedPoint3.y < yTop)
159 yTop = (int) projectedPoint3.y;
164 // find bottom-most point
165 int yBottom = (int) projectedPoint1.y;
167 if (projectedPoint2.y > yBottom)
168 yBottom = (int) projectedPoint2.y;
170 if (projectedPoint3.y > yBottom)
171 yBottom = (int) projectedPoint3.y;
173 if (yBottom >= renderBuffer.height)
174 yBottom = renderBuffer.height - 1;
177 double totalVisibleDistance = projectedPoint1
178 .getDistanceTo(projectedPoint2);
179 totalVisibleDistance += projectedPoint1.getDistanceTo(projectedPoint3);
180 totalVisibleDistance += projectedPoint2.getDistanceTo(projectedPoint3);
182 if (totalTextureDistance == -1)
183 computeTotalTextureDistance();
184 final double scaleFactor = (totalVisibleDistance / totalTextureDistance) * 1.2d;
186 final TextureBitmap zoomedBitmap = texture.getZoomedBitmap(scaleFactor);
188 is[0].setPoints(projectedPoint1, projectedPoint2, texturePoint1,
190 is[1].setPoints(projectedPoint1, projectedPoint3, texturePoint1,
192 is[2].setPoints(projectedPoint2, projectedPoint3, texturePoint2,
195 java.util.Arrays.sort(is);
197 for (int y = yTop; y < yBottom; y++)
198 if (is[0].containsY(y)) {
200 if (is[1].containsY(y))
201 drawHorizontalLine(is[0], is[1], y, renderBuffer,
203 else if (is[2].containsY(y))
204 drawHorizontalLine(is[0], is[2], y, renderBuffer,
206 } else if (is[1].containsY(y))
207 if (is[2].containsY(y))
208 drawHorizontalLine(is[1], is[2], y, renderBuffer,
213 private void showBorders(final RenderingContext renderBuffer) {
215 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
216 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
217 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
219 renderBuffer.graphics.setColor(Color.YELLOW);
220 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
221 (int) projectedPoint1.y, (int) projectedPoint2.x,
222 (int) projectedPoint2.y);
223 renderBuffer.graphics.drawLine((int) projectedPoint3.x,
224 (int) projectedPoint3.y, (int) projectedPoint2.x,
225 (int) projectedPoint2.y);
226 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
227 (int) projectedPoint1.y, (int) projectedPoint3.x,
228 (int) projectedPoint3.y);