erebus

annotate 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
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 }