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.octree.raytracer;
7 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
8 import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
9 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
10 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
11 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
13 import java.util.Vector;
15 public class RayTracer implements Runnable {
17 private static final int PROGRESS_UPDATE_FREQUENCY_MILLIS = 1000;
18 private final Camera camera;
19 private final Texture texture;
20 private final ViewPanel viewPanel;
21 private final OctreeVolume octreeVolume;
22 private final Vector<LightSource> lights;
23 private int computedLights;
25 public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
26 final Vector<LightSource> lights, final Camera camera,
27 final ViewPanel viewPanel) {
29 this.texture = texture;
30 this.octreeVolume = octreeVolume;
33 this.viewPanel = viewPanel;
42 // Camera cam = new Camera(camCenter, upLeft, upRight, downLeft,
45 // add camera to the raytracing point
46 // Main.mainWorld.geometryCollection.addObject(cam);
47 // Main.mainWorld.compiledGeometry.compileGeometry(Main.mainWorld.geometryCollection);
49 final int width = texture.primaryBitmap.width;
50 final int height = texture.primaryBitmap.height;
52 final CameraView cameraView = camera.getCameraView();
54 // calculate vertical vectors
55 final double x1p = cameraView.bottomLeft.x - cameraView.topLeft.x;
56 final double y1p = cameraView.bottomLeft.y - cameraView.topLeft.y;
57 final double z1p = cameraView.bottomLeft.z - cameraView.topLeft.z;
59 final double x2p = cameraView.bottomRight.x - cameraView.topRight.x;
60 final double y2p = cameraView.bottomRight.y - cameraView.topRight.y;
61 final double z2p = cameraView.bottomRight.z - cameraView.topRight.z;
63 long nextBitmapUpdate = System.currentTimeMillis()
64 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
66 for (int y = 0; y < height; y++) {
67 final double cx1 = cameraView.topLeft.x + ((x1p * y) / height);
68 final double cy1 = cameraView.topLeft.y + ((y1p * y) / height);
69 final double cz1 = cameraView.topLeft.z + ((z1p * y) / height);
71 final double cx2 = cameraView.topRight.x + ((x2p * y) / height);
72 final double cy2 = cameraView.topRight.y + ((y2p * y) / height);
73 final double cz2 = cameraView.topRight.z + ((z2p * y) / height);
75 // calculate horisontal vector
76 final double x3p = cx2 - cx1;
77 final double y3p = cy2 - cy1;
78 final double z3p = cz2 - cz1;
80 for (int x = 0; x < width; x++) {
81 final double cx3 = cx1 + ((x3p * x) / width);
82 final double cy3 = cy1 + ((y3p * x) / width);
83 final double cz3 = cz1 + ((z3p * x) / width);
85 final Ray r = new Ray(
86 new Point3D(cameraView.cameraCenter.x,
87 cameraView.cameraCenter.y,
88 cameraView.cameraCenter.z),
90 cx3 - cameraView.cameraCenter.x, cy3
91 - cameraView.cameraCenter.y, cz3
92 - cameraView.cameraCenter.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 double xDist = (l.location.x - ray.hitCellX);
131 final double yDist = (l.location.y - ray.hitCellY);
132 final double zDist = (l.location.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(
144 ray.hitCellY - (float) 1.5,
147 new Point3D((float) l.location.x - (float) ray.hitCellX, l.location.y
148 - (ray.hitCellY - (float) 1.5), (float) l.location.z
149 - (float) ray.hitCellZ)
152 final int rt1 = octreeVolume.traceCell(0, 0, 0,
153 octreeVolume.masterCellSize, 0, r1);
156 newRed = (l.color.r * l.brightness) / distance;
157 newGreen = (l.color.g * l.brightness) / distance;
158 newBlue = (l.color.b * l.brightness) / distance;
161 final Ray r2 = new Ray(
163 ray.hitCellX - (float) 1.5,
164 ray.hitCellY, ray.hitCellZ),
167 l.location.x - (ray.hitCellX - (float) 1.5), (float) l.location.y
168 - (float) ray.hitCellY, (float) l.location.z
169 - (float) ray.hitCellZ)
172 final int rt2 = octreeVolume.traceCell(0, 0, 0,
173 octreeVolume.masterCellSize, 0, r2);
176 tempRed = (l.color.r * l.brightness) / distance;
177 tempGreen = (l.color.g * l.brightness) / distance;
178 tempBlue = (l.color.b * l.brightness) / distance;
180 if (tempRed > newRed)
182 if (tempGreen > newGreen)
183 newGreen = tempGreen;
184 if (tempBlue > newBlue)
188 final Ray r3 = new Ray(
190 ray.hitCellX, ray.hitCellY,
191 ray.hitCellZ - (float) 1.5),
193 (float) l.location.x - (float) ray.hitCellX, (float) l.location.y
194 - (float) ray.hitCellY, l.location.z
195 - (ray.hitCellZ - (float) 1.5))
198 final int rt3 = octreeVolume.traceCell(0, 0, 0,
199 octreeVolume.masterCellSize, 0, r3);
202 tempRed = (l.color.r * l.brightness) / distance;
203 tempGreen = (l.color.g * l.brightness) / distance;
204 tempBlue = (l.color.b * l.brightness) / distance;
205 if (tempRed > newRed)
207 if (tempGreen > newGreen)
208 newGreen = tempGreen;
209 if (tempBlue > newBlue)
213 final Ray r4 = new Ray(
216 ray.hitCellY+ (float) 1.5,
220 (float) l.location.x - (float) ray.hitCellX, l.location.y
221 - (ray.hitCellY + (float) 1.5), (float) l.location.z
222 - (float) ray.hitCellZ)
225 final int rt4 = octreeVolume.traceCell(0, 0, 0,
226 octreeVolume.masterCellSize, 0, r4);
229 tempRed = (l.color.r * l.brightness) / distance;
230 tempGreen = (l.color.g * l.brightness) / distance;
231 tempBlue = (l.color.b * l.brightness) / distance;
232 if (tempRed > newRed)
234 if (tempGreen > newGreen)
235 newGreen = tempGreen;
236 if (tempBlue > newBlue)
240 final Ray r5 = new Ray(
242 ray.hitCellX + (float) 1.5,
243 ray.hitCellY, ray.hitCellZ),
246 l.location.x - (ray.hitCellX + (float) 1.5), (float) l.location.y
247 - (float) ray.hitCellY, (float) l.location.z
248 - (float) ray.hitCellZ)
251 final int rt5 = octreeVolume.traceCell(0, 0, 0,
252 octreeVolume.masterCellSize, 0, r5);
255 tempRed = (l.color.r * l.brightness) / distance;
256 tempGreen = (l.color.g * l.brightness) / distance;
257 tempBlue = (l.color.b * l.brightness) / distance;
258 if (tempRed > newRed)
260 if (tempGreen > newGreen)
261 newGreen = tempGreen;
262 if (tempBlue > newBlue)
266 final Ray r6 = new Ray(
268 ray.hitCellX, ray.hitCellY,
269 ray.hitCellZ + (float) 1.5),
273 (float) l.location.x - (float) ray.hitCellX, (float) l.location.y
274 - (float) ray.hitCellY, l.location.z
275 - (ray.hitCellZ + (float) 1.5)));
277 final int rt6 = octreeVolume.traceCell(0, 0, 0,
278 octreeVolume.masterCellSize, 0, r6);
281 tempRed = (l.color.r * l.brightness) / distance;
282 tempGreen = (l.color.g * l.brightness) / distance;
283 tempBlue = (l.color.b * l.brightness) / distance;
284 if (tempRed > newRed)
286 if (tempGreen > newGreen)
287 newGreen = tempGreen;
288 if (tempBlue > newBlue)
297 final int cellColor = octreeVolume.ce2[intersectingCell];
299 red = (red * ((cellColor & 0xFF0000) >> 16)) / 255;
300 green = (green * ((cellColor & 0xFF00) >> 8)) / 255;
301 blue = (blue * (cellColor & 0xFF)) / 255;
310 octreeVolume.ce3[intersectingCell] = (((int) red) << 16)
311 + (((int) green) << 8) + ((int) blue);
314 if (octreeVolume.ce3[intersectingCell] == 0)
315 return octreeVolume.ce2[intersectingCell];
316 return octreeVolume.ce3[intersectingCell];
319 // return (200 << 16) + (200 << 8) + 255;