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