src/kdtree.cc
author Radek Brich <radek.brich@devl.cz>
Tue, 22 Apr 2008 13:33:12 +0200
branchpyrit
changeset 77 dbe8438d5dca
parent 76 3b60fd0bea64
child 78 9569e9f35374
permissions -rw-r--r--
rewrite subsampling from old code to DefaultSampler render in phases, clean workers after each phase
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
34
28f6e8b9d5d1 quaternion moved to extra header file
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
     1
/*
44
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     2
 * kdtree.cc: KdTree class
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     3
 *
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     4
 * This file is part of Pyrit Ray Tracer.
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     5
 *
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     6
 * Copyright 2006, 2007  Radek Brich
34
28f6e8b9d5d1 quaternion moved to extra header file
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
     7
 *
44
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
     9
 * of this software and associated documentation files (the "Software"), to deal
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    10
 * in the Software without restriction, including without limitation the rights
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    11
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    12
 * copies of the Software, and to permit persons to whom the Software is
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    13
 * furnished to do so, subject to the following conditions:
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    14
 *
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    15
 * The above copyright notice and this permission notice shall be included in
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    16
 * all copies or substantial portions of the Software.
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    17
 *
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    23
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3763b26244f0 MIT license for sources
Radek Brich <radek.brich@devl.cz>
parents: 42
diff changeset
    24
 * THE SOFTWARE.
34
28f6e8b9d5d1 quaternion moved to extra header file
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    25
 */
28f6e8b9d5d1 quaternion moved to extra header file
Radek Brich <radek.brich@devl.cz>
parents: 30
diff changeset
    26
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    27
#include <algorithm>
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    28
#include <stack>
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    29
20
f22952603f29 new C++ demo: realtime.cc (real-time scene viewer using SDL)
Radek Brich <radek.brich@devl.cz>
parents: 17
diff changeset
    30
#include "common.h"
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    31
#include "kdtree.h"
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    32
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    33
class ShapeBound
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    34
{
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    35
public:
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    36
	Shape *shape;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    37
	Float pos;
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    38
	bool end;
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    39
	ShapeBound(Shape *ashape, const Float apos, const bool aend):
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    40
		shape(ashape), pos(apos), end(aend) {};
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    41
	friend bool operator<(const ShapeBound& a, const ShapeBound& b)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    42
	{
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    43
		if (a.pos == b.pos)
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    44
			return a.shape < b.shape;
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    45
		else
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    46
			return a.pos < b.pos;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    47
	};
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    48
};
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    49
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    50
// stack element for kd-tree traversal
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
    51
struct StackElem
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    52
{
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    53
	KdNode* node; /* pointer to far child */
22
76b7bd51d64a new make infrastructure
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
    54
	Float t; /* the entry/exit signed distance */
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    55
	Vector3 pb; /* the coordinates of entry/exit point */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
    56
	int prev;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    57
};
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    58
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    59
// ----------------------------------------
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
    60
