erebus

view liberebus/src/geomobj.cc @ 16:d2b6cee8ea5c

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