erebus

annotate liberebus/src/geomobj.cc @ 17:e9da2916bc79

fixed the normal bug
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 26 May 2014 05:41:28 +0300
parents d2b6cee8ea5c
children 09028848f276
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@17 25 return -(hit.local_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@17 48 if(d < 1e-6) 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@17 54 if(t0 < 1e-6) t0 = t1;
nuclear@17 55 if(t1 < 1e-6) t1 = t0;
nuclear@4 56 float t = t0 < t1 ? t0 : t1;
nuclear@17 57 if(t < 1e-6) 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@17 69 Vector3 pt = hit.local_ray.origin + hit.local_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@17 91 Vector3 pt = hit.local_ray.origin + hit.local_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 }