2 * Sixth 3D engine. Copyright ©2012-2019, 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.octree.raytracer;
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;
17 import java.util.Vector;
19 public class RayTracer implements Runnable {
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;
29 public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
30 final Vector<LightSource> lights, final Camera camera,
31 final ViewPanel viewPanel) {
33 this.texture = texture;
34 this.octreeVolume = octreeVolume;
37 this.viewPanel = viewPanel;
46 // Camera cam = new Camera(camCenter, upLeft, upRight, downLeft,
49 // add camera to the raytracing point
50 // Main.mainWorld.geometryCollection.addObject(cam);
51 // Main.mainWorld.compiledGeometry.compileGeometry(Main.mainWorld.geometryCollection);
53 final int width = texture.primaryBitmap.width;
54 final int height = texture.primaryBitmap.height;
56 final CameraView cameraView = camera.getCameraView();
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;
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;
67 long nextBitmapUpdate = System.currentTimeMillis()
68 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
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);
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);
79 // calculate horisontal vector
80 final double x3p = cx2 - cx1;
81 final double y3p = cy2 - cy1;
82 final double z3p = cz2 - cz1;
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);
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);
96 final Color color = new Color(c);
97 texture.primaryBitmap.drawPixel(x, y, color);
100 if (System.currentTimeMillis() > nextBitmapUpdate) {
101 nextBitmapUpdate = System.currentTimeMillis()
102 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
103 texture.resetResampledBitmapCache();
104 viewPanel.repaintDuringNextViewUpdate();
108 texture.resetResampledBitmapCache();
109 viewPanel.repaintDuringNextViewUpdate();
112 private int traceRay(final Ray ray) {
114 final int intersectingCell = octreeVolume.traceCell(0, 0, 0,
115 octreeVolume.masterCellSize, 0, ray);
117 if (intersectingCell != -1) {
118 // if lightening not computed, compute it
119 if (octreeVolume.ce3[intersectingCell] == -1)
120 // if cell is larger than 1
121 if (ray.hitCellSize > 1) {
123 octreeVolume.breakSolidCell(intersectingCell);
124 return traceRay(ray);
127 float red = 30, green = 30, blue = 30;
129 for (final LightSource l : lights) {
130 final int xDist = (l.x - ray.hitCellX);
131 final int yDist = (l.y - ray.hitCellY);
132 final int zDist = (l.z - ray.hitCellZ);
134 double newRed = 0, newGreen = 0, newBlue = 0;
135 double tempRed, tempGreen, tempBlue;
137 double distance = Math.sqrt((xDist * xDist)
138 + (yDist * yDist) + (zDist * zDist));
139 distance = (distance / 3) + 1;
141 final Ray r1 = new Ray(ray.hitCellX, ray.hitCellY
142 - (float) 1.5, ray.hitCellZ,
144 (float) l.x - (float) ray.hitCellX, l.y
145 - (ray.hitCellY - (float) 1.5), (float) l.z
146 - (float) ray.hitCellZ);
148 final int rt1 = octreeVolume.traceCell(0, 0, 0,
149 octreeVolume.masterCellSize, 0, r1);
152 newRed = (l.color.r * l.brightness) / distance;
153 newGreen = (l.color.g * l.brightness) / distance;
154 newBlue = (l.color.b * l.brightness) / distance;
157 final Ray r2 = new Ray(ray.hitCellX - (float) 1.5,
158 ray.hitCellY, ray.hitCellZ,
160 l.x - (ray.hitCellX - (float) 1.5), (float) l.y
161 - (float) ray.hitCellY, (float) l.z
162 - (float) ray.hitCellZ);
164 final int rt2 = octreeVolume.traceCell(0, 0, 0,
165 octreeVolume.masterCellSize, 0, r2);
168 tempRed = (l.color.r * l.brightness) / distance;
169 tempGreen = (l.color.g * l.brightness) / distance;
170 tempBlue = (l.color.b * l.brightness) / distance;
172 if (tempRed > newRed)
174 if (tempGreen > newGreen)
175 newGreen = tempGreen;
176 if (tempBlue > newBlue)
180 final Ray r3 = new Ray(ray.hitCellX, ray.hitCellY,
181 ray.hitCellZ - (float) 1.5,
183 (float) l.x - (float) ray.hitCellX, (float) l.y
184 - (float) ray.hitCellY, l.z
185 - (ray.hitCellZ - (float) 1.5));
187 final int rt3 = octreeVolume.traceCell(0, 0, 0,
188 octreeVolume.masterCellSize, 0, r3);
191 tempRed = (l.color.r * l.brightness) / distance;
192 tempGreen = (l.color.g * l.brightness) / distance;
193 tempBlue = (l.color.b * l.brightness) / distance;
194 if (tempRed > newRed)
196 if (tempGreen > newGreen)
197 newGreen = tempGreen;
198 if (tempBlue > newBlue)
202 final Ray r4 = new Ray(ray.hitCellX, ray.hitCellY
203 + (float) 1.5, ray.hitCellZ,
205 (float) l.x - (float) ray.hitCellX, l.y
206 - (ray.hitCellY + (float) 1.5), (float) l.z
207 - (float) ray.hitCellZ);
209 final int rt4 = octreeVolume.traceCell(0, 0, 0,
210 octreeVolume.masterCellSize, 0, r4);
213 tempRed = (l.color.r * l.brightness) / distance;
214 tempGreen = (l.color.g * l.brightness) / distance;
215 tempBlue = (l.color.b * l.brightness) / distance;
216 if (tempRed > newRed)
218 if (tempGreen > newGreen)
219 newGreen = tempGreen;
220 if (tempBlue > newBlue)
224 final Ray r5 = new Ray(ray.hitCellX + (float) 1.5,
225 ray.hitCellY, ray.hitCellZ,
227 l.x - (ray.hitCellX + (float) 1.5), (float) l.y
228 - (float) ray.hitCellY, (float) l.z
229 - (float) ray.hitCellZ);
231 final int rt5 = octreeVolume.traceCell(0, 0, 0,
232 octreeVolume.masterCellSize, 0, r5);
235 tempRed = (l.color.r * l.brightness) / distance;
236 tempGreen = (l.color.g * l.brightness) / distance;
237 tempBlue = (l.color.b * l.brightness) / distance;
238 if (tempRed > newRed)
240 if (tempGreen > newGreen)
241 newGreen = tempGreen;
242 if (tempBlue > newBlue)
246 final Ray r6 = new Ray(ray.hitCellX, ray.hitCellY,
247 ray.hitCellZ + (float) 1.5,
249 (float) l.x - (float) ray.hitCellX, (float) l.y
250 - (float) ray.hitCellY, l.z
251 - (ray.hitCellZ + (float) 1.5));
253 final int rt6 = octreeVolume.traceCell(0, 0, 0,
254 octreeVolume.masterCellSize, 0, r6);
257 tempRed = (l.color.r * l.brightness) / distance;
258 tempGreen = (l.color.g * l.brightness) / distance;
259 tempBlue = (l.color.b * l.brightness) / distance;
260 if (tempRed > newRed)
262 if (tempGreen > newGreen)
263 newGreen = tempGreen;
264 if (tempBlue > newBlue)
273 final int cellColor = octreeVolume.ce2[intersectingCell];
275 red = (red * ((cellColor & 0xFF0000) >> 16)) / 255;
276 green = (green * ((cellColor & 0xFF00) >> 8)) / 255;
277 blue = (blue * (cellColor & 0xFF)) / 255;
286 octreeVolume.ce3[intersectingCell] = (((int) red) << 16)
287 + (((int) green) << 8) + ((int) blue);
290 if (octreeVolume.ce3[intersectingCell] == 0)
291 return octreeVolume.ce2[intersectingCell];
292 return octreeVolume.ce3[intersectingCell];
295 // return (200 << 16) + (200 << 8) + 255;