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;
8 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
9 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
10 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.slicer.PolygonCoordinate;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
17 import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
19 public class TexturedPolygon extends AbstractCoordinateShape {
21 public final Texture texture;
22 final PolygonBorderInterpolator[] is = new PolygonBorderInterpolator[]{
23 new PolygonBorderInterpolator(), new PolygonBorderInterpolator(),
24 new PolygonBorderInterpolator()};
26 * Polygon texture coordinates.
28 public Point2D texturePoint1, texturePoint2, texturePoint3;
29 private boolean showBorders = false;
30 private double totalTextureDistance = -1;
32 public TexturedPolygon(final Point3D p1, final Point3D p2,
33 final Point3D p3, final Point2D tp1, final Point2D tp2,
34 final Point2D tp3, final Texture texture) {
42 this.texture = texture;
45 public TexturedPolygon(final PolygonCoordinate pc1,
46 final PolygonCoordinate pc2, final PolygonCoordinate pc3,
47 final Texture texture) {
49 this(pc1.space, pc2.space, pc3.space, pc1.texture, pc2.texture,
50 pc3.texture, texture);
53 private void computeTotalTextureDistance() {
54 // compute total texture distance
55 totalTextureDistance = texturePoint1.getDistanceTo(texturePoint2);
56 totalTextureDistance += texturePoint1.getDistanceTo(texturePoint3);
57 totalTextureDistance += texturePoint2.getDistanceTo(texturePoint3);
60 private void drawHorizontalLine(final PolygonBorderInterpolator line1,
61 final PolygonBorderInterpolator line2, final int y,
62 final RenderingContext renderBuffer,
63 final TextureBitmap textureBitmap) {
68 int x1 = line1.getX();
69 int x2 = line2.getX();
71 final double tx2, ty2;
72 final double tx1, ty1;
76 tx1 = line1.getTX() * textureBitmap.multiplicationFactor;
77 ty1 = line1.getTY() * textureBitmap.multiplicationFactor;
79 tx2 = line2.getTX() * textureBitmap.multiplicationFactor;
80 ty2 = line2.getTY() * textureBitmap.multiplicationFactor;
87 tx1 = line2.getTX() * textureBitmap.multiplicationFactor;
88 ty1 = line2.getTY() * textureBitmap.multiplicationFactor;
90 tx2 = line1.getTX() * textureBitmap.multiplicationFactor;
91 ty2 = line1.getTY() * textureBitmap.multiplicationFactor;
94 final double realWidth = x2 - x1;
95 final double realX1 = x1;
100 if (x2 >= renderBuffer.width)
101 x2 = renderBuffer.width - 1;
103 int renderBufferOffset = ((y * renderBuffer.width) + x1) * 4;
104 final byte[] renderBufferBytes = renderBuffer.pixels;
106 final double twidth = tx2 - tx1;
107 final double theight = ty2 - ty1;
109 for (int x = x1; x < x2; x++) {
111 final double distance = x - realX1;
113 final double tx = tx1 + ((twidth * distance) / realWidth);
114 final double ty = ty1 + ((theight * distance) / realWidth);
116 final int textureOffset = textureBitmap.getAddress((int) tx,
119 textureBitmap.drawPixel(textureOffset, renderBufferBytes,
122 renderBufferOffset += 4;
128 public void paint(final RenderingContext renderBuffer) {
130 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
131 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
132 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
134 projectedPoint1.roundToInteger();
135 projectedPoint2.roundToInteger();
136 projectedPoint3.roundToInteger();
138 if (mouseInteractionController != null)
139 if (renderBuffer.getMouseEvent() != null)
140 if (pointWithinPolygon(
141 renderBuffer.getMouseEvent().coordinate, projectedPoint1,
142 projectedPoint2, projectedPoint3))
143 renderBuffer.setObjectUnderMouse(mouseInteractionController);
145 // Show polygon boundaries (for debugging)
147 showBorders(renderBuffer);
149 // find top-most point
150 int yTop = (int) projectedPoint1.y;
152 if (projectedPoint2.y < yTop)
153 yTop = (int) projectedPoint2.y;
155 if (projectedPoint3.y < yTop)
156 yTop = (int) projectedPoint3.y;
161 // find bottom-most point
162 int yBottom = (int) projectedPoint1.y;
164 if (projectedPoint2.y > yBottom)
165 yBottom = (int) projectedPoint2.y;
167 if (projectedPoint3.y > yBottom)
168 yBottom = (int) projectedPoint3.y;
170 if (yBottom >= renderBuffer.height)
171 yBottom = renderBuffer.height - 1;
174 double totalVisibleDistance = projectedPoint1
175 .getDistanceTo(projectedPoint2);
176 totalVisibleDistance += projectedPoint1.getDistanceTo(projectedPoint3);
177 totalVisibleDistance += projectedPoint2.getDistanceTo(projectedPoint3);
179 if (totalTextureDistance == -1)
180 computeTotalTextureDistance();
181 final double scaleFactor = (totalVisibleDistance / totalTextureDistance) * 1.2d;
183 final TextureBitmap zoomedBitmap = texture.getZoomedBitmap(scaleFactor);
185 is[0].setPoints(projectedPoint1, projectedPoint2, texturePoint1,
187 is[1].setPoints(projectedPoint1, projectedPoint3, texturePoint1,
189 is[2].setPoints(projectedPoint2, projectedPoint3, texturePoint2,
192 java.util.Arrays.sort(is);
194 for (int y = yTop; y < yBottom; y++)
195 if (is[0].containsY(y)) {
197 if (is[1].containsY(y))
198 drawHorizontalLine(is[0], is[1], y, renderBuffer,
200 else if (is[2].containsY(y))
201 drawHorizontalLine(is[0], is[2], y, renderBuffer,
203 } else if (is[1].containsY(y))
204 if (is[2].containsY(y))
205 drawHorizontalLine(is[1], is[2], y, renderBuffer,
210 private void showBorders(final RenderingContext renderBuffer) {
212 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
213 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
214 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
216 renderBuffer.graphics.setColor(Color.YELLOW);
217 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
218 (int) projectedPoint1.y, (int) projectedPoint2.x,
219 (int) projectedPoint2.y);
220 renderBuffer.graphics.drawLine((int) projectedPoint3.x,
221 (int) projectedPoint3.y, (int) projectedPoint2.x,
222 (int) projectedPoint2.y);
223 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
224 (int) projectedPoint1.y, (int) projectedPoint3.x,
225 (int) projectedPoint3.y);