Removed ViewListener interface. Renamed View to ViewPanel.
[sixth-3d.git] / src / main / java / eu / svjatoslav / sixth / e3d / renderer / octree / raytracer / RayTracer.java
1 /*
2  * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
3  *
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.
7  *
8  */
9
10 package eu.svjatoslav.sixth.e3d.renderer.octree.raytracer;
11
12 import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
13 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
14 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
15 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
16
17 import java.util.Vector;
18
19 public class RayTracer implements Runnable {
20
21     private static final int PROGRESS_UPDATE_FREQUENCY_MILLIS = 1000;
22     private final Camera camera;
23     private final Texture texture;
24     private final ViewPanel viewPanel;
25     private OctreeVolume octreeVolume;
26     private Vector<LightSource> lights;
27     private int computedLights;
28
29     public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
30                      final Vector<LightSource> lights, final Camera camera,
31                      final ViewPanel viewPanel) {
32
33         this.texture = texture;
34         this.octreeVolume = octreeVolume;
35         this.lights = lights;
36         this.camera = camera;
37         this.viewPanel = viewPanel;
38     }
39
40     @Override
41     public void run() {
42         computedLights = 0;
43
44         // create camera
45
46         // Camera cam = new Camera(camCenter, upLeft, upRight, downLeft,
47         // downRight);
48
49         // add camera to the raytracing point
50         // Main.mainWorld.geometryCollection.addObject(cam);
51         // Main.mainWorld.compiledGeometry.compileGeometry(Main.mainWorld.geometryCollection);
52
53         final int width = texture.primaryBitmap.width;
54         final int height = texture.primaryBitmap.height;
55
56         final CameraView cameraView = camera.getCameraView();
57
58         // calculate vertical vectors
59         final double x1p = cameraView.downLeft.x - cameraView.upLeft.x;
60         final double y1p = cameraView.downLeft.y - cameraView.upLeft.y;
61         final double z1p = cameraView.downLeft.z - cameraView.upLeft.z;
62
63         final double x2p = cameraView.downRight.x - cameraView.upRight.x;
64         final double y2p = cameraView.downRight.y - cameraView.upRight.y;
65         final double z2p = cameraView.downRight.z - cameraView.upRight.z;
66
67         long nextBitmapUpdate = System.currentTimeMillis()
68                 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
69
70         for (int y = 0; y < height; y++) {
71             final double cx1 = cameraView.upLeft.x + ((x1p * y) / height);
72             final double cy1 = cameraView.upLeft.y + ((y1p * y) / height);
73             final double cz1 = cameraView.upLeft.z + ((z1p * y) / height);
74
75             final double cx2 = cameraView.upRight.x + ((x2p * y) / height);
76             final double cy2 = cameraView.upRight.y + ((y2p * y) / height);
77             final double cz2 = cameraView.upRight.z + ((z2p * y) / height);
78
79             // calculate horisontal vector
80             final double x3p = cx2 - cx1;
81             final double y3p = cy2 - cy1;
82             final double z3p = cz2 - cz1;
83
84             for (int x = 0; x < width; x++) {
85                 final double cx3 = cx1 + ((x3p * x) / width);
86                 final double cy3 = cy1 + ((y3p * x) / width);
87                 final double cz3 = cz1 + ((z3p * x) / width);
88
89                 final Ray r = new Ray(cameraView.camCenter.x,
90                         cameraView.camCenter.y, cameraView.camCenter.z, cx3
91                         - cameraView.camCenter.x, cy3
92                         - cameraView.camCenter.y, cz3
93                         - cameraView.camCenter.z);
94                 final int c = traceRay(r);
95
96                 final Color color = new Color(c);
97                 texture.primaryBitmap.drawPixel(x, y, color);
98             }
99
100             if (System.currentTimeMillis() > nextBitmapUpdate) {
101                 nextBitmapUpdate = System.currentTimeMillis()
102                         + PROGRESS_UPDATE_FREQUENCY_MILLIS;
103                 texture.resetResampledBitmapCache();
104                 viewPanel.repaintDuringNextViewUpdate();
105             }
106         }
107
108         texture.resetResampledBitmapCache();
109         viewPanel.repaintDuringNextViewUpdate();
110         // System.out.println("Raytracing done.");
111         // System.out.println("New lights computed:" + computedLights);
112     }
113
114     public int traceLight(final LightSource l, final int cubeX,
115                           final int cubeY, final int cubeZ) {
116         return 0;
117     }
118
119     public int traceRay(final Ray r) {
120
121         final int re = octreeVolume.traceCell(0, 0, 0,
122                 octreeVolume.masterCellSize, 0, r);
123
124         if (re != -1) {
125             // if lightening not computed, compute it
126             if (octreeVolume.ce3[re] == -1)
127                 // if cell is larger than 1
128                 if (r.hitCellSize > 1) {
129                     // break it up
130                     octreeVolume.breakSolidCell(re);
131                     return traceRay(r);
132                 } else {
133                     computedLights++;
134                     float red = 30, green = 30, blue = 30;
135
136                     for (final LightSource l : lights) {
137                         final int xDist = (l.x - r.hitCellX);
138                         final int yDist = (l.y - r.hitCellY);
139                         final int zDist = (l.z - r.hitCellZ);
140
141                         double newRed = 0, newGreen = 0, newBlue = 0;
142                         double tempRed, tempGreen, tempBlue;
143
144                         double distance = Math.sqrt((xDist * xDist)
145                                 + (yDist * yDist) + (zDist * zDist));
146                         distance = (distance / 3) + 1;
147
148                         final Ray r1 = new Ray(r.hitCellX, r.hitCellY
149                                 - (float) 1.5, r.hitCellZ,
150
151                                 (float) l.x - (float) r.hitCellX, l.y
152                                 - (r.hitCellY - (float) 1.5), (float) l.z
153                                 - (float) r.hitCellZ);
154
155                         final int rt1 = octreeVolume.traceCell(0, 0, 0,
156                                 octreeVolume.masterCellSize, 0, r1);
157
158                         if (rt1 == -1) {
159                             newRed = (l.color.r * l.brightness) / distance;
160                             newGreen = (l.color.g * l.brightness) / distance;
161                             newBlue = (l.color.b * l.brightness) / distance;
162                         }
163
164                         final Ray r2 = new Ray(r.hitCellX - (float) 1.5,
165                                 r.hitCellY, r.hitCellZ,
166
167                                 l.x - (r.hitCellX - (float) 1.5), (float) l.y
168                                 - (float) r.hitCellY, (float) l.z
169                                 - (float) r.hitCellZ);
170
171                         final int rt2 = octreeVolume.traceCell(0, 0, 0,
172                                 octreeVolume.masterCellSize, 0, r2);
173
174                         if (rt2 == -1) {
175                             tempRed = (l.color.r * l.brightness) / distance;
176                             tempGreen = (l.color.g * l.brightness) / distance;
177                             tempBlue = (l.color.b * l.brightness) / distance;
178
179                             if (tempRed > newRed)
180                                 newRed = tempRed;
181                             if (tempGreen > newGreen)
182                                 newGreen = tempGreen;
183                             if (tempBlue > newBlue)
184                                 newBlue = tempBlue;
185                         }
186
187                         final Ray r3 = new Ray(r.hitCellX, r.hitCellY,
188                                 r.hitCellZ - (float) 1.5,
189
190                                 (float) l.x - (float) r.hitCellX, (float) l.y
191                                 - (float) r.hitCellY, l.z
192                                 - (r.hitCellZ - (float) 1.5));
193
194                         final int rt3 = octreeVolume.traceCell(0, 0, 0,
195                                 octreeVolume.masterCellSize, 0, r3);
196
197                         if (rt3 == -1) {
198                             tempRed = (l.color.r * l.brightness) / distance;
199                             tempGreen = (l.color.g * l.brightness) / distance;
200                             tempBlue = (l.color.b * l.brightness) / distance;
201                             if (tempRed > newRed)
202                                 newRed = tempRed;
203                             if (tempGreen > newGreen)
204                                 newGreen = tempGreen;
205                             if (tempBlue > newBlue)
206                                 newBlue = tempBlue;
207                         }
208
209                         final Ray r4 = new Ray(r.hitCellX, r.hitCellY
210                                 + (float) 1.5, r.hitCellZ,
211
212                                 (float) l.x - (float) r.hitCellX, l.y
213                                 - (r.hitCellY + (float) 1.5), (float) l.z
214                                 - (float) r.hitCellZ);
215
216                         final int rt4 = octreeVolume.traceCell(0, 0, 0,
217                                 octreeVolume.masterCellSize, 0, r4);
218
219                         if (rt4 == -1) {
220                             tempRed = (l.color.r * l.brightness) / distance;
221                             tempGreen = (l.color.g * l.brightness) / distance;
222                             tempBlue = (l.color.b * l.brightness) / distance;
223                             if (tempRed > newRed)
224                                 newRed = tempRed;
225                             if (tempGreen > newGreen)
226                                 newGreen = tempGreen;
227                             if (tempBlue > newBlue)
228                                 newBlue = tempBlue;
229                         }
230
231                         final Ray r5 = new Ray(r.hitCellX + (float) 1.5,
232                                 r.hitCellY, r.hitCellZ,
233
234                                 l.x - (r.hitCellX + (float) 1.5), (float) l.y
235                                 - (float) r.hitCellY, (float) l.z
236                                 - (float) r.hitCellZ);
237
238                         final int rt5 = octreeVolume.traceCell(0, 0, 0,
239                                 octreeVolume.masterCellSize, 0, r5);
240
241                         if (rt5 == -1) {
242                             tempRed = (l.color.r * l.brightness) / distance;
243                             tempGreen = (l.color.g * l.brightness) / distance;
244                             tempBlue = (l.color.b * l.brightness) / distance;
245                             if (tempRed > newRed)
246                                 newRed = tempRed;
247                             if (tempGreen > newGreen)
248                                 newGreen = tempGreen;
249                             if (tempBlue > newBlue)
250                                 newBlue = tempBlue;
251                         }
252
253                         final Ray r6 = new Ray(r.hitCellX, r.hitCellY,
254                                 r.hitCellZ + (float) 1.5,
255
256                                 (float) l.x - (float) r.hitCellX, (float) l.y
257                                 - (float) r.hitCellY, l.z
258                                 - (r.hitCellZ + (float) 1.5));
259
260                         final int rt6 = octreeVolume.traceCell(0, 0, 0,
261                                 octreeVolume.masterCellSize, 0, r6);
262
263                         if (rt6 == -1) {
264                             tempRed = (l.color.r * l.brightness) / distance;
265                             tempGreen = (l.color.g * l.brightness) / distance;
266                             tempBlue = (l.color.b * l.brightness) / distance;
267                             if (tempRed > newRed)
268                                 newRed = tempRed;
269                             if (tempGreen > newGreen)
270                                 newGreen = tempGreen;
271                             if (tempBlue > newBlue)
272                                 newBlue = tempBlue;
273                         }
274                         red += newRed;
275                         green += newGreen;
276                         blue += newBlue;
277
278                     }
279
280                     final int cellColor = octreeVolume.ce2[re];
281
282                     red = (red * ((cellColor & 0xFF0000) >> 16)) / 255;
283                     green = (green * ((cellColor & 0xFF00) >> 8)) / 255;
284                     blue = (blue * (cellColor & 0xFF)) / 255;
285
286                     if (red > 255)
287                         red = 255;
288                     if (green > 255)
289                         green = 255;
290                     if (blue > 255)
291                         blue = 255;
292
293                     octreeVolume.ce3[re] = (((int) red) << 16)
294                             + (((int) green) << 8) + ((int) blue);
295
296                 }
297             if (octreeVolume.ce3[re] == 0)
298                 return octreeVolume.ce2[re];
299             return octreeVolume.ce3[re];
300         }
301
302         // return (200 << 16) + (200 << 8) + 255;
303         return 0;
304     }
305
306 }