Updated readability of the code.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / raster / shapes / basic / solidpolygon / SolidPolygon.java
1 /*
2  * Sixth 3D engine. Author: Svjatoslav Agejenko.
3  * This project is released under Creative Commons Zero (CC0) license.
4  */
5 package eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.solidpolygon;
6
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;
13
14 import static eu.svjatoslav.sixth.e3d.geometry.Polygon.pointWithinPolygon;
15
16 /**
17  * polygon with solid color.
18  */
19 public class SolidPolygon extends AbstractCoordinateShape {
20
21     private final static LineInterpolator polygonBoundary1 = new LineInterpolator();
22     private final static LineInterpolator polygonBoundary2 = new LineInterpolator();
23     private final static LineInterpolator polygonBoundary3 = new LineInterpolator();
24     private Color color;
25
26     public SolidPolygon(final Point3D point1, final Point3D point2,
27                         final Point3D point3, final Color color) {
28         super(point1, point2, point3);
29         this.color = color;
30     }
31
32     public static void drawHorizontalLine(final LineInterpolator line1,
33                                           final LineInterpolator line2, final int y,
34                                           final RenderingContext renderBuffer, final Color color) {
35
36         int x1 = line1.getX(y);
37         int x2 = line2.getX(y);
38
39         if (x1 > x2) {
40             final int tmp = x1;
41             x1 = x2;
42             x2 = tmp;
43         }
44
45         if (x1 < 0)
46             x1 = 0;
47
48         if (x2 >= renderBuffer.width)
49             x2 = renderBuffer.width - 1;
50
51         final int width = x2 - x1;
52
53         int offset = ((y * renderBuffer.width) + x1) * 4;
54         final byte[] offSreenBufferBytes = renderBuffer.pixels;
55
56         final int polygonAlpha = color.a;
57         final int b = color.b;
58         final int g = color.g;
59         final int r = color.r;
60
61         if (polygonAlpha == 255)
62             for (int i = 0; i < width; i++) {
63                 offSreenBufferBytes[offset] = (byte) 255;
64                 offset++;
65                 offSreenBufferBytes[offset] = (byte) b;
66                 offset++;
67                 offSreenBufferBytes[offset] = (byte) g;
68                 offset++;
69                 offSreenBufferBytes[offset] = (byte) r;
70                 offset++;
71             }
72         else {
73             final int backgroundAlpha = 255 - polygonAlpha;
74
75             final int blueWithAlpha = b * polygonAlpha;
76             final int greenWithAlpha = g * polygonAlpha;
77             final int redWithAlpha = r * polygonAlpha;
78
79             for (int i = 0; i < width; i++) {
80                 offSreenBufferBytes[offset] = (byte) 255;
81                 offset++;
82                 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + blueWithAlpha) / 256);
83                 offset++;
84                 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + greenWithAlpha) / 256);
85                 offset++;
86                 offSreenBufferBytes[offset] = (byte) ((((offSreenBufferBytes[offset] & 0xff) * backgroundAlpha) + redWithAlpha) / 256);
87                 offset++;
88             }
89
90         }
91
92     }
93
94     public static void drawPolygon(final RenderingContext context,
95                                    final Point2D onScreenPoint1, final Point2D onScreenPoint2,
96                                    final Point2D onScreenPoint3,
97                                    final MouseInteractionController mouseInteractionController,
98                                    final Color color) {
99
100         onScreenPoint1.roundToInteger();
101         onScreenPoint2.roundToInteger();
102         onScreenPoint3.roundToInteger();
103
104         if (mouseInteractionController != null)
105             if (context.getMouseEvent() != null)
106                 if (pointWithinPolygon(context.getMouseEvent().coordinate,
107                         onScreenPoint1, onScreenPoint2, onScreenPoint3))
108                     context.setCurrentObjectUnderMouseCursor(mouseInteractionController);
109
110         if (color.isTransparent())
111             return;
112
113         // find top-most point
114         int yTop = (int) onScreenPoint1.y;
115
116         if (onScreenPoint2.y < yTop)
117             yTop = (int) onScreenPoint2.y;
118
119         if (onScreenPoint3.y < yTop)
120             yTop = (int) onScreenPoint3.y;
121
122         if (yTop < 0)
123             yTop = 0;
124
125         // find bottom-most point
126         int yBottom = (int) onScreenPoint1.y;
127
128         if (onScreenPoint2.y > yBottom)
129             yBottom = (int) onScreenPoint2.y;
130
131         if (onScreenPoint3.y > yBottom)
132             yBottom = (int) onScreenPoint3.y;
133
134         if (yBottom >= context.height)
135             yBottom = context.height - 1;
136
137         // paint
138         polygonBoundary1.setPoints(onScreenPoint1, onScreenPoint2);
139         polygonBoundary2.setPoints(onScreenPoint1, onScreenPoint3);
140         polygonBoundary3.setPoints(onScreenPoint2, onScreenPoint3);
141
142         final LineInterpolator[] is = new LineInterpolator[3];
143         is[0] = polygonBoundary1;
144         is[1] = polygonBoundary2;
145         is[2] = polygonBoundary3;
146
147         java.util.Arrays.sort(is);
148
149         for (int y = yTop; y < yBottom; y++)
150             if (is[0].containsY(y)) {
151
152                 if (is[1].containsY(y))
153                     drawHorizontalLine(is[0], is[1], y, context, color);
154                 else if (is[2].containsY(y))
155                     drawHorizontalLine(is[0], is[2], y, context, color);
156             } else if (is[1].containsY(y))
157                 if (is[2].containsY(y))
158                     drawHorizontalLine(is[1], is[2], y, context, color);
159     }
160
161     public Color getColor() {
162         return color;
163     }
164
165     public void setColor(final Color color) {
166         this.color = color;
167     }
168
169     @Override
170     public void paint(final RenderingContext renderBuffer) {
171
172         final Point2D onScreenPoint1 = coordinates[0].onScreenCoordinate;
173         final Point2D onScreenPoint2 = coordinates[1].onScreenCoordinate;
174         final Point2D onScreenPoint3 = coordinates[2].onScreenCoordinate;
175
176         drawPolygon(renderBuffer, onScreenPoint1, onScreenPoint2,
177                 onScreenPoint3, mouseInteractionController, color);
178
179     }
180
181 }