Day 33, Domain-Specific Language
Not a single feature improvement today, but instead a bit of quality of life improvements.
One of the great things about modern dynamic introspective languages is that it’s very easy to create a domain-specific language for a project like this, to make a scene description be less like pages of complicated code, and more like a reasonably fluent declarative description of the objects in the scene.
material :glazed_ceramic do
color rgb 1.0, 0.8, 0.5
ambient 0.3
diffuse 0.7
phong 0.9, 300
reflective 0.1
end
shape.mesh :utah_teapot do |version = 'hi'|
file "teapot-#{version}.obj"
material :glazed_ceramic
rotate x: -1/4r
scale 1/16r
end
The top-level declarations creates methods on the appropriate classes so they can be called by reference later on to create the concrete model objects dynamically, and does more or less the same as the previous raw API code:
def setup_teapot(world, version)
world << ObjFile.new(File.open(__dir__ + "/teapot-#{version}.obj")) do |g|
g.transform = identity.rotate_x('-1/4'.to_r)
.scale('1/16'.to_r)
g.material = Material.new do |m|
m.color = Color[1.0, 0.8, 0.5]
m.shininess = 300
m.diffuse = 0.7
m.ambient = 0.3
end
end
end
Next related
Day 36, Constructive Solid Geometry
The final pre-defined feature of the project is done, Constructive Solid Geometry, implementing the boolean set operations union, intersection, and difference for solid geometries. This way we can use the basic geometric surface shapes to create more advanced shapes, without resorting to approximating by thousands of triangles.
Previous related
Day 32, Smoothly interpolated normals
Tea, Cocktails, and a Happy New Year
Day 31, Optimizing triangles
Triangle rendering was painfully slow, as mentioned yesterday. Putting a little reflective shine on the floor and walls of the room took rendering time past 90 minutes. After a bit of research i tried a binary bounding volume hierarchy, dividing the list of shapes into subtrees, split evenly on the largest axis of the bounding box, recursively. This way we get a spacially balanced binary tree with the actual shapes as leaves, and theoretically get \(O(log\ n)\) instead of \(O(n)\) search time per ray. Huge difference, especially with rays branching recursively for reflections and refractions. Down from 90 to 6 minutes for the same scene.