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.gui.ViewPanel;
8 import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
9 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
10 import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
12 import java.util.Vector;
14 public class RayTracer implements Runnable {
16 private static final int PROGRESS_UPDATE_FREQUENCY_MILLIS = 1000;
17 private final Camera camera;
18 private final Texture texture;
19 private final ViewPanel viewPanel;
20 private OctreeVolume octreeVolume;
21 private Vector<LightSource> lights;
22 private int computedLights;
24 public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
25 final Vector<LightSource> lights, final Camera camera,
26 final ViewPanel viewPanel) {
28 this.texture = texture;
29 this.octreeVolume = octreeVolume;
32 this.viewPanel = viewPanel;
41 // Camera cam = new Camera(camCenter, upLeft, upRight, downLeft,
44 // add camera to the raytracing point
45 // Main.mainWorld.geometryCollection.addObject(cam);
46 // Main.mainWorld.compiledGeometry.compileGeometry(Main.mainWorld.geometryCollection);
48 final int width = texture.primaryBitmap.width;
49 final int height = texture.primaryBitmap.height;
51 final CameraView cameraView = camera.getCameraView();
53 // calculate vertical vectors
54 final double x1p = cameraView.downLeft.x - cameraView.upLeft.x;
55 final double y1p = cameraView.downLeft.y - cameraView.upLeft.y;
56 final double z1p = cameraView.downLeft.z - cameraView.upLeft.z;
58 final double x2p = cameraView.downRight.x - cameraView.upRight.x;
59 final double y2p = cameraView.downRight.y - cameraView.upRight.y;
60 final double z2p = cameraView.downRight.z - cameraView.upRight.z;
62 long nextBitmapUpdate = System.currentTimeMillis()
63 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
65 for (int y = 0; y < height; y++) {
66 final double cx1 = cameraView.upLeft.x + ((x1p * y) / height);
67 final double cy1 = cameraView.upLeft.y + ((y1p * y) / height);
68 final double cz1 = cameraView.upLeft.z + ((z1p * y) / height);
70 final double cx2 = cameraView.upRight.x + ((x2p * y) / height);
71 final double cy2 = cameraView.upRight.y + ((y2p * y) / height);
72 final double cz2 = cameraView.upRight.z + ((z2p * y) / height);
74 // calculate horisontal vector
75 final double x3p = cx2 - cx1;
76 final double y3p = cy2 - cy1;
77 final double z3p = cz2 - cz1;
79 for (int x = 0; x < width; x++) {
80 final double cx3 = cx1 + ((x3p * x) / width);
81 final double cy3 = cy1 + ((y3p * x) / width);
82 final double cz3 = cz1 + ((z3p * x) / width);
84 final Ray r = new Ray(cameraView.camCenter.x,
85 cameraView.camCenter.y, cameraView.camCenter.z, cx3
86 - cameraView.camCenter.x, cy3
87 - cameraView.camCenter.y, cz3
88 - cameraView.camCenter.z);
89 final int c = traceRay(r);
91 final Color color = new Color(c);
92 texture.primaryBitmap.drawPixel(x, y, color);
95 if (System.currentTimeMillis() > nextBitmapUpdate) {
96 nextBitmapUpdate = System.currentTimeMillis()
97 + PROGRESS_UPDATE_FREQUENCY_MILLIS;
98 texture.resetResampledBitmapCache();
99 viewPanel.repaintDuringNextViewUpdate();
103 texture.resetResampledBitmapCache();
104 viewPanel.repaintDuringNextViewUpdate();
107 private int traceRay(final Ray ray) {
109 final int intersectingCell = octreeVolume.traceCell(0, 0, 0,
110 octreeVolume.masterCellSize, 0, ray);
112 if (intersectingCell != -1) {
113 // if lightening not computed, compute it
114 if (octreeVolume.ce3[intersectingCell] == -1)
115 // if cell is larger than 1
116 if (ray.hitCellSize > 1) {
118 octreeVolume.breakSolidCell(intersectingCell);
119 return traceRay(ray);
122 float red = 30, green = 30, blue = 30;
124 for (final LightSource l : lights) {
125 final int xDist = (l.x - ray.hitCellX);
126 final int yDist = (l.y - ray.hitCellY);
127 final int zDist = (l.z - ray.hitCellZ);
129 double newRed = 0, newGreen = 0, newBlue = 0;
130 double tempRed, tempGreen, tempBlue;
132 double distance = Math.sqrt((xDist * xDist)
133 + (yDist * yDist) + (zDist * zDist));
134 distance = (distance / 3) + 1;
136 final Ray r1 = new Ray(ray.hitCellX, ray.hitCellY
137 - (float) 1.5, ray.hitCellZ,
139 (float) l.x - (float) ray.hitCellX, l.y
140 - (ray.hitCellY - (float) 1.5), (float) l.z
141 - (float) ray.hitCellZ);
143 final int rt1 = octreeVolume.traceCell(0, 0, 0,
144 octreeVolume.masterCellSize, 0, r1);
147 newRed = (l.color.r * l.brightness) / distance;
148 newGreen = (l.color.g * l.brightness) / distance;
149 newBlue = (l.color.b * l.brightness) / distance;
152 final Ray r2 = new Ray(ray.hitCellX - (float) 1.5,
153 ray.hitCellY, ray.hitCellZ,
155 l.x - (ray.hitCellX - (float) 1.5), (float) l.y
156 - (float) ray.hitCellY, (float) l.z
157 - (float) ray.hitCellZ);
159 final int rt2 = octreeVolume.traceCell(0, 0, 0,
160 octreeVolume.masterCellSize, 0, r2);
163 tempRed = (l.color.r * l.brightness) / distance;
164 tempGreen = (l.color.g * l.brightness) / distance;
165 tempBlue = (l.color.b * l.brightness) / distance;
167 if (tempRed > newRed)
169 if (tempGreen > newGreen)
170 newGreen = tempGreen;
171 if (tempBlue > newBlue)
175 final Ray r3 = new Ray(ray.hitCellX, ray.hitCellY,
176 ray.hitCellZ - (float) 1.5,
178 (float) l.x - (float) ray.hitCellX, (float) l.y
179 - (float) ray.hitCellY, l.z
180 - (ray.hitCellZ - (float) 1.5));
182 final int rt3 = octreeVolume.traceCell(0, 0, 0,
183 octreeVolume.masterCellSize, 0, r3);
186 tempRed = (l.color.r * l.brightness) / distance;
187 tempGreen = (l.color.g * l.brightness) / distance;
188 tempBlue = (l.color.b * l.brightness) / distance;
189 if (tempRed > newRed)
191 if (tempGreen > newGreen)
192 newGreen = tempGreen;
193 if (tempBlue > newBlue)
197 final Ray r4 = new Ray(ray.hitCellX, ray.hitCellY
198 + (float) 1.5, ray.hitCellZ,
200 (float) l.x - (float) ray.hitCellX, l.y
201 - (ray.hitCellY + (float) 1.5), (float) l.z
202 - (float) ray.hitCellZ);
204 final int rt4 = octreeVolume.traceCell(0, 0, 0,
205 octreeVolume.masterCellSize, 0, r4);
208 tempRed = (l.color.r * l.brightness) / distance;
209 tempGreen = (l.color.g * l.brightness) / distance;
210 tempBlue = (l.color.b * l.brightness) / distance;
211 if (tempRed > newRed)
213 if (tempGreen > newGreen)
214 newGreen = tempGreen;
215 if (tempBlue > newBlue)
219 final Ray r5 = new Ray(ray.hitCellX + (float) 1.5,
220 ray.hitCellY, ray.hitCellZ,
222 l.x - (ray.hitCellX + (float) 1.5), (float) l.y
223 - (float) ray.hitCellY, (float) l.z
224 - (float) ray.hitCellZ);
226 final int rt5 = octreeVolume.traceCell(0, 0, 0,
227 octreeVolume.masterCellSize, 0, r5);
230 tempRed = (l.color.r * l.brightness) / distance;
231 tempGreen = (l.color.g * l.brightness) / distance;
232 tempBlue = (l.color.b * l.brightness) / distance;
233 if (tempRed > newRed)
235 if (tempGreen > newGreen)
236 newGreen = tempGreen;
237 if (tempBlue > newBlue)
241 final Ray r6 = new Ray(ray.hitCellX, ray.hitCellY,
242 ray.hitCellZ + (float) 1.5,
244 (float) l.x - (float) ray.hitCellX, (float) l.y
245 - (float) ray.hitCellY, l.z
246 - (ray.hitCellZ + (float) 1.5));
248 final int rt6 = octreeVolume.traceCell(0, 0, 0,
249 octreeVolume.masterCellSize, 0, r6);
252 tempRed = (l.color.r * l.brightness) / distance;
253 tempGreen = (l.color.g * l.brightness) / distance;
254 tempBlue = (l.color.b * l.brightness) / distance;
255 if (tempRed > newRed)
257 if (tempGreen > newGreen)
258 newGreen = tempGreen;
259 if (tempBlue > newBlue)
268 final int cellColor = octreeVolume.ce2[intersectingCell];
270 red = (red * ((cellColor & 0xFF0000) >> 16)) / 255;
271 green = (green * ((cellColor & 0xFF00) >> 8)) / 255;
272 blue = (blue * (cellColor & 0xFF)) / 255;
281 octreeVolume.ce3[intersectingCell] = (((int) red) << 16)
282 + (((int) green) << 8) + ((int) blue);
285 if (octreeVolume.ce3[intersectingCell] == 0)
286 return octreeVolume.ce2[intersectingCell];
287 return octreeVolume.ce3[intersectingCell];
290 // return (200 << 16) + (200 << 8) + 255;