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;
7 import eu.svjatoslav.sixth.e3d.geometry.Point3D;
8 import eu.svjatoslav.sixth.e3d.renderer.octree.raytracer.Ray;
9 import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
11 import static java.lang.Integer.max;
12 import static java.lang.Integer.min;
16 * There are 3 cell types:
23 * visible color, after being illuminated by nearby light sources
26 * contains pointers to 8 sub cells
30 public class OctreeVolume {
32 // cell is not hit by the ray
33 public static final int TRACE_NO_HIT = -1;
35 // solid cell (contains color and illumination)
36 private static final int CELL_STATE_SOLID = -2;
39 private static final int CELL_STATE_UNUSED = -1;
51 * Pointer to the first unused cell.
53 public int cellAllocationPointer = 0;
54 public int usedCellsCount = 0;
55 public int masterCellSize;
57 public OctreeVolume() {
58 initWorld(1500000, 256 * 64);
61 public void breakSolidCell(final int pointer) {
62 final int color = getCellColor(pointer);
63 final int illumination = getCellIllumination(pointer);
65 cell1[pointer] = makeNewCell(color, illumination);
66 cell2[pointer] = makeNewCell(color, illumination);
67 cell3[pointer] = makeNewCell(color, illumination);
68 cell4[pointer] = makeNewCell(color, illumination);
69 cell5[pointer] = makeNewCell(color, illumination);
70 cell6[pointer] = makeNewCell(color, illumination);
71 cell7[pointer] = makeNewCell(color, illumination);
72 cell8[pointer] = makeNewCell(color, illumination);
77 * @param pointer Pointer to the cell.
79 public void clearCell(final int pointer) {
91 public void deleteCell(final int cellPointer) {
92 clearCell(cellPointer);
93 cell1[cellPointer] = CELL_STATE_UNUSED;
97 public int doesIntersect(final int cubeX, final int cubeY, final int cubeZ,
98 final int cubeSize, final Ray r) {
100 // ray starts inside the cube
101 if ((cubeX - cubeSize) < r.origin.x)
102 if ((cubeX + cubeSize) > r.origin.x)
103 if ((cubeY - cubeSize) < r.origin.y)
104 if ((cubeY + cubeSize) > r.origin.y)
105 if ((cubeZ - cubeSize) < r.origin.z)
106 if ((cubeZ + cubeSize) > r.origin.z) {
107 r.hitPoint = r.origin.clone();
111 if (r.direction.z > 0)
112 if ((cubeZ - cubeSize) > r.origin.z) {
113 final double mult = ((cubeZ - cubeSize) - r.origin.z) / r.direction.z;
114 final double hitX = (r.direction.x * mult) + r.origin.x;
115 if ((cubeX - cubeSize) < hitX)
116 if ((cubeX + cubeSize) > hitX) {
117 final double hitY = (r.direction.y * mult) + r.origin.y;
118 if ((cubeY - cubeSize) < hitY)
119 if ((cubeY + cubeSize) > hitY) {
120 r.hitPoint = new Point3D(hitX, hitY, cubeZ
128 if (r.direction.y > 0)
129 if ((cubeY - cubeSize) > r.origin.y) {
130 final double mult = ((cubeY - cubeSize) - r.origin.y) / r.direction.y;
131 final double hitX = (r.direction.x * mult) + r.origin.x;
132 if ((cubeX - cubeSize) < hitX)
133 if ((cubeX + cubeSize) > hitX) {
134 final double hitZ = (r.direction.z * mult) + r.origin.z;
135 if ((cubeZ - cubeSize) < hitZ)
136 if ((cubeZ + cubeSize) > hitZ) {
137 r.hitPoint = new Point3D(hitX, cubeY - cubeSize,
145 if (r.direction.x > 0)
146 if ((cubeX - cubeSize) > r.origin.x) {
147 final double mult = ((cubeX - cubeSize) - r.origin.x) / r.direction.x;
148 final double hitY = (r.direction.y * mult) + r.origin.y;
149 if ((cubeY - cubeSize) < hitY)
150 if ((cubeY + cubeSize) > hitY) {
151 final double hitZ = (r.direction.z * mult) + r.origin.z;
152 if ((cubeZ - cubeSize) < hitZ)
153 if ((cubeZ + cubeSize) > hitZ) {
154 r.hitPoint = new Point3D(cubeX - cubeSize, hitY,
162 if (r.direction.z < 0)
163 if ((cubeZ + cubeSize) < r.origin.z) {
164 final double mult = ((cubeZ + cubeSize) - r.origin.z) / r.direction.z;
165 final double hitX = (r.direction.x * mult) + r.origin.x;
166 if ((cubeX - cubeSize) < hitX)
167 if ((cubeX + cubeSize) > hitX) {
168 final double hitY = (r.direction.y * mult) + r.origin.y;
169 if ((cubeY - cubeSize) < hitY)
170 if ((cubeY + cubeSize) > hitY) {
171 r.hitPoint = new Point3D(hitX, hitY, cubeZ
179 if (r.direction.y < 0)
180 if ((cubeY + cubeSize) < r.origin.y) {
181 final double mult = ((cubeY + cubeSize) - r.origin.y) / r.direction.y;
182 final double hitX = (r.direction.x * mult) + r.origin.x;
183 if ((cubeX - cubeSize) < hitX)
184 if ((cubeX + cubeSize) > hitX) {
185 final double hitZ = (r.direction.z * mult) + r.origin.z;
186 if ((cubeZ - cubeSize) < hitZ)
187 if ((cubeZ + cubeSize) > hitZ) {
188 r.hitPoint = new Point3D(hitX, cubeY + cubeSize,
196 if (r.direction.x < 0)
197 if ((cubeX + cubeSize) < r.origin.x) {
198 final double mult = ((cubeX + cubeSize) - r.origin.x) / r.direction.x;
199 final double hitY = (r.direction.y * mult) + r.origin.y;
200 if ((cubeY - cubeSize) < hitY)
201 if ((cubeY + cubeSize) > hitY) {
202 final double hitZ = (r.direction.z * mult) + r.origin.z;
203 if ((cubeZ - cubeSize) < hitZ)
204 if ((cubeZ + cubeSize) > hitZ) {
205 r.hitPoint = new Point3D(cubeX + cubeSize, hitY,
217 public void fillRectangle(IntegerPoint p1, IntegerPoint p2, Color color) {
219 int x1 = min(p1.x, p2.x);
220 int x2 = max(p1.x, p2.x);
221 int y1 = min(p1.y, p2.y);
222 int y2 = max(p1.y, p2.y);
223 int z1 = min(p1.z, p2.z);
224 int z2 = max(p1.z, p2.z);
226 for (int x = x1; x <= x2; x++)
227 for (int y = y1; y <= y2; y++)
228 for (int z = z1; z <= z2; z++)
229 putCell(x, y, z, 0, 0, 0, masterCellSize, 0, color);
232 public int getCellColor(final int pointer) {
233 return cell2[pointer];
236 public int getCellIllumination(final int pointer) {
237 return cell3[pointer];
240 public void initWorld(final int bufferLength, final int masterCellSize) {
241 // System.out.println("Initializing new world");
243 // initialize world storage buffer
244 this.masterCellSize = masterCellSize;
246 cell1 = new int[bufferLength];
247 cell2 = new int[bufferLength];
248 cell3 = new int[bufferLength];
249 cell4 = new int[bufferLength];
251 cell5 = new int[bufferLength];
252 cell6 = new int[bufferLength];
253 cell7 = new int[bufferLength];
254 cell8 = new int[bufferLength];
256 for (int i = 0; i < bufferLength; i++)
257 cell1[i] = CELL_STATE_UNUSED;
259 // initialize master cell
263 public boolean isCellSolid(final int pointer) {
264 return cell1[pointer] == CELL_STATE_SOLID;
268 * Scans cells arrays and returns pointer to found unused cell.
269 * @return pointer to found unused cell
271 public int getNewCellPointer() {
273 // ensure that cell allocation pointer is in bounds
274 if (cellAllocationPointer >= cell1.length)
275 cellAllocationPointer = 0;
277 if (cell1[cellAllocationPointer] == CELL_STATE_UNUSED) {
279 clearCell(cellAllocationPointer);
282 return cellAllocationPointer;
284 cellAllocationPointer++;
288 public int makeNewCell(final int color, final int illumination) {
289 final int pointer = getNewCellPointer();
290 markCellAsSolid(pointer);
291 setCellColor(pointer, color);
292 setCellIllumination(pointer, illumination);
297 * Mark cell as solid.
299 * @param pointer pointer to cell
301 public void markCellAsSolid(final int pointer) {
302 cell1[pointer] = CELL_STATE_SOLID;
305 public void putCell(final int x, final int y, final int z, final Color color) {
306 putCell(x, y, z, 0, 0, 0, masterCellSize, 0, color);
309 private void putCell(final int x, final int y, final int z,
310 final int cellX, final int cellY, final int cellZ,
311 final int cellSize, final int cellPointer, final Color color) {
315 // if case of big cell
316 if (isCellSolid(cellPointer)) {
318 // if cell is already a needed color, do notheing
319 if (getCellColor(cellPointer) == color.toInt())
322 // otherwise break cell up
323 breakSolidCell(cellPointer);
325 // continue, as if it is cluster now
328 // decide witch subcube to use
330 int subX, subY, subZ;
333 subX = (cellSize / 2) + cellX;
335 subY = (cellSize / 2) + cellY;
337 subZ = (cellSize / 2) + cellZ;
339 subCubeArray = cell7;
341 subZ = (-cellSize / 2) + cellZ;
343 subCubeArray = cell3;
346 subY = (-cellSize / 2) + cellY;
348 subZ = (cellSize / 2) + cellZ;
350 subCubeArray = cell6;
352 subZ = (-cellSize / 2) + cellZ;
354 subCubeArray = cell2;
358 subX = (-cellSize / 2) + cellX;
360 subY = (cellSize / 2) + cellY;
362 subZ = (cellSize / 2) + cellZ;
364 subCubeArray = cell8;
366 subZ = (-cellSize / 2) + cellZ;
368 subCubeArray = cell4;
371 subY = (-cellSize / 2) + cellY;
373 subZ = (cellSize / 2) + cellZ;
375 subCubeArray = cell5;
377 subZ = (-cellSize / 2) + cellZ;
379 subCubeArray = cell1;
385 if (subCubeArray[cellPointer] == 0) {
386 // create empty cluster
387 subCubePointer = getNewCellPointer();
388 subCubeArray[cellPointer] = subCubePointer;
390 subCubePointer = subCubeArray[cellPointer];
392 putCell(x, y, z, subX, subY, subZ, cellSize / 2, subCubePointer,
395 cell1[cellPointer] = CELL_STATE_SOLID;
396 cell2[cellPointer] = color.toInt();
397 cell3[cellPointer] = CELL_STATE_UNUSED;
398 // System.out.println("Cell written!");
402 public void setCellColor(final int pointer, final int color) {
403 cell2[pointer] = color;
406 public void setCellIllumination(final int pointer, final int illumination) {
407 cell3[pointer] = illumination;
411 * Trace ray through the world and return pointer to intersecting cell.
413 * @return pointer to intersecting cell or TRACE_NO_HIT if no intersection.
415 public int traceCell(final int cellX, final int cellY, final int cellZ,
416 final int cellSize, final int pointer, final Ray ray) {
417 if (isCellSolid(pointer)) {
419 if (doesIntersect(cellX, cellY, cellZ, cellSize, ray) != 0) {
420 ray.hitCellSize = cellSize;
421 ray.hitCellX = cellX;
422 ray.hitCellY = cellY;
423 ray.hitCellZ = cellZ;
428 if (doesIntersect(cellX, cellY, cellZ, cellSize, ray) != 0) {
429 final int halfOfCellSize = cellSize / 2;
430 int rayIntersectionResult;
432 if (ray.origin.x > cellX) {
433 if (ray.origin.y > cellY) {
434 if (ray.origin.z > cellZ) {
438 if (cell7[pointer] != 0) {
439 rayIntersectionResult = traceCell(cellX
440 + halfOfCellSize, cellY + halfOfCellSize,
441 cellZ + halfOfCellSize, halfOfCellSize,
442 cell7[pointer], ray);
443 if (rayIntersectionResult >= 0)
444 return rayIntersectionResult;
446 if (cell6[pointer] != 0) {
447 rayIntersectionResult = traceCell(cellX
448 + halfOfCellSize, cellY - halfOfCellSize,
449 cellZ + halfOfCellSize, halfOfCellSize,
450 cell6[pointer], ray);
451 if (rayIntersectionResult >= 0)
452 return rayIntersectionResult;
454 if (cell8[pointer] != 0) {
455 rayIntersectionResult = traceCell(cellX
456 - halfOfCellSize, cellY + halfOfCellSize,
457 cellZ + halfOfCellSize, halfOfCellSize,
458 cell8[pointer], ray);
459 if (rayIntersectionResult >= 0)
460 return rayIntersectionResult;
462 if (cell3[pointer] != 0) {
463 rayIntersectionResult = traceCell(cellX
464 + halfOfCellSize, cellY + halfOfCellSize,
465 cellZ - halfOfCellSize, halfOfCellSize,
466 cell3[pointer], ray);
467 if (rayIntersectionResult >= 0)
468 return rayIntersectionResult;
471 if (cell2[pointer] != 0) {
472 rayIntersectionResult = traceCell(cellX
473 + halfOfCellSize, cellY - halfOfCellSize,
474 cellZ - halfOfCellSize, halfOfCellSize,
475 cell2[pointer], ray);
476 if (rayIntersectionResult >= 0)
477 return rayIntersectionResult;
479 if (cell4[pointer] != 0) {
480 rayIntersectionResult = traceCell(cellX
481 - halfOfCellSize, cellY + halfOfCellSize,
482 cellZ - halfOfCellSize, halfOfCellSize,
483 cell4[pointer], ray);
484 if (rayIntersectionResult >= 0)
485 return rayIntersectionResult;
488 if (cell5[pointer] != 0) {
489 rayIntersectionResult = traceCell(cellX
490 - halfOfCellSize, cellY - halfOfCellSize,
491 cellZ + halfOfCellSize, halfOfCellSize,
492 cell5[pointer], ray);
493 if (rayIntersectionResult >= 0)
494 return rayIntersectionResult;
497 if (cell1[pointer] != 0) {
498 rayIntersectionResult = traceCell(cellX
499 - halfOfCellSize, cellY - halfOfCellSize,
500 cellZ - halfOfCellSize, halfOfCellSize,
501 cell1[pointer], ray);
502 if (rayIntersectionResult >= 0)
503 return rayIntersectionResult;
509 if (cell3[pointer] != 0) {
510 rayIntersectionResult = traceCell(cellX
511 + halfOfCellSize, cellY + halfOfCellSize,
512 cellZ - halfOfCellSize, halfOfCellSize,
513 cell3[pointer], ray);
514 if (rayIntersectionResult >= 0)
515 return rayIntersectionResult;
518 if (cell2[pointer] != 0) {
519 rayIntersectionResult = traceCell(cellX
520 + halfOfCellSize, cellY - halfOfCellSize,
521 cellZ - halfOfCellSize, halfOfCellSize,
522 cell2[pointer], ray);
523 if (rayIntersectionResult >= 0)
524 return rayIntersectionResult;
526 if (cell4[pointer] != 0) {
527 rayIntersectionResult = traceCell(cellX
528 - halfOfCellSize, cellY + halfOfCellSize,
529 cellZ - halfOfCellSize, halfOfCellSize,
530 cell4[pointer], ray);
531 if (rayIntersectionResult >= 0)
532 return rayIntersectionResult;
535 if (cell7[pointer] != 0) {
536 rayIntersectionResult = traceCell(cellX
537 + halfOfCellSize, cellY + halfOfCellSize,
538 cellZ + halfOfCellSize, halfOfCellSize,
539 cell7[pointer], ray);
540 if (rayIntersectionResult >= 0)
541 return rayIntersectionResult;
543 if (cell6[pointer] != 0) {
544 rayIntersectionResult = traceCell(cellX
545 + halfOfCellSize, cellY - halfOfCellSize,
546 cellZ + halfOfCellSize, halfOfCellSize,
547 cell6[pointer], ray);
548 if (rayIntersectionResult >= 0)
549 return rayIntersectionResult;
551 if (cell8[pointer] != 0) {
552 rayIntersectionResult = traceCell(cellX
553 - halfOfCellSize, cellY + halfOfCellSize,
554 cellZ + halfOfCellSize, halfOfCellSize,
555 cell8[pointer], ray);
556 if (rayIntersectionResult >= 0)
557 return rayIntersectionResult;
560 if (cell1[pointer] != 0) {
561 rayIntersectionResult = traceCell(cellX
562 - halfOfCellSize, cellY - halfOfCellSize,
563 cellZ - halfOfCellSize, halfOfCellSize,
564 cell1[pointer], ray);
565 if (rayIntersectionResult >= 0)
566 return rayIntersectionResult;
569 if (cell5[pointer] != 0) {
570 rayIntersectionResult = traceCell(cellX
571 - halfOfCellSize, cellY - halfOfCellSize,
572 cellZ + halfOfCellSize, halfOfCellSize,
573 cell5[pointer], ray);
574 if (rayIntersectionResult >= 0)
575 return rayIntersectionResult;
579 } else if (ray.origin.z > cellZ) {
582 if (cell6[pointer] != 0) {
583 rayIntersectionResult = traceCell(cellX
584 + halfOfCellSize, cellY - halfOfCellSize, cellZ
585 + halfOfCellSize, halfOfCellSize, cell6[pointer],
587 if (rayIntersectionResult >= 0)
588 return rayIntersectionResult;
591 if (cell7[pointer] != 0) {
592 rayIntersectionResult = traceCell(cellX
593 + halfOfCellSize, cellY + halfOfCellSize, cellZ
594 + halfOfCellSize, halfOfCellSize, cell7[pointer],
596 if (rayIntersectionResult >= 0)
597 return rayIntersectionResult;
599 if (cell2[pointer] != 0) {
600 rayIntersectionResult = traceCell(cellX
601 + halfOfCellSize, cellY - halfOfCellSize, cellZ
602 - halfOfCellSize, halfOfCellSize, cell2[pointer],
604 if (rayIntersectionResult >= 0)
605 return rayIntersectionResult;
607 if (cell5[pointer] != 0) {
608 rayIntersectionResult = traceCell(cellX
609 - halfOfCellSize, cellY - halfOfCellSize, cellZ
610 + halfOfCellSize, halfOfCellSize, cell5[pointer],
612 if (rayIntersectionResult >= 0)
613 return rayIntersectionResult;
615 if (cell8[pointer] != 0) {
616 rayIntersectionResult = traceCell(cellX
617 - halfOfCellSize, cellY + halfOfCellSize, cellZ
618 + halfOfCellSize, halfOfCellSize, cell8[pointer],
620 if (rayIntersectionResult >= 0)
621 return rayIntersectionResult;
623 if (cell3[pointer] != 0) {
624 rayIntersectionResult = traceCell(cellX
625 + halfOfCellSize, cellY + halfOfCellSize, cellZ
626 - halfOfCellSize, halfOfCellSize, cell3[pointer],
628 if (rayIntersectionResult >= 0)
629 return rayIntersectionResult;
632 if (cell1[pointer] != 0) {
633 rayIntersectionResult = traceCell(cellX
634 - halfOfCellSize, cellY - halfOfCellSize, cellZ
635 - halfOfCellSize, halfOfCellSize, cell1[pointer],
637 if (rayIntersectionResult >= 0)
638 return rayIntersectionResult;
640 if (cell4[pointer] != 0) {
641 rayIntersectionResult = traceCell(cellX
642 - halfOfCellSize, cellY + halfOfCellSize, cellZ
643 - halfOfCellSize, halfOfCellSize, cell4[pointer],
645 if (rayIntersectionResult >= 0)
646 return rayIntersectionResult;
652 if (cell2[pointer] != 0) {
653 rayIntersectionResult = traceCell(cellX
654 + halfOfCellSize, cellY - halfOfCellSize, cellZ
655 - halfOfCellSize, halfOfCellSize, cell2[pointer],
657 if (rayIntersectionResult >= 0)
658 return rayIntersectionResult;
661 if (cell3[pointer] != 0) {
662 rayIntersectionResult = traceCell(cellX
663 + halfOfCellSize, cellY + halfOfCellSize, cellZ
664 - halfOfCellSize, halfOfCellSize, cell3[pointer],
666 if (rayIntersectionResult >= 0)
667 return rayIntersectionResult;
670 if (cell1[pointer] != 0) {
671 rayIntersectionResult = traceCell(cellX
672 - halfOfCellSize, cellY - halfOfCellSize, cellZ
673 - halfOfCellSize, halfOfCellSize, cell1[pointer],
675 if (rayIntersectionResult >= 0)
676 return rayIntersectionResult;
678 if (cell6[pointer] != 0) {
679 rayIntersectionResult = traceCell(cellX
680 + halfOfCellSize, cellY - halfOfCellSize, cellZ
681 + halfOfCellSize, halfOfCellSize, cell6[pointer],
683 if (rayIntersectionResult >= 0)
684 return rayIntersectionResult;
687 if (cell7[pointer] != 0) {
688 rayIntersectionResult = traceCell(cellX
689 + halfOfCellSize, cellY + halfOfCellSize, cellZ
690 + halfOfCellSize, halfOfCellSize, cell7[pointer],
692 if (rayIntersectionResult >= 0)
693 return rayIntersectionResult;
695 if (cell5[pointer] != 0) {
696 rayIntersectionResult = traceCell(cellX
697 - halfOfCellSize, cellY - halfOfCellSize, cellZ
698 + halfOfCellSize, halfOfCellSize, cell5[pointer],
700 if (rayIntersectionResult >= 0)
701 return rayIntersectionResult;
703 if (cell4[pointer] != 0) {
704 rayIntersectionResult = traceCell(cellX
705 - halfOfCellSize, cellY + halfOfCellSize, cellZ
706 - halfOfCellSize, halfOfCellSize, cell4[pointer],
708 if (rayIntersectionResult >= 0)
709 return rayIntersectionResult;
711 if (cell8[pointer] != 0) {
712 rayIntersectionResult = traceCell(cellX
713 - halfOfCellSize, cellY + halfOfCellSize, cellZ
714 + halfOfCellSize, halfOfCellSize, cell8[pointer],
716 if (rayIntersectionResult >= 0)
717 return rayIntersectionResult;
721 } else if (ray.origin.y > cellY) {
722 if (ray.origin.z > cellZ) {
726 if (cell8[pointer] != 0) {
727 rayIntersectionResult = traceCell(cellX
728 - halfOfCellSize, cellY + halfOfCellSize, cellZ
729 + halfOfCellSize, halfOfCellSize, cell8[pointer],
731 if (rayIntersectionResult >= 0)
732 return rayIntersectionResult;
734 if (cell7[pointer] != 0) {
735 rayIntersectionResult = traceCell(cellX
736 + halfOfCellSize, cellY + halfOfCellSize, cellZ
737 + halfOfCellSize, halfOfCellSize, cell7[pointer],
739 if (rayIntersectionResult >= 0)
740 return rayIntersectionResult;
742 if (cell5[pointer] != 0) {
743 rayIntersectionResult = traceCell(cellX
744 - halfOfCellSize, cellY - halfOfCellSize, cellZ
745 + halfOfCellSize, halfOfCellSize, cell5[pointer],
747 if (rayIntersectionResult >= 0)
748 return rayIntersectionResult;
750 if (cell4[pointer] != 0) {
751 rayIntersectionResult = traceCell(cellX
752 - halfOfCellSize, cellY + halfOfCellSize, cellZ
753 - halfOfCellSize, halfOfCellSize, cell4[pointer],
755 if (rayIntersectionResult >= 0)
756 return rayIntersectionResult;
759 if (cell3[pointer] != 0) {
760 rayIntersectionResult = traceCell(cellX
761 + halfOfCellSize, cellY + halfOfCellSize, cellZ
762 - halfOfCellSize, halfOfCellSize, cell3[pointer],
764 if (rayIntersectionResult >= 0)
765 return rayIntersectionResult;
768 if (cell1[pointer] != 0) {
769 rayIntersectionResult = traceCell(cellX
770 - halfOfCellSize, cellY - halfOfCellSize, cellZ
771 - halfOfCellSize, halfOfCellSize, cell1[pointer],
773 if (rayIntersectionResult >= 0)
774 return rayIntersectionResult;
776 if (cell6[pointer] != 0) {
777 rayIntersectionResult = traceCell(cellX
778 + halfOfCellSize, cellY - halfOfCellSize, cellZ
779 + halfOfCellSize, halfOfCellSize, cell6[pointer],
781 if (rayIntersectionResult >= 0)
782 return rayIntersectionResult;
785 if (cell2[pointer] != 0) {
786 rayIntersectionResult = traceCell(cellX
787 + halfOfCellSize, cellY - halfOfCellSize, cellZ
788 - halfOfCellSize, halfOfCellSize, cell2[pointer],
790 if (rayIntersectionResult >= 0)
791 return rayIntersectionResult;
798 if (cell4[pointer] != 0) {
799 rayIntersectionResult = traceCell(cellX
800 - halfOfCellSize, cellY + halfOfCellSize, cellZ
801 - halfOfCellSize, halfOfCellSize, cell4[pointer],
803 if (rayIntersectionResult >= 0)
804 return rayIntersectionResult;
807 if (cell8[pointer] != 0) {
808 rayIntersectionResult = traceCell(cellX
809 - halfOfCellSize, cellY + halfOfCellSize, cellZ
810 + halfOfCellSize, halfOfCellSize, cell8[pointer],
812 if (rayIntersectionResult >= 0)
813 return rayIntersectionResult;
815 if (cell3[pointer] != 0) {
816 rayIntersectionResult = traceCell(cellX
817 + halfOfCellSize, cellY + halfOfCellSize, cellZ
818 - halfOfCellSize, halfOfCellSize, cell3[pointer],
820 if (rayIntersectionResult >= 0)
821 return rayIntersectionResult;
824 if (cell1[pointer] != 0) {
825 rayIntersectionResult = traceCell(cellX
826 - halfOfCellSize, cellY - halfOfCellSize, cellZ
827 - halfOfCellSize, halfOfCellSize, cell1[pointer],
829 if (rayIntersectionResult >= 0)
830 return rayIntersectionResult;
832 if (cell7[pointer] != 0) {
833 rayIntersectionResult = traceCell(cellX
834 + halfOfCellSize, cellY + halfOfCellSize, cellZ
835 + halfOfCellSize, halfOfCellSize, cell7[pointer],
837 if (rayIntersectionResult >= 0)
838 return rayIntersectionResult;
840 if (cell5[pointer] != 0) {
841 rayIntersectionResult = traceCell(cellX
842 - halfOfCellSize, cellY - halfOfCellSize, cellZ
843 + halfOfCellSize, halfOfCellSize, cell5[pointer],
845 if (rayIntersectionResult >= 0)
846 return rayIntersectionResult;
849 if (cell2[pointer] != 0) {
850 rayIntersectionResult = traceCell(cellX
851 + halfOfCellSize, cellY - halfOfCellSize, cellZ
852 - halfOfCellSize, halfOfCellSize, cell2[pointer],
854 if (rayIntersectionResult >= 0)
855 return rayIntersectionResult;
857 if (cell6[pointer] != 0) {
858 rayIntersectionResult = traceCell(cellX
859 + halfOfCellSize, cellY - halfOfCellSize, cellZ
860 + halfOfCellSize, halfOfCellSize, cell6[pointer],
862 if (rayIntersectionResult >= 0)
863 return rayIntersectionResult;
867 } else if (ray.origin.z > cellZ) {
871 if (cell5[pointer] != 0) {
872 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
873 cellY - halfOfCellSize, cellZ + halfOfCellSize,
874 halfOfCellSize, cell5[pointer], ray);
875 if (rayIntersectionResult >= 0)
876 return rayIntersectionResult;
879 if (cell1[pointer] != 0) {
880 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
881 cellY - halfOfCellSize, cellZ - halfOfCellSize,
882 halfOfCellSize, cell1[pointer], ray);
883 if (rayIntersectionResult >= 0)
884 return rayIntersectionResult;
887 if (cell6[pointer] != 0) {
888 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
889 cellY - halfOfCellSize, cellZ + halfOfCellSize,
890 halfOfCellSize, cell6[pointer], ray);
891 if (rayIntersectionResult >= 0)
892 return rayIntersectionResult;
895 if (cell8[pointer] != 0) {
896 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
897 cellY + halfOfCellSize, cellZ + halfOfCellSize,
898 halfOfCellSize, cell8[pointer], ray);
899 if (rayIntersectionResult >= 0)
900 return rayIntersectionResult;
903 if (cell4[pointer] != 0) {
904 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
905 cellY + halfOfCellSize, cellZ - halfOfCellSize,
906 halfOfCellSize, cell4[pointer], ray);
907 if (rayIntersectionResult >= 0)
908 return rayIntersectionResult;
911 if (cell7[pointer] != 0) {
912 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
913 cellY + halfOfCellSize, cellZ + halfOfCellSize,
914 halfOfCellSize, cell7[pointer], ray);
915 if (rayIntersectionResult >= 0)
916 return rayIntersectionResult;
919 if (cell2[pointer] != 0) {
920 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
921 cellY - halfOfCellSize, cellZ - halfOfCellSize,
922 halfOfCellSize, cell2[pointer], ray);
923 if (rayIntersectionResult >= 0)
924 return rayIntersectionResult;
927 if (cell3[pointer] != 0) {
928 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
929 cellY + halfOfCellSize, cellZ - halfOfCellSize,
930 halfOfCellSize, cell3[pointer], ray);
931 if (rayIntersectionResult >= 0)
932 return rayIntersectionResult;
939 if (cell1[pointer] != 0) {
940 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
941 cellY - halfOfCellSize, cellZ - halfOfCellSize,
942 halfOfCellSize, cell1[pointer], ray);
943 if (rayIntersectionResult >= 0)
944 return rayIntersectionResult;
947 if (cell5[pointer] != 0) {
948 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
949 cellY - halfOfCellSize, cellZ + halfOfCellSize,
950 halfOfCellSize, cell5[pointer], ray);
951 if (rayIntersectionResult >= 0)
952 return rayIntersectionResult;
954 if (cell2[pointer] != 0) {
955 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
956 cellY - halfOfCellSize, cellZ - halfOfCellSize,
957 halfOfCellSize, cell2[pointer], ray);
958 if (rayIntersectionResult >= 0)
959 return rayIntersectionResult;
962 if (cell4[pointer] != 0) {
963 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
964 cellY + halfOfCellSize, cellZ - halfOfCellSize,
965 halfOfCellSize, cell4[pointer], ray);
966 if (rayIntersectionResult >= 0)
967 return rayIntersectionResult;
970 if (cell6[pointer] != 0) {
971 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
972 cellY - halfOfCellSize, cellZ + halfOfCellSize,
973 halfOfCellSize, cell6[pointer], ray);
974 if (rayIntersectionResult >= 0)
975 return rayIntersectionResult;
978 if (cell8[pointer] != 0) {
979 rayIntersectionResult = traceCell(cellX - halfOfCellSize,
980 cellY + halfOfCellSize, cellZ + halfOfCellSize,
981 halfOfCellSize, cell8[pointer], ray);
982 if (rayIntersectionResult >= 0)
983 return rayIntersectionResult;
986 if (cell3[pointer] != 0) {
987 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
988 cellY + halfOfCellSize, cellZ - halfOfCellSize,
989 halfOfCellSize, cell3[pointer], ray);
990 if (rayIntersectionResult >= 0)
991 return rayIntersectionResult;
993 if (cell7[pointer] != 0) {
994 rayIntersectionResult = traceCell(cellX + halfOfCellSize,
995 cellY + halfOfCellSize, cellZ + halfOfCellSize,
996 halfOfCellSize, cell7[pointer], ray);
997 if (rayIntersectionResult >= 0)
998 return rayIntersectionResult;
1002 return TRACE_NO_HIT;