Last active
August 29, 2015 14:23
-
-
Save RicherMans/984f3f849966324a39fb to your computer and use it in GitHub Desktop.
Raytraceing example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import numpy as np | |
| from collections import namedtuple | |
| from scipy.misc import imsave | |
| from matplotlib import pyplot as plt | |
| import functools | |
| import time | |
| import argparse | |
| AMBIENT = 0.1 | |
| SCENE_W = 300 | |
| SCENE_H = 400 | |
| InterSection = namedtuple('InterSection', ['point', 'dist', 'normal', 'obj']) | |
| SPECULAR_K = 30. | |
| LIGHT_COLOR = np.ones(3) | |
| def parse_args(): | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument() | |
| return parser.parse_args() | |
| def Vec3(x=0, y=0, z=0): | |
| return np.array([x, y, z]) | |
| def normalize(vec): | |
| return vec / np.sqrt((vec ** 2).sum(-1))[..., np.newaxis] | |
| class Ray: | |
| def __init__(self, pos, direction): | |
| self.direction = normalize(direction) | |
| self.pos = pos | |
| class Plane: | |
| def __init__(self, point, normal, color): | |
| ''' | |
| Function: __init__ | |
| Summary: | |
| Examples: | |
| Attributes: | |
| @param (self): | |
| @param (point): | |
| @param (normal): | |
| @param (color): | |
| Returns: | |
| ''' | |
| self.normal = normal | |
| self.point = point | |
| self.color = color | |
| self.diffuse_c = 0.75 | |
| self.specular_c = 0.80 | |
| @property | |
| def diffuse_c(self): | |
| return self._diffuse_c | |
| @property | |
| def specular_c(self): | |
| return self._specular_c | |
| def intersect(self, ray): | |
| # Projection of the plane normal to the ray, aka, if its orthogonal | |
| # there is no way we can have an intersection | |
| ndot = self.normal.dot(ray.direction.T) | |
| if (ndot == 0): | |
| return None | |
| dist = (self.normal.dot((self.point - ray.pos).T) / ndot) | |
| return InterSection(ray.pos + ray.direction * dist, dist, self.normal, self) | |
| class Poly(Plane): | |
| def __init__(self, verts, n, color): | |
| self.verts = verts | |
| Plane.__init__(self, point=verts[0], normal=n, color=color) | |
| def intersect(self, ray): | |
| x = Plane.intersect(self, ray) | |
| if x is None: | |
| return None | |
| for i in xrange(1, len(self.verts)): | |
| if self._sameside(self.verts[i], self.verts[i - 1], x.point) < 0: | |
| return None | |
| return x | |
| def _sameside(self, a, b, x): | |
| return self.normal.dot(np.cross((b - a), (x - a))) | |
| class Triangle(Poly): | |
| def __init__(self, a, b, c, n, color): | |
| Poly.__init__(self, verts=[a, b, c], n=n, color=color) | |
| class Rect(): | |
| def __init__(self, a, b, n, color): | |
| self.a = a | |
| self.b = b | |
| self.normal = n | |
| self.color = color | |
| def intersect(self, ray): | |
| tx1 = (self.a[0] - ray.pos[0]) | |
| tx2 = (self.b[0] - ray.pos[0]) | |
| tmin = min(tx1, tx2) | |
| tmax = max(tx1, tx2) | |
| class Sphere(): | |
| def __init__(self, center, radius, color): | |
| self.center = center | |
| self.radius = radius | |
| self.color = color | |
| self.diffuse_c = 0.89 | |
| self.specular_c = 0.7 | |
| @property | |
| def diffuse_c(self): | |
| return self._diffuse_c | |
| @property | |
| def specular_c(self): | |
| return self._specular_c | |
| def intersect(self, ray): | |
| # d=-(\mathbf{l}\cdot(\mathbf{o}-\mathbf{c})) \pm | |
| # \sqrt{(\mathbf{l}\cdot(\mathbf{o}-\mathbf{c}))^2-\left\Vert\mathbf{o}-\mathbf{c}\right\Vert^2+r^2} | |
| posMCenter = ray.pos - self.center | |
| decision = ray.direction.dot( | |
| posMCenter.T)**2 - posMCenter.dot(posMCenter.T) + self.radius**2 | |
| if decision < 0: | |
| return None | |
| lhs = - ray.direction.dot(posMCenter.T) | |
| d1 = lhs - np.sqrt(decision) | |
| d2 = lhs + np.sqrt(decision) | |
| d = min(d1, d2) | |
| if d < 0: | |
| return None | |
| return InterSection(ray.pos + ray.direction * d, d, self._normal(ray.pos + ray.direction * d), self) | |
| def _normal(self, vec): | |
| return normalize(vec - self.center) | |
| class Cylinder: | |
| def __init__(self, center, radius, height, color): | |
| self.center = center | |
| self.radius = radius | |
| self.height = height | |
| self.color = color | |
| class Cube(Poly): | |
| def __init__(self, a, b, c, d, n, color): | |
| Poly.__init__(self, [a, b, c, d], n, color) | |
| class Scene: | |
| def __init__(self, camera): | |
| self.objs = [] | |
| self.lightsources = [] | |
| self.camera = camera | |
| def addObj(self, obj): | |
| self.objs.append(obj) | |
| def addLight(self, light): | |
| self.lightsources.append(light) | |
| @property | |
| def camera(self): | |
| return self._camera | |
| def _intersectRay(self, ray, ignoreobj=None): | |
| intersection = None | |
| maxdistance = np.i |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment