rev |
line source |
nuclear@4
|
1 #include <float.h>
|
nuclear@4
|
2 #include "geomobj.h"
|
nuclear@4
|
3
|
nuclear@4
|
4 static LambertRefl lambert;
|
nuclear@4
|
5
|
nuclear@4
|
6 GeomObject::GeomObject()
|
nuclear@4
|
7 {
|
nuclear@4
|
8 brdf = &lambert;
|
nuclear@4
|
9 }
|
nuclear@4
|
10
|
nuclear@4
|
11 ObjType GeomObject::get_type() const
|
nuclear@4
|
12 {
|
nuclear@4
|
13 return ObjType::geom;
|
nuclear@4
|
14 }
|
nuclear@4
|
15
|
nuclear@4
|
16 bool GeomObject::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@4
|
17 {
|
nuclear@4
|
18 return false;
|
nuclear@4
|
19 }
|
nuclear@4
|
20
|
nuclear@8
|
21 Vector3 GeomObject::calc_normal(const RayHit &hit) const
|
nuclear@8
|
22 {
|
nuclear@8
|
23 // when you look at singularities, the singularities always look back at you :)
|
nuclear@8
|
24 return -(hit.world_ray.dir).normalized();
|
nuclear@8
|
25 }
|
nuclear@8
|
26
|
nuclear@8
|
27 Vector3 GeomObject::calc_tangent(const RayHit &hit) const
|
nuclear@8
|
28 {
|
nuclear@8
|
29 return Vector3(1, 0, 0); // whatever...
|
nuclear@8
|
30 }
|
nuclear@8
|
31
|
nuclear@8
|
32 Vector2 GeomObject::calc_texcoords(const RayHit &hit) const
|
nuclear@8
|
33 {
|
nuclear@8
|
34 return Vector2();
|
nuclear@8
|
35 }
|
nuclear@8
|
36
|
nuclear@4
|
37 // --- class Sphere ---
|
nuclear@4
|
38
|
nuclear@4
|
39 bool Sphere::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@4
|
40 {
|
nuclear@4
|
41 // assumes center is the origin and radius is 1
|
nuclear@4
|
42 float a = dot_product(ray.dir, ray.dir);
|
nuclear@4
|
43 float b = 2.0 * dot_product(ray.dir, ray.origin);
|
nuclear@4
|
44 float c = dot_product(ray.origin, ray.origin) - 1.0;
|
nuclear@4
|
45
|
nuclear@4
|
46 float d = b * b - 4.0 * a * c;
|
nuclear@4
|
47 if(d < 1e-4) return false;
|
nuclear@4
|
48
|
nuclear@4
|
49 float sqrt_d = sqrt(d);
|
nuclear@4
|
50 float t0 = (-b + sqrt_d) / (2.0 * a);
|
nuclear@4
|
51 float t1 = (-b - sqrt_d) / (2.0 * a);
|
nuclear@4
|
52
|
nuclear@4
|
53 if(t0 < 1e-4) t0 = t1;
|
nuclear@4
|
54 if(t1 < 1e-4) t1 = t0;
|
nuclear@4
|
55 float t = t0 < t1 ? t0 : t1;
|
nuclear@4
|
56 if(t < 1e-4) return false;
|
nuclear@4
|
57
|
nuclear@4
|
58 if(hit) {
|
nuclear@4
|
59 hit->dist = t;
|
nuclear@4
|
60 hit->obj = this;
|
nuclear@4
|
61 hit->subobj = 0;
|
nuclear@4
|
62 }
|
nuclear@4
|
63 return true;
|
nuclear@4
|
64 }
|
nuclear@4
|
65
|
nuclear@8
|
66 Vector3 Sphere::calc_normal(const RayHit &hit) const
|
nuclear@8
|
67 {
|
nuclear@8
|
68 Vector3 pt = hit.world_ray.origin + hit.world_ray.dir * hit.dist;
|
nuclear@8
|
69 return pt.normalized();
|
nuclear@8
|
70 }
|
nuclear@8
|
71
|
nuclear@8
|
72 static inline Vector3 sphvec(float u, float v)
|
nuclear@8
|
73 {
|
nuclear@8
|
74 float theta = u * M_PI * 2.0;
|
nuclear@8
|
75 float phi = v * M_PI;
|
nuclear@8
|
76
|
nuclear@8
|
77 return Vector3(sin(theta) * sin(phi), cos(phi), cos(theta) * sin(phi));
|
nuclear@8
|
78 }
|
nuclear@8
|
79
|
nuclear@8
|
80 Vector3 Sphere::calc_tangent(const RayHit &hit) const
|
nuclear@8
|
81 {
|
nuclear@8
|
82 Vector2 uv = calc_texcoords(hit);
|
nuclear@8
|
83 Vector3 pnext = sphvec(uv.x + 0.05, 0.5);
|
nuclear@8
|
84 Vector3 pprev = sphvec(uv.y - 0.05, 0.5);
|
nuclear@8
|
85 return (pnext - pprev).normalized();
|
nuclear@8
|
86 }
|
nuclear@8
|
87
|
nuclear@8
|
88 Vector2 Sphere::calc_texcoords(const RayHit &hit) const
|
nuclear@8
|
89 {
|
nuclear@8
|
90 Vector3 pt = hit.world_ray.origin + hit.world_ray.dir * hit.dist;
|
nuclear@8
|
91 pt.normalize();
|
nuclear@8
|
92
|
nuclear@8
|
93 float theta = atan2(pt.z, pt.x);
|
nuclear@8
|
94 float phi = acos(pt.y);
|
nuclear@8
|
95
|
nuclear@8
|
96 return Vector2(theta / M_PI + 0.5, phi / M_PI);
|
nuclear@8
|
97 }
|
nuclear@8
|
98
|
nuclear@8
|
99
|
nuclear@4
|
100 // --- class Box ---
|
nuclear@4
|
101
|
nuclear@4
|
102 bool Box::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@4
|
103 {
|
nuclear@4
|
104 return false;
|
nuclear@4
|
105 }
|
nuclear@4
|
106
|
nuclear@4
|
107 // --- class Triangle ---
|
nuclear@4
|
108
|
nuclear@4
|
109 bool Triangle::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@4
|
110 {
|
nuclear@4
|
111 return false;
|
nuclear@4
|
112 }
|
nuclear@4
|
113
|
nuclear@4
|
114 // --- class Mesh ---
|
nuclear@4
|
115
|
nuclear@4
|
116 bool Mesh::intersect(const Ray &ray, RayHit *hit) const
|
nuclear@4
|
117 {
|
nuclear@4
|
118 RayHit nearest;
|
nuclear@4
|
119 nearest.dist = FLT_MAX;
|
nuclear@4
|
120
|
nuclear@4
|
121 for(size_t i=0; i<faces.size(); i++) {
|
nuclear@4
|
122 if(faces[i].intersect(ray, hit)) {
|
nuclear@4
|
123 if(!hit) return true;
|
nuclear@4
|
124 if(hit->dist < nearest.dist) {
|
nuclear@4
|
125 nearest = *hit;
|
nuclear@4
|
126 }
|
nuclear@4
|
127 }
|
nuclear@4
|
128 }
|
nuclear@4
|
129
|
nuclear@4
|
130 if(nearest.dist < FLT_MAX) {
|
nuclear@4
|
131 *hit = nearest;
|
nuclear@4
|
132 hit->subobj = hit->obj;
|
nuclear@4
|
133 hit->obj = this;
|
nuclear@4
|
134 return true;
|
nuclear@4
|
135 }
|
nuclear@4
|
136 return false;
|
nuclear@4
|
137 }
|