2 * Sixth 3D engine. Author: Svjatoslav Agejenko.
3 * This project is released under Creative Commons Zero (CC0) license.
8 package eu.svjatoslav.sixth.e3d.renderer.octree.raytracer;
10 import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
11 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
12 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
13 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
15 import java.util.Vector;
17 public class RayTracer implements Runnable {
19 private static final int PROGRESS_UPDATE_FREQUENCY_MILLIS = 1000;
20 private final Camera camera;
21 private final Texture texture;
22 private final ViewPanel viewPanel;
23 private OctreeVolume octreeVolume;
24 private Vector<LightSource> lights;
25 private int computedLights;
27 public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
28 final Vector<LightSource> lights, final Camera camera,
29 final ViewPanel viewPanel) {
31 this.texture = texture;
32 this.octreeVolume = octreeVolume;
35 this.viewPanel = viewPanel;
44 // Camera cam = new Camera(camCenter, upLeft, upRight, downLeft,
47 // add camera to the raytracing point
48 // Main.mainWorld.geometryCollection.addObject(cam);
49 // Main.mainWorld.compiledGeometry.compileGeometry(Main.mainWorld.geometryCollection);
51 final int width = texture.primaryBitmap.width;
52 final int height = texture.primaryBitmap.height;
54 final CameraView cameraView = camera.getCameraView();
56 // calculate vertical vectors
57 final double x1p = cameraView.downLeft.x - cameraView.upLeft.x;
58 final double y1p = cameraView.downLeft.y - cameraView.upLeft.y;
59 final double z1p = cameraView.downLeft.z - cameraView.upLeft.z;
61 final double x2p = cameraView.downRight.x - cameraView.upRight.x;
62 final double y2p = cameraView.downRight.y - cameraView.upRight.y;
63 final double z2p = cameraView.downRight.z - cameraView.upRight.z;
65 long nextBitmapUpdate = System.currentTimeMillis()
66 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
68 for (int y = 0; y < height; y++) {
69 final double cx1 = cameraView.upLeft.x + ((x1p * y) / height);
70 final double cy1 = cameraView.upLeft.y + ((y1p * y) / height);
71 final double cz1 = cameraView.upLeft.z + ((z1p * y) / height);
73 final double cx2 = cameraView.upRight.x + ((x2p * y) / height);
74 final double cy2 = cameraView.upRight.y + ((y2p * y) / height);
75 final double cz2 = cameraView.upRight.z + ((z2p * y) / height);
77 // calculate horisontal vector
78 final double x3p = cx2 - cx1;
79 final double y3p = cy2 - cy1;
80 final double z3p = cz2 - cz1;
82 for (int x = 0; x < width; x++) {
83 final double cx3 = cx1 + ((x3p * x) / width);
84 final double cy3 = cy1 + ((y3p * x) / width);
85 final double cz3 = cz1 + ((z3p * x) / width);
87 final Ray r = new Ray(cameraView.camCenter.x,
88 cameraView.camCenter.y, cameraView.camCenter.z, cx3
89 - cameraView.camCenter.x, cy3
90 - cameraView.camCenter.y, cz3
91 - cameraView.camCenter.z);
92 final int c = traceRay(r);
94 final Color color = new Color(c);
95 texture.primaryBitmap.drawPixel(x, y, color);
98 if (System.currentTimeMillis() > nextBitmapUpdate) {
99 nextBitmapUpdate = System.currentTimeMillis()
100 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
101 texture.resetResampledBitmapCache();
102 viewPanel.repaintDuringNextViewUpdate();
106 texture.resetResampledBitmapCache();
107 viewPanel.repaintDuringNextViewUpdate();
110 private int traceRay(final Ray ray) {
112 final int intersectingCell = octreeVolume.traceCell(0, 0, 0,
113 octreeVolume.masterCellSize, 0, ray);
115 if (intersectingCell != -1) {
116 // if lightening not computed, compute it
117 if (octreeVolume.ce3[intersectingCell] == -1)
118 // if cell is larger than 1
119 if (ray.hitCellSize > 1) {
121 octreeVolume.breakSolidCell(intersectingCell);
122 return traceRay(ray);
125 float red = 30, green = 30, blue = 30;
127 for (final LightSource l : lights) {
128 final int xDist = (l.x - ray.hitCellX);
129 final int yDist = (l.y - ray.hitCellY);
130 final int zDist = (l.z - ray.hitCellZ);
132 double newRed = 0, newGreen = 0, newBlue = 0;
133 double tempRed, tempGreen, tempBlue;
135 double distance = Math.sqrt((xDist * xDist)
136 + (yDist * yDist) + (zDist * zDist));
137 distance = (distance / 3) + 1;
139 final Ray r1 = new Ray(ray.hitCellX, ray.hitCellY
140 - (float) 1.5, ray.hitCellZ,
142 (float) l.x - (float) ray.hitCellX, l.y
143 - (ray.hitCellY - (float) 1.5), (float) l.z
144 - (float) ray.hitCellZ);
146 final int rt1 = octreeVolume.traceCell(0, 0, 0,
147 octreeVolume.masterCellSize, 0, r1);
150 newRed = (l.color.r * l.brightness) / distance;
151 newGreen = (l.color.g * l.brightness) / distance;
152 newBlue = (l.color.b * l.brightness) / distance;
155 final Ray r2 = new Ray(ray.hitCellX - (float) 1.5,
156 ray.hitCellY, ray.hitCellZ,
158 l.x - (ray.hitCellX - (float) 1.5), (float) l.y
159 - (float) ray.hitCellY, (float) l.z
160 - (float) ray.hitCellZ);
162 final int rt2 = octreeVolume.traceCell(0, 0, 0,
163 octreeVolume.masterCellSize, 0, r2);
166 tempRed = (l.color.r * l.brightness) / distance;
167 tempGreen = (l.color.g * l.brightness) / distance;
168 tempBlue = (l.color.b * l.brightness) / distance;
170 if (tempRed > newRed)
172 if (tempGreen > newGreen)
173 newGreen = tempGreen;
174 if (tempBlue > newBlue)
178 final Ray r3 = new Ray(ray.hitCellX, ray.hitCellY,
179 ray.hitCellZ - (float) 1.5,
181 (float) l.x - (float) ray.hitCellX, (float) l.y
182 - (float) ray.hitCellY, l.z
183 - (ray.hitCellZ - (float) 1.5));
185 final int rt3 = octreeVolume.traceCell(0, 0, 0,
186 octreeVolume.masterCellSize, 0, r3);
189 tempRed = (l.color.r * l.brightness) / distance;
190 tempGreen = (l.color.g * l.brightness) / distance;
191 tempBlue = (l.color.b * l.brightness) / distance;
192 if (tempRed > newRed)
194 if (tempGreen > newGreen)
195 newGreen = tempGreen;
196 if (tempBlue > newBlue)
200 final Ray r4 = new Ray(ray.hitCellX, ray.hitCellY
201 + (float) 1.5, ray.hitCellZ,
203 (float) l.x - (float) ray.hitCellX, l.y
204 - (ray.hitCellY + (float) 1.5), (float) l.z
205 - (float) ray.hitCellZ);
207 final int rt4 = octreeVolume.traceCell(0, 0, 0,
208 octreeVolume.masterCellSize, 0, r4);
211 tempRed = (l.color.r * l.brightness) / distance;
212 tempGreen = (l.color.g * l.brightness) / distance;
213 tempBlue = (l.color.b * l.brightness) / distance;
214 if (tempRed > newRed)
216 if (tempGreen > newGreen)
217 newGreen = tempGreen;
218 if (tempBlue > newBlue)
222 final Ray r5 = new Ray(ray.hitCellX + (float) 1.5,
223 ray.hitCellY, ray.hitCellZ,
225 l.x - (ray.hitCellX + (float) 1.5), (float) l.y
226 - (float) ray.hitCellY, (float) l.z
227 - (float) ray.hitCellZ);
229 final int rt5 = octreeVolume.traceCell(0, 0, 0,
230 octreeVolume.masterCellSize, 0, r5);
233 tempRed = (l.color.r * l.brightness) / distance;
234 tempGreen = (l.color.g * l.brightness) / distance;
235 tempBlue = (l.color.b * l.brightness) / distance;
236 if (tempRed > newRed)
238 if (tempGreen > newGreen)
239 newGreen = tempGreen;
240 if (tempBlue > newBlue)
244 final Ray r6 = new Ray(ray.hitCellX, ray.hitCellY,
245 ray.hitCellZ + (float) 1.5,
247 (float) l.x - (float) ray.hitCellX, (float) l.y
248 - (float) ray.hitCellY, l.z
249 - (ray.hitCellZ + (float) 1.5));
251 final int rt6 = octreeVolume.traceCell(0, 0, 0,
252 octreeVolume.masterCellSize, 0, r6);
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)
271 final int cellColor = octreeVolume.ce2[intersectingCell];
273 red = (red * ((cellColor & 0xFF0000) >> 16)) / 255;
274 green = (green * ((cellColor & 0xFF00) >> 8)) / 255;
275 blue = (blue * (cellColor & 0xFF)) / 255;
284 octreeVolume.ce3[intersectingCell] = (((int) red) << 16)
285 + (((int) green) << 8) + ((int) blue);
288 if (octreeVolume.ce3[intersectingCell] == 0)
289 return octreeVolume.ce2[intersectingCell];
290 return octreeVolume.ce3[intersectingCell];
293 // return (200 << 16) + (200 << 8) + 255;