16
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    61
KdNode::~KdNode()
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    62
{
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    63
	if (isLeaf())
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
    64
		delete getShapes();
16
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    65
	else
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
    66
		delete[] getLeftChild();
16
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    67
}
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
    68
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    69
// kd-tree recursive build algorithm, inspired by PBRT (www.pbrt.org)
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    70
void KdTree::recursive_build(KdNode *node, BBox bounds, int maxdepth)
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
    71
{
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    72
	ShapeList *shapes = node->getShapes();
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    73
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    74
	if (maxdepth <= 0 || shapes->size() <= 2)
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
    75
	{
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    76
		node->setLeaf();
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
    77
		return;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
    78
	}
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
    79
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    80
	// choose split axis
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    81
	/*axis = 0;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    82
	if (bounds.h() > bounds.w() && bounds.h() > bounds.d())
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    83
		axis = 1;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    84
	if (bounds.d() > bounds.w() && bounds.d() > bounds.h())
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    85
		axis = 2;
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    86
*/
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    87
	// create sorted list of shape bounds (= find all posible splits)
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    88
	vector<ShapeBound> edges[3];
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    89
	ShapeList::iterator shape;
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
    90
	for (shape = shapes->begin(); shape != shapes->end(); shape++)
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    91
	{
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
    92
		BBox shapebounds = (*shape)->get_bbox();
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    93
		for (int ax = 0; ax < 3; ax++)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    94
		{
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    95
			edges[ax].push_back(ShapeBound(*shape, shapebounds.L[ax], 0));
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    96
			edges[ax].push_back(ShapeBound(*shape, shapebounds.H[ax], 1));
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    97
		}
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
    98
	}
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
    99
	for (int ax = 0; ax < 3; ax++)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   100
		sort(edges[ax].begin(), edges[ax].end());
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
   101
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
   102
	// choose best split pos
22
76b7bd51d64a new make infrastructure
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   103
	const Float K = 1.4; // constant, K = cost of traversal / cost of ray-triangle intersection
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   104
	Float SAV = (bounds.w()*bounds.h() +  // surface area of node
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   105
		bounds.w()*bounds.d() + bounds.h()*bounds.d());
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   106
	Float cost = SAV * (K + shapes->size()); // initial cost = non-split cost
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   107
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   108
	vector<ShapeBound>::iterator edge, splitedge = edges[2].end();
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   109
	int axis = 0;
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   110
	for (int ax = 0; ax < 3; ax++)
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
   111
	{
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   112
		int lnum = 0, rnum = shapes->size();
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   113
		BBox lbb = bounds;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   114
		BBox rbb = bounds;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   115
		for (edge = edges[ax].begin(); edge != edges[ax].end(); edge++)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   116
		{
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   117
			if (edge->end)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   118
				rnum--;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   119
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   120
			// calculate SAH cost of this split
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   121
			lbb.H.cell[ax] = edge->pos;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   122
			rbb.L.cell[ax] = edge->pos;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   123
			Float SAL = (lbb.w()*lbb.h() + lbb.w()*lbb.d() + lbb.h()*lbb.d());
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   124
			Float SAR = (rbb.w()*rbb.h() + rbb.w()*rbb.d() + rbb.h()*rbb.d());
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   125
			Float splitcost = K*SAV + SAL*(K + lnum) + SAR*(K + rnum);
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   126
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   127
			if (splitcost < cost)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   128
			{
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   129
				axis = ax;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   130
				splitedge = edge;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   131
				cost = splitcost;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   132
			}
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   133
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   134
			if (!edge->end)
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   135
				lnum++;
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   136
		}
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
   137
	}
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   138
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   139
	if (splitedge == edges[2].end())
15
a0a3e334744f C++ demos: prepare infrastructure, add spheres_shadow.cc
Radek Brich <radek.brich@devl.cz>
parents: 14
diff changeset
   140
	{
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   141
		node->setLeaf();
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   142
		return;
15
a0a3e334744f C++ demos: prepare infrastructure, add spheres_shadow.cc
Radek Brich <radek.brich@devl.cz>
parents: 14
diff changeset
   143
	}
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   144
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   145
	node->setSplit(splitedge->pos);
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   146
29
574c34441a1c new C++ demo: realtime_bunny
Radek Brich <radek.brich@devl.cz>
parents: 28
diff changeset
   147
#if 0
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   148
// export kd-tree as .obj for visualization
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   149
// this would be hard to reconstruct later
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   150
	static ofstream F("kdtree.obj");
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   151
	Vector3 v;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   152
	static int f=0;
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   153
	v.cell[axis] = node->getSplit();
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   154
	v.cell[(axis+1)%3] = bounds.L.cell[(axis+1)%3];
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   155
	v.cell[(axis+2)%3] = bounds.L.cell[(axis+2)%3];
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   156
	F << "v " << v.x << " " << v.y << " " << v.z << endl;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   157
	v.cell[(axis+1)%3] = bounds.L.cell[(axis+1)%3];
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   158
	v.cell[(axis+2)%3] = bounds.H.cell[(axis+2)%3];
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   159
	F << "v " << v.x << " " << v.y << " " << v.z << endl;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   160
	v.cell[(axis+1)%3] = bounds.H.cell[(axis+1)%3];
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   161
	v.cell[(axis+2)%3] = bounds.H.cell[(axis+2)%3];
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   162
	F << "v " << v.x << " " << v.y << " " << v.z << endl;
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   163
	v.cell[(axis+1)%3] = bounds.H.cell[(axis+1)%3];
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   164
	v.cell[(axis+2)%3] = bounds.L.cell[(axis+2)%3];
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   165
	F << "v " << v.x << " " << v.y << " " << v.z << endl;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   166
	F << "f " << f+1 << " " << f+2 << " " << f+3 << " " << f+4 << endl;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   167
	f += 4;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   168
#endif
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   169
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   170
	// split this node
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   171
	delete shapes;
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   172
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   173
	BBox lbb = bounds;
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   174
	BBox rbb = bounds;
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   175
	lbb.H.cell[axis] = node->getSplit();
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   176
	rbb.L.cell[axis] = node->getSplit();
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   177
	node->setChildren(new KdNode[2]);
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   178
	node->setAxis(axis);
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   179
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   180
	for (edge = edges[axis].begin(); edge != splitedge; edge++)
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   181
		if (!edge->end && edge->shape->intersect_bbox(lbb))
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   182
			node->getLeftChild()->addShape(edge->shape);
71
4fedf7290929 simplify kd-tree building, it's also much faster now
Radek Brich <radek.brich@devl.cz>
parents: 44
diff changeset
   183
	for (edge = splitedge; edge < edges[axis].end(); edge++)
72
7c3f38dff082 kd-tree building - check all axes for best split, add additional shape-bbox check
Radek Brich <radek.brich@devl.cz>
parents: 71
diff changeset
   184
		if (edge->end && edge->shape->intersect_bbox(rbb))
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   185
			node->getRightChild()->addShape(edge->shape);
9
3239f749e394 kd-tree: build algorithm - completed, untested
Radek Brich <radek.brich@devl.cz>
parents: 7
diff changeset
   186
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   187
	recursive_build(node->getLeftChild(), lbb, maxdepth-1);
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   188
	recursive_build(node->getRightChild(), rbb, maxdepth-1);
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   189
}
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   190
11
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   191
void KdTree::build()
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   192
{
30
33f95441790e pyrit_verbosity: new variable for controlling amount of output, see common.h
Radek Brich <radek.brich@devl.cz>
parents: 29
diff changeset
   193
	dbgmsg(1, "* building kd-tree\n");
7
bf17f9f84c91 kd-tree: build algorithm - searching for all posible splits
Radek Brich <radek.brich@devl.cz>
parents: 0
diff changeset
   194
	root = new KdNode();
17
5176ba000a67 fix last leak as reported by valgrind
Radek Brich <radek.brich@devl.cz>
parents: 16
diff changeset
   195
	ShapeList::iterator shape;
5176ba000a67 fix last leak as reported by valgrind
Radek Brich <radek.brich@devl.cz>
parents: 16
diff changeset
   196
	for (shape = shapes.begin(); shape != shapes.end(); shape++)
5176ba000a67 fix last leak as reported by valgrind
Radek Brich <radek.brich@devl.cz>
parents: 16
diff changeset
   197
		root->addShape(*shape);
76
3b60fd0bea64 kd-tree: move recursive build subroutine from KdNode to KdTree
Radek Brich <radek.brich@devl.cz>
parents: 74
diff changeset
   198
	recursive_build(root, bbox, max_depth);
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   199
	built = true;
0
3547b885df7e initial commit, raytracer source as written year ago and unchanged since 2007-03-25
Radek Brich <radek.brich@devl.cz>
parents:
diff changeset
   200
}
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   201
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   202
/* algorithm by Vlastimil Havran, Heuristic Ray Shooting Algorithms, appendix C */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   203
Shape *KdTree::nearest_intersection(const Shape *origin_shape, const Ray &ray,
22
76b7bd51d64a new make infrastructure
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   204
	Float &nearest_distance)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   205
{
22
76b7bd51d64a new make infrastructure
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   206
	Float a, b; /* entry/exit signed distance */
76b7bd51d64a new make infrastructure
Radek Brich <radek.brich@devl.cz>
parents: 21
diff changeset
   207
	Float t;    /* signed distance to the splitting plane */
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   208
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   209
	/* if we have no tree, fall back to naive test */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   210
	if (!built)
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   211
		return Container::nearest_intersection(origin_shape, ray, nearest_distance);
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   212
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   213
	if (!bbox.intersect(ray, a, b))
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   214
		return NULL;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   215
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   216
	/* pointers to the far child node and current node */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   217
	KdNode *farchild, *node;
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   218
	node = root;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   219
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   220
	StackElem stack[max_depth];
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   221
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   222
	int entry = 0, exit = 1;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   223
	stack[entry].t = a;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   224
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   225
	/* distinguish between internal and external origin of a ray*/
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   226
	if (a >= 0.0)
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   227
		stack[entry].pb = ray.o + ray.dir * a; /* external */
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   228
	else
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   229
		stack[entry].pb = ray.o;               /* internal */
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   230
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   231
	/* setup initial exit point in the stack */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   232
	stack[exit].t = b;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   233
	stack[exit].pb = ray.o + ray.dir * b;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   234
	stack[exit].node = NULL;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   235
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   236
	/* loop, traverse through the whole kd-tree, until an object is intersected or ray leaves the scene */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   237
	Float splitVal;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   238
	int axis;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   239
	static const int mod3[] = {0,1,2,0,1};
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   240
	const Vector3 invdir = 1 / ray.dir;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   241
	while (node)
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   242
	{
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   243
		/* loop until a leaf is found */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   244
		while (!node->isLeaf())
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   245
		{
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   246
			/* retrieve position of splitting plane */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   247
			splitVal = node->getSplit();
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   248
			axis = node->getAxis();
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   249
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   250
			if (stack[entry].pb[axis] <= splitVal)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   251
			{
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   252
				if (stack[exit].pb[axis] <= splitVal)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   253
				{ /* case N1, N2, N3, P5, Z2, and Z3 */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   254
					node = node->getLeftChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   255
					continue;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   256
				}
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   257
				if (stack[exit].pb[axis] == splitVal)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   258
				{ /* case Z1 */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   259
					node = node->getRightChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   260
					continue;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   261
				}
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   262
				/* case N4 */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   263
				farchild = node->getRightChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   264
				node = node->getLeftChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   265
			}
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   266
			else
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   267
			{ /* (stack[entry].pb[axis] > splitVal) */
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   268
				if (splitVal < stack[exit].pb[axis])
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   269
				{
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   270
					/* case P1, P2, P3, and N5 */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   271
					node = node->getRightChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   272
					continue;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   273
				}
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   274
				/* case P4 */
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   275
				farchild = node->getLeftChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   276
				node = node->getRightChild();
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   277
			}
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   278
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   279
			/* case P4 or N4 . . . traverse both children */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   280
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   281
			/* signed distance to the splitting plane */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   282
			t = (splitVal - ray.o[axis]) * invdir[axis];
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   283
16
20bceb605f48 add Raytracer::setThreads()
Radek Brich <radek.brich@devl.cz>
parents: 15
diff changeset
   284
			/* setup the new exit point and push it onto stack */
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   285
			register int tmp = exit;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   286
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   287
			exit++;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   288
			if (exit == entry)
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   289
				exit++;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   290
			assert(exit < max_depth);
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   291
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   292
			stack[exit].prev = tmp;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   293
			stack[exit].t = t;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   294
			stack[exit].node = farchild;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   295
			stack[exit].pb.cell[axis] = splitVal;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   296
			stack[exit].pb.cell[mod3[axis+1]] = ray.o.cell[mod3[axis+1]]
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   297
				+ t * ray.dir.cell[mod3[axis+1]];
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   298
			stack[exit].pb.cell[mod3[axis+2]] = ray.o.cell[mod3[axis+2]]
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   299
				+ t * ray.dir.cell[mod3[axis+2]];
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   300
		}
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   301
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   302
		/* current node is the leaf . . . empty or full */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   303
		Shape *nearest_shape = NULL;
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   304
		Float dist = stack[exit].t;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   305
		ShapeList::iterator shape;
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   306
		for (shape = node->getShapes()->begin(); shape != node->getShapes()->end(); shape++)
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   307
			if (*shape != origin_shape && (*shape)->intersect(ray, dist)
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   308
			&& dist >= stack[entry].t)
35
fb170fccb19f new space partitioning structure: octree
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   309
			{
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   310
				nearest_shape = *shape;
35
fb170fccb19f new space partitioning structure: octree
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   311
				nearest_distance = dist;
fb170fccb19f new space partitioning structure: octree
Radek Brich <radek.brich@devl.cz>
parents: 34
diff changeset
   312
			}
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   313
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   314
		if (nearest_shape)
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   315
			return nearest_shape;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   316
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   317
		entry = exit;
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   318
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   319
		/* retrieve the pointer to the next node,
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   320
		it is possible that ray traversal terminates */
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   321
		node = stack[entry].node;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   322
		exit = stack[entry].prev;
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   323
	}
14
fc18ac4833f2 replace Plane with axis-aligned Box (because infinite Plane is not usable with kd-tree)
Radek Brich <radek.brich@devl.cz>
parents: 13
diff changeset
   324
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   325
	/* ray leaves the scene */
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   326
	return NULL;
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   327
}
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   328
11
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   329
// this should save whole kd-tree with triangles distributed into leaves
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   330
void KdTree::save(ostream &str, KdNode *node)
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   331
{
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   332
	if (!built)
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   333
		return;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   334
	if (node == NULL)
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   335
		node = root;
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   336
	if (node->isLeaf())
74
09aedbf5f95f kd-tree traversal - avoid dynamic memory allocation
Radek Brich <radek.brich@devl.cz>
parents: 72
diff changeset
   337
		str << "(leaf: " << node->getShapes()->size() << " shapes)";
10
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   338
	else
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   339
	{
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   340
		str << "(split " << (char)('x'+node->getAxis()) << " at " << node->getSplit() << "; L=";
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   341
		save(str, node->getLeftChild());
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   342
		str << "; R=";
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   343
		save(str, node->getRightChild());
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   344
		str << ";)";
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   345
	}
f9fad94cd0cc kd-tree: build algorithm tested and fixed
Radek Brich <radek.brich@devl.cz>
parents: 9
diff changeset
   346
}
11
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   347
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   348
// load kd-tree from file/stream
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   349
void KdTree::load(istream &str, KdNode *node)
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   350
{
12
f4fcabf05785 kd-tree: traversal algorithm (KdTree::nearest_intersection)
Radek Brich <radek.brich@devl.cz>
parents: 11
diff changeset
   351
11
4d192e13ee84 move nearest_intersection() to Container, add dummy KdTree.load(), plus small fixes
Radek Brich <radek.brich@devl.cz>
parents: 10
diff changeset
   352
}