2 * Sixth 3D engine. Copyright ©2012-2020, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of version 3 of the GNU Lesser General Public License
6 * or later as published by the Free Software Foundation.
10 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.texturedpolygon;
12 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
13 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
14 import eu.svjatoslav.sixth.e3d.gui.RenderingContext;
15 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
16 import eu.svjatoslav.sixth.e3d.renderer.raster.slicer.PolygonCoordinate;
17 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
18 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.TextureBitmap;
22 import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
24 public class TexturedPolygon extends AbstractCoordinateShape {
26 public final Texture texture;
27 final PolygonBorderInterpolator[] is = new PolygonBorderInterpolator[]{
28 new PolygonBorderInterpolator(), new PolygonBorderInterpolator(),
29 new PolygonBorderInterpolator()};
31 * Polygon texture coordinates.
33 public Point2D texturePoint1, texturePoint2, texturePoint3;
34 private boolean showBorders = false;
35 private double totalTextureDistance = -1;
37 public TexturedPolygon(final Point3D p1, final Point3D p2,
38 final Point3D p3, final Point2D tp1, final Point2D tp2,
39 final Point2D tp3, final Texture texture) {
47 this.texture = texture;
50 public TexturedPolygon(final PolygonCoordinate pc1,
51 final PolygonCoordinate pc2, final PolygonCoordinate pc3,
52 final Texture texture) {
54 this(pc1.space, pc2.space, pc3.space, pc1.texture, pc2.texture,
55 pc3.texture, texture);
58 private void computeTotalTextureDistance() {
59 // compute total texture distance
60 totalTextureDistance = texturePoint1.getDistanceTo(texturePoint2);
61 totalTextureDistance += texturePoint1.getDistanceTo(texturePoint3);
62 totalTextureDistance += texturePoint2.getDistanceTo(texturePoint3);
65 private void drawHorizontalLine(final PolygonBorderInterpolator line1,
66 final PolygonBorderInterpolator line2, final int y,
67 final RenderingContext renderBuffer,
68 final TextureBitmap textureBitmap) {
73 int x1 = line1.getX();
74 int x2 = line2.getX();
76 final double tx2, ty2;
77 final double tx1, ty1;
81 tx1 = line1.getTX() * textureBitmap.multiplicationFactor;
82 ty1 = line1.getTY() * textureBitmap.multiplicationFactor;
84 tx2 = line2.getTX() * textureBitmap.multiplicationFactor;
85 ty2 = line2.getTY() * textureBitmap.multiplicationFactor;
92 tx1 = line2.getTX() * textureBitmap.multiplicationFactor;
93 ty1 = line2.getTY() * textureBitmap.multiplicationFactor;
95 tx2 = line1.getTX() * textureBitmap.multiplicationFactor;
96 ty2 = line1.getTY() * textureBitmap.multiplicationFactor;
99 final double realWidth = x2 - x1;
100 final double realX1 = x1;
105 if (x2 >= renderBuffer.width)
106 x2 = renderBuffer.width - 1;
108 int renderBufferOffset = ((y * renderBuffer.width) + x1) * 4;
109 final byte[] renderBufferBytes = renderBuffer.pixels;
111 final double twidth = tx2 - tx1;
112 final double theight = ty2 - ty1;
114 for (int x = x1; x < x2; x++) {
116 final double distance = x - realX1;
118 final double tx = tx1 + ((twidth * distance) / realWidth);
119 final double ty = ty1 + ((theight * distance) / realWidth);
121 final int textureOffset = textureBitmap.getAddress((int) tx,
124 textureBitmap.drawPixel(textureOffset, renderBufferBytes,
127 renderBufferOffset += 4;
133 public void paint(final RenderingContext renderBuffer) {
135 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
136 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
137 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
139 projectedPoint1.roundToInteger();
140 projectedPoint2.roundToInteger();
141 projectedPoint3.roundToInteger();
143 if (mouseInteractionController != null)
144 if (renderBuffer.getMouseEvent() != null)
145 if (pointWithinPolygon(
146 renderBuffer.getMouseEvent().coordinate, projectedPoint1,
147 projectedPoint2, projectedPoint3))
148 renderBuffer.setObjectUnderMouse(mouseInteractionController);
150 // Show polygon boundaries (for debugging)
152 showBorders(renderBuffer);
154 // find top-most point
155 int yTop = (int) projectedPoint1.y;
157 if (projectedPoint2.y < yTop)
158 yTop = (int) projectedPoint2.y;
160 if (projectedPoint3.y < yTop)
161 yTop = (int) projectedPoint3.y;
166 // find bottom-most point
167 int yBottom = (int) projectedPoint1.y;
169 if (projectedPoint2.y > yBottom)
170 yBottom = (int) projectedPoint2.y;
172 if (projectedPoint3.y > yBottom)
173 yBottom = (int) projectedPoint3.y;
175 if (yBottom >= renderBuffer.height)
176 yBottom = renderBuffer.height - 1;
179 double totalVisibleDistance = projectedPoint1
180 .getDistanceTo(projectedPoint2);
181 totalVisibleDistance += projectedPoint1.getDistanceTo(projectedPoint3);
182 totalVisibleDistance += projectedPoint2.getDistanceTo(projectedPoint3);
184 if (totalTextureDistance == -1)
185 computeTotalTextureDistance();
186 final double scaleFactor = (totalVisibleDistance / totalTextureDistance) * 1.2d;
188 final TextureBitmap zoomedBitmap = texture.getZoomedBitmap(scaleFactor);
190 is[0].setPoints(projectedPoint1, projectedPoint2, texturePoint1,
192 is[1].setPoints(projectedPoint1, projectedPoint3, texturePoint1,
194 is[2].setPoints(projectedPoint2, projectedPoint3, texturePoint2,
197 java.util.Arrays.sort(is);
199 for (int y = yTop; y < yBottom; y++)
200 if (is[0].containsY(y)) {
202 if (is[1].containsY(y))
203 drawHorizontalLine(is[0], is[1], y, renderBuffer,
205 else if (is[2].containsY(y))
206 drawHorizontalLine(is[0], is[2], y, renderBuffer,
208 } else if (is[1].containsY(y))
209 if (is[2].containsY(y))
210 drawHorizontalLine(is[1], is[2], y, renderBuffer,
215 private void showBorders(final RenderingContext renderBuffer) {
217 final Point2D projectedPoint1 = coordinates[0].onScreenCoordinate;
218 final Point2D projectedPoint2 = coordinates[1].onScreenCoordinate;
219 final Point2D projectedPoint3 = coordinates[2].onScreenCoordinate;
221 renderBuffer.graphics.setColor(Color.YELLOW);
222 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
223 (int) projectedPoint1.y, (int) projectedPoint2.x,
224 (int) projectedPoint2.y);
225 renderBuffer.graphics.drawLine((int) projectedPoint3.x,
226 (int) projectedPoint3.y, (int) projectedPoint2.x,
227 (int) projectedPoint2.y);
228 renderBuffer.graphics.drawLine((int) projectedPoint1.x,
229 (int) projectedPoint1.y, (int) projectedPoint3.x,
230 (int) projectedPoint3.y);