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