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