開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Python 3.7 (プログラミング言語)
- GIMP (ビットマップ画像編集・加工ソフトウェア、PPM形式(portable pixmap)の画像用)
The Ray Tracer Challenge: A Test-Driven Guide to Your First 3D Renderer (Jamis Buck(著)、Pragmatic Bookshelf)、Chapter 14(Groups)のImplementing Groupsを取り組んでみる。
コード
groups_test.py
#!/usr/bin/env python3
from unittest import TestCase, main
from shapes import Shape
from spheres import Sphere
from groups import Group
from matrices import IDENTITY_MATRIX
from rays import Ray
from tuples import Point, Vector
from transformations import translation, scaling
class GroupTest(TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def test_group(self):
group = Group()
self.assertEqual(group.transform, IDENTITY_MATRIX)
self.assertEqual(len(group), 0)
def test_adding_child_to(self):
group = Group()
shape = Shape()
group.add_child(shape)
self.assertIn(shape, group)
self.assertEqual(shape.parent, group)
def test_intersecting_ray_with_empty_group(self):
group = Group()
ray = Ray(Point(0, 0, 0), Vector(0, 0, 1))
intersections = group.intersect(ray)
self.assertEqual(len(intersections), 0)
def test_intersecting_ray_nonempty_group(self):
group = Group()
s1 = Sphere()
s2 = Sphere(transform=translation(0, 0, -3))
s3 = Sphere(transform=translation(5, 0, 0))
for s in [s1, s2, s3]:
group.add_child(s)
ray = Ray(Point(0, 0, -5), Vector(0, 0, 1))
intersections = group.intersect(ray)
self.assertEqual(len(intersections), 4)
for intersection, shape in zip(intersections, [s2, s2, s1, s1]):
self.assertEqual(intersection.obj, shape)
def test_intersecting_transformed(self):
group = Group(transform=scaling(2, 2, 2))
sphere = Sphere(transform=translation(5, 0, 0))
group.add_child(sphere)
ray = Ray(Point(10, 0, -10), Vector(0, 0, 1))
intersections = group.intersect(ray)
self.assertEqual(len(intersections), 2)
if __name__ == '__main__':
main()
groups.py
from shapes import Shape
from intersections import Intersections
class Group(Shape):
def __init__(self, transform=None, material=None):
super().__init__(transform=transform, material=material)
self.shapes = []
def __len__(self):
return len(self.shapes)
def __getitem__(self, y):
return self.shapes[y]
def add_child(self, shape):
shape.parent = self
self.shapes.append(shape)
def intersect(self, ray):
ray = ray.transform(self.transform.inverse())
intersections = []
for shape in self.shapes:
intersections += shape.intersect(ray).xs
return Intersections(*intersections)
shapes_test.py
#!/usr/bin/env python3
from unittest import TestCase, main
from shapes import Shape
from transformations import translation
from matrices import IDENTITY_MATRIX, Matrix
from materials import Material
from rays import Ray
from tuples import Point, Vector
from transformations import scaling
class ShapeTest(TestCase):
def setUp(self):
self.shape = Shape(material=Material())
def tearDown(self):
pass
def test_default_transformation(self):
self.assertEqual(self.shape.transform, IDENTITY_MATRIX)
def test_material(self):
self.assertEqual(self.shape.material.ambient, 0.1)
self.assertEqual(self.shape.material, Material())
def test_transform(self):
self.assertEqual(Shape().transform,
IDENTITY_MATRIX)
s = Shape()
t = translation(2, 3, 4)
s.transform = t
self.assertEqual(s.transform, t)
def test_parent_attribute(self):
s = Shape()
self.assertIsNone(s.parent)
if __name__ == '__main__':
main()
shapes.py
from matrices import Matrix, IDENTITY_MATRIX
from materials import Material
class Shape:
def __init__(self, transform=None, material=None, parent=None):
if transform is None:
self.transform = IDENTITY_MATRIX
else:
self.transform = transform
if material is None:
self.material = Material()
else:
self.material = material
self.parent = None
def __repr__(self):
return f'{self.__class__.__name__}({self.transform},{self.material})'
def intersect(self, ray):
raise NotImplementedError()
def normal_at(self, point):
raise NotImplementedError()
入出力結果(Bash、cmd.exe(コマンドプロンプト)、Terminal、Jupyter(IPython))
C:\Users\...>py groups_test.py ..... ---------------------------------------------------------------------- Ran 5 tests in 0.005s OK C:\Users\...>py shapes_test.py .... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK C:\Users\...>
0 コメント:
コメントを投稿