-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCSG.cpp
More file actions
123 lines (99 loc) · 3.66 KB
/
CSG.cpp
File metadata and controls
123 lines (99 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/* $Rev: 250 $ */
#include "CSG.h"
#include "utility.h"
CSG::CSG() : Object() {
left = std::shared_ptr<Sphere>(new Sphere());
right = std::shared_ptr<Sphere>(new Sphere());
right->transform.translate(-1,0,0);
}
CSG::CSG(const CSG& csg) : Object(csg) {
}
CSG::~CSG() {
}
const CSG& CSG::operator=(const CSG& csg) {
if (this != &csg) {
Object::operator=(csg);
}
return *this;
}
bool nearer(RayIntersection a, RayIntersection b) { return (a<b); }
void CSG::setupCSG(std::string type){
csgType = type;
}
std::vector<RayIntersection> CSG::intersect(const Ray& ray) const {
csg_state csg_table[3][3] = {
{OUTSIDE,OUTSIDE,OUTSIDE},
{OUTSIDE,OUTSIDE,OUTSIDE},
{OUTSIDE,OUTSIDE,OUTSIDE}
};
if (csgType == "INTERSECTION") {
// make the csg_table appropriate for intersection
csg_table[INSIDE][BORDER] = BORDER;
csg_table[INSIDE][INSIDE] = INSIDE;
csg_table[BORDER][INSIDE] = BORDER;
} else if (csgType == "DIFFERENCE") {
csg_table[INSIDE][OUTSIDE] = INSIDE;
csg_table[BORDER][OUTSIDE] = BORDER;
csg_table[INSIDE][BORDER] = BORDER;
} else if (csgType == "UNION"){
csg_table[INSIDE][OUTSIDE] = INSIDE;
csg_table[BORDER][OUTSIDE] = BORDER;
csg_table[INSIDE][INSIDE] = INSIDE;
csg_table[OUTSIDE][INSIDE] = INSIDE;
csg_table[BORDER][INSIDE] = INSIDE;
csg_table[INSIDE][BORDER] = INSIDE;
csg_table[OUTSIDE][BORDER] = BORDER;
csg_table[BORDER][BORDER] = BORDER;
}
std::vector<RayIntersection> result;
Ray inverseRay = transform.applyInverse(ray);
std::vector<RayIntersection> leftIntersections;
std::vector<RayIntersection> rightIntersections;
leftIntersections = left->intersect(inverseRay);
rightIntersections = right->intersect(inverseRay);
// sort intersections
std::sort(leftIntersections.begin(), leftIntersections.end(), nearer);
std::sort(rightIntersections.begin(), rightIntersections.end(), nearer);
int numLeftIs = leftIntersections.size();
int numRightIs = rightIntersections.size();
// We will assume that an odd number of intersections
// indicates being inside an object. This is not correct for
// glancing intersections. These artefacts could be fixed, up
// to a point, by tracing a ray in the reverse direction and
// looking for object intersections, however for this ray
// tracer, we will just live with the (rare) glitches.
csg_state leftState = OUTSIDE;
csg_state rightState = OUTSIDE;
if (numLeftIs % 2 == 1) leftState = INSIDE;
if (numRightIs % 2 == 1) rightState = INSIDE;
// We also need to keep track of the previous state.
// This allows us to update correctly as we transition across a border
// So if previousLeftState is inside, and we cross a border we end up outside
csg_state previousLeftState = leftState;
csg_state previousRightState = rightState;
// iterate through both child objects' ray intersections
int lIi = 0;
int rIi = 0;
RayIntersection possibleIntersection;
while( lIi < numLeftIs || rIi < numRightIs ){
// there's still work to do
if( rIi==numRightIs ||
( lIi<numLeftIs && leftIntersections[lIi] < rightIntersections[rIi] )
) {
// TODO: process leftIntersections[lIi]
lIi++;
}else{
// TODO: process rightIntersections[lIi]
rIi++;
}
// TODO: Check the possible intersection against the
// csg_table to see if it is actually a hitpoint of
// the overall CSG object. If it is a hitpoint, add
// it to the result.
// TODO: Update the left and/or the right tree to
// ensure that they advance beyond their BORDER state,
// as the tracing ray resumes its progression through
// the scene.
}
return result;
}