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.solidpolygon;
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.gui.humaninput.MouseInteractionController;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.AbstractCoordinateShape;
14 import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
16 public class SolidPolygon extends AbstractCoordinateShape {
18 private final static LineInterpolator polygonBoundary1 = new LineInterpolator();
19 private final static LineInterpolator polygonBoundary2 = new LineInterpolator();
20 private final static LineInterpolator polygonBoundary3 = new LineInterpolator();
23 public SolidPolygon(final Point3D point1, final Point3D point2,
24 final Point3D point3, final Color color) {
25 super(point1, point2, point3);
29 public static void drawHorizontalLine(final LineInterpolator line1,
30 final LineInterpolator line2, final int y,
31 final RenderingContext renderBuffer, final Color color) {
33 int x1 = line1.getX(y);
34 int x2 = line2.getX(y);
45 if (x2 >= renderBuffer.width)
46 x2 = renderBuffer.width - 1;
48 final int width = x2 - x1;
50 int offset = ((y * renderBuffer.width) + x1) * 4;
51 final byte[] offSreenBufferBytes = renderBuffer.pixels;
53 final int polygonAlpha = color.a;
54 final int b = color.b;
55 final int g = color.g;
56 final int r = color.r;
58 if (polygonAlpha == 255)
59 for (int i = 0; i < width; i++) {
60 offSreenBufferBytes[offset] = (byte) 255;
62 offSreenBufferBytes[offset] = (byte) b;
64 offSreenBufferBytes[offset] = (byte) g;
66 offSreenBufferBytes[offset] = (byte) r;
70 final int backgroundAlpha = 255 - polygonAlpha;
72 final int blueWithAlpha = b * polygonAlpha;
73 final int greenWithAlpha = g * polygonAlpha;
74 final int redWithAlpha = r * polygonAlpha;
76 for (int i = 0; i < width; i++) {
77 offSreenBufferBytes[offset] = (byte) 255;
79 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + blueWithAlpha) / 256);
81 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + greenWithAlpha) / 256);
83 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + redWithAlpha) / 256);
91 public static void drawPolygon(final RenderingContext context,
92 final Point2D onScreenPoint1, final Point2D onScreenPoint2,
93 final Point2D onScreenPoint3,
94 final MouseInteractionController mouseInteractionController,
97 onScreenPoint1.roundToInteger();
98 onScreenPoint2.roundToInteger();
99 onScreenPoint3.roundToInteger();
101 if (mouseInteractionController != null)
102 if (context.getMouseEvent() != null)
103 if (pointWithinPolygon(context.getMouseEvent().coordinate,
104 onScreenPoint1, onScreenPoint2, onScreenPoint3))
105 context.setObjectUnderMouse(mouseInteractionController);
107 if (color.isTransparent())
110 // find top-most point
111 int yTop = (int) onScreenPoint1.y;
113 if (onScreenPoint2.y < yTop)
114 yTop = (int) onScreenPoint2.y;
116 if (onScreenPoint3.y < yTop)
117 yTop = (int) onScreenPoint3.y;
122 // find bottom-most point
123 int yBottom = (int) onScreenPoint1.y;
125 if (onScreenPoint2.y > yBottom)
126 yBottom = (int) onScreenPoint2.y;
128 if (onScreenPoint3.y > yBottom)
129 yBottom = (int) onScreenPoint3.y;
131 if (yBottom >= context.height)
132 yBottom = context.height - 1;
135 polygonBoundary1.setPoints(onScreenPoint1, onScreenPoint2);
136 polygonBoundary2.setPoints(onScreenPoint1, onScreenPoint3);
137 polygonBoundary3.setPoints(onScreenPoint2, onScreenPoint3);
139 final LineInterpolator[] is = new LineInterpolator[3];
140 is[0] = polygonBoundary1;
141 is[1] = polygonBoundary2;
142 is[2] = polygonBoundary3;
144 java.util.Arrays.sort(is);
146 for (int y = yTop; y < yBottom; y++)
147 if (is[0].containsY(y)) {
149 if (is[1].containsY(y))
150 drawHorizontalLine(is[0], is[1], y, context, color);
151 else if (is[2].containsY(y))
152 drawHorizontalLine(is[0], is[2], y, context, color);
153 } else if (is[1].containsY(y))
154 if (is[2].containsY(y))
155 drawHorizontalLine(is[1], is[2], y, context, color);
158 public Color getColor() {
162 public void setColor(final Color color) {
167 public void paint(final RenderingContext renderBuffer) {
169 final Point2D onScreenPoint1 = coordinates[0].onScreenCoordinate;
170 final Point2D onScreenPoint2 = coordinates[1].onScreenCoordinate;
171 final Point2D onScreenPoint3 = coordinates[2].onScreenCoordinate;
173 drawPolygon(renderBuffer, onScreenPoint1, onScreenPoint2,
174 onScreenPoint3, mouseInteractionController, color);