|
1 /* |
|
2 * shapes.h: shape classes |
|
3 * |
|
4 * This file is part of Pyrit Ray Tracer. |
|
5 * |
|
6 * Copyright 2006, 2007, 2008 Radek Brich |
|
7 * |
|
8 * Permission is hereby granted, free of charge, to any person obtaining a copy |
|
9 * of this software and associated documentation files (the "Software"), to deal |
|
10 * in the Software without restriction, including without limitation the rights |
|
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
12 * copies of the Software, and to permit persons to whom the Software is |
|
13 * furnished to do so, subject to the following conditions: |
|
14 * |
|
15 * The above copyright notice and this permission notice shall be included in |
|
16 * all copies or substantial portions of the Software. |
|
17 * |
|
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|
24 * THE SOFTWARE. |
|
25 */ |
|
26 |
|
27 #ifndef SHAPES_H |
|
28 #define SHAPES_H |
|
29 |
|
30 #include "common.h" |
|
31 #include "scene.h" |
|
32 |
|
33 /* |
|
34 triangle intersection alghoritm |
|
35 options are: |
|
36 TRI_PLUCKER |
|
37 TRI_BARI |
|
38 TRI_BARI_PRE |
|
39 */ |
|
40 #if !defined(TRI_PLUCKER) && !defined(TRI_BARI) && !defined(TRI_BARI_PRE) |
|
41 # define TRI_BARI_PRE |
|
42 #endif |
|
43 |
|
44 /** |
|
45 * shape |
|
46 */ |
|
47 class Shape |
|
48 { |
|
49 public: |
|
50 Material *material; |
|
51 Shape() {}; |
|
52 virtual ~Shape() {}; |
|
53 |
|
54 // first intersection point |
|
55 virtual bool intersect(const Ray &ray, Float &dist) const = 0; |
|
56 |
|
57 // all intersections (only for CSG) |
|
58 virtual bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const = 0; |
|
59 |
|
60 // intersection with AABB |
|
61 virtual bool intersect_bbox(const BBox &bbox) const = 0; |
|
62 |
|
63 // normal at point P |
|
64 virtual const Vector3 normal(const Vector3 &P) const = 0; |
|
65 |
|
66 virtual BBox get_bbox() const = 0; |
|
67 |
|
68 virtual ostream & dump(ostream &st) const = 0; |
|
69 }; |
|
70 |
|
71 /** |
|
72 * list of shapes |
|
73 */ |
|
74 typedef vector<Shape*> ShapeList; |
|
75 |
|
76 /** |
|
77 * sphere shape |
|
78 */ |
|
79 class Sphere: public Shape |
|
80 { |
|
81 Vector3 center; |
|
82 Float radius; |
|
83 |
|
84 Float sqr_radius; |
|
85 Float inv_radius; |
|
86 public: |
|
87 Sphere(const Vector3 &acenter, const Float aradius, Material *amaterial): |
|
88 center(acenter), radius(aradius), |
|
89 sqr_radius(aradius*aradius), inv_radius(1.0f/aradius) |
|
90 { material = amaterial; } |
|
91 bool intersect(const Ray &ray, Float &dist) const; |
|
92 bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const; |
|
93 bool intersect_bbox(const BBox &bbox) const; |
|
94 const Vector3 normal(const Vector3 &P) const { return (P - center) * inv_radius; }; |
|
95 BBox get_bbox() const; |
|
96 const Vector3 getCenter() const { return center; }; |
|
97 const Float getRadius() const { return radius; }; |
|
98 ostream & dump(ostream &st) const; |
|
99 }; |
|
100 |
|
101 /** |
|
102 * box shape |
|
103 */ |
|
104 class Box: public Shape |
|
105 { |
|
106 Vector3 L; |
|
107 Vector3 H; |
|
108 public: |
|
109 Box(const Vector3 &aL, const Vector3 &aH, Material *amaterial): L(aL), H(aH) |
|
110 { |
|
111 for (int i = 0; i < 3; i++) |
|
112 if (L.cell[i] > H.cell[i]) |
|
113 swap(L.cell[i], H.cell[i]); |
|
114 material = amaterial; |
|
115 }; |
|
116 bool intersect(const Ray &ray, Float &dist) const; |
|
117 bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const { return false; }; |
|
118 bool intersect_bbox(const BBox &bbox) const; |
|
119 const Vector3 normal(const Vector3 &P) const; |
|
120 BBox get_bbox() const { return BBox(L, H); }; |
|
121 const Vector3 getL() const { return L; }; |
|
122 const Vector3 getH() const { return H; }; |
|
123 ostream & dump(ostream &st) const; |
|
124 }; |
|
125 |
|
126 /** |
|
127 * triangle vertex |
|
128 */ |
|
129 class Vertex |
|
130 { |
|
131 public: |
|
132 Vector3 P; |
|
133 Vertex(const Vector3 &aP): P(aP) {}; |
|
134 virtual ostream & dump(ostream &st) const; |
|
135 }; |
|
136 |
|
137 /** |
|
138 * triangle vertex with normal |
|
139 */ |
|
140 class NormalVertex: public Vertex |
|
141 { |
|
142 public: |
|
143 Vector3 N; |
|
144 NormalVertex(const NormalVertex *v): Vertex(v->P), N(v->N) {}; |
|
145 NormalVertex(const Vector3 &aP): Vertex(aP) {}; |
|
146 NormalVertex(const Vector3 &aP, const Vector3 &aN): Vertex(aP), N(aN) {}; |
|
147 const Vector3 &getNormal() { return N; }; |
|
148 void setNormal(const Vector3 &aN) { N = aN; }; |
|
149 ostream & dump(ostream &st) const; |
|
150 }; |
|
151 |
|
152 /** |
|
153 * triangle shape |
|
154 */ |
|
155 class Triangle: public Shape |
|
156 { |
|
157 #ifdef TRI_BARI_PRE |
|
158 Float nu, nv, nd; |
|
159 int k; // dominant axis |
|
160 Float bnu, bnv; |
|
161 Float cnu, cnv; |
|
162 #endif |
|
163 #ifdef TRI_BARI |
|
164 int k; // dominant axis |
|
165 #endif |
|
166 #ifdef TRI_PLUCKER |
|
167 Float pla[6], plb[6], plc[6]; |
|
168 #endif |
|
169 Vector3 N; |
|
170 const Vector3 smooth_normal(const Vector3 &P) const |
|
171 { |
|
172 #ifdef TRI_BARI_PRE |
|
173 const Vector3 &NA = static_cast<NormalVertex*>(A)->N; |
|
174 const Vector3 &NB = static_cast<NormalVertex*>(B)->N; |
|
175 const Vector3 &NC = static_cast<NormalVertex*>(C)->N; |
|
176 static const int modulo3[5] = {0,1,2,0,1}; |
|
177 register const int ku = modulo3[k+1]; |
|
178 register const int kv = modulo3[k+2]; |
|
179 const Float pu = P[ku] - A->P[ku]; |
|
180 const Float pv = P[kv] - A->P[kv]; |
|
181 const Float u = pv * bnu + pu * bnv; |
|
182 const Float v = pu * cnv + pv * cnu; |
|
183 Vector3 n = NA + u * (NB - NA) + v * (NC - NA); |
|
184 n.normalize(); |
|
185 return n; |
|
186 #else |
|
187 return N; // not implemented for other algorithms |
|
188 #endif |
|
189 }; |
|
190 public: |
|
191 Vertex *A, *B, *C; |
|
192 |
|
193 Triangle() {}; |
|
194 Triangle(Vertex *aA, Vertex *aB, Vertex *aC, Material *amaterial); |
|
195 bool intersect(const Ray &ray, Float &dist) const; |
|
196 bool intersect_all(const Ray &ray, Float dist, vector<Float> &allts) const {return false;}; |
|
197 bool intersect_bbox(const BBox &bbox) const; |
|
198 const Vector3 normal(const Vector3 &P) const { return (material->smooth ? smooth_normal(P) : N); }; |
|
199 const Vector3 getNormal() const { return N; }; |
|
200 BBox get_bbox() const; |
|
201 ostream & dump(ostream &st) const; |
|
202 }; |
|
203 |
|
204 template <class T> class Array |
|
205 { |
|
206 T *array; |
|
207 public: |
|
208 Array(int n) { array = new T[n]; }; |
|
209 ~Array() { delete[] array; }; |
|
210 const T &operator[](int i) const { return array[i]; }; |
|
211 }; |
|
212 |
|
213 typedef Array<Vertex> VertexArray; |
|
214 typedef Array<NormalVertex> NormalVertexArray; |
|
215 typedef Array<Triangle> TriangleArray; |
|
216 |
|
217 #endif |