Commits

Anonymous committed 1246069

change ordering of arguments, read file for scene

Comments (0)

Files changed (1)

raytrace/raytrace.awk

+# raytrace.awk
+
+# example scene. place this in a file and run:
+# awk -f raytrace.awk scene > image.ppm && display image.ppm
+# 
+#vector  position   0    100     100
+#vector  direction  0    -1      -1
+#camera  200        200  2       2      40  1  1000  position  direction
+#
+#vector  center     0    0       0
+#vector  color      255  0       0
+#sphere  head       20   center  color
+#
+#vector  center     15   15      0
+#vector  color      0    255     0
+#sphere  ear1       10   center  color
+#
+#vector  center     -15  15      0
+#vector  color      0    0       255
+#sphere  ear2       10   center  color
+
+# hacked together structures using arrays like so:
+# array["field"] = value
+# so a vector looks like:
+# vector["x"] = 0
+# vector["y"] = 0
+# vector["z"] = 0
+#
+# for nested structures we do:
+# outer["innerprefix" "innerfield"] = value
+#
+# so a sphere which has a radius, center(vector), and color(vector),
+# looks like:
+# sphere["radius" ] = 5
+# sphere["centerx"] = 0
+# sphere["centery"] = 1
+# sphere["centerz"] = 2
+# sphere["colorx" ] = 0
+# sphere["colory" ] = 255
+# sphere["colorz" ] = 0
+#
+# and when I have an array full of spheres, I add a name prefix for each
+# sphere so I'd have
+# objects["sphere1centerx"] = 0
+# objects["sphere2centerx"] = 1
+# etc.
+#
+# functions that take a structure take the array name then
+# prefix. examples:
+# magnitude(sphere, "center")
+# magnitude(objects, "sphere1" "center")
+# dot(sphere, "center", vec, "")
+#
+# functions that need to "return" a structure take the result array to
+# fill and its prefix first. examples:
+# make_vector(center, "", 0, 0, 0)
+# make_vector(sphere, "center", 0, 0, 0)
+# make_vector(objects, "sphere1" "color", 0, 0, 0)
+
 function tan(a) {
     return sin(a)/cos(b)
 }
+
 function make_vector(result, pre, x, y, z) {
     result[pre "x"] = x
     result[pre "y"] = y
     result[pre "z"] = z
 }
-function copy_vector(dst, src, dpre, spre) {
+
+function copy_vector(dst, dpre, src, spre) {
     dst[dpre "x"] = src[spre "x"]
     dst[dpre "y"] = src[spre "y"]
     dst[dpre "z"] = src[spre "z"]
 }
-function make_ray(result, origin, direction, tmin, tmax, rpre, opre, dpre)
+
+function make_ray(result, rpre, origin, opre, direction, dpre, tmin, tmax)
 {
-    copy_vector(result, origin   , rpre "origin"   , opre)
-    copy_vector(result, direction, rpre "direction", dpre)
+    copy_vector(result, rpre "origin"   , origin   , opre)
+    copy_vector(result, rpre "direction", direction, dpre)
 
     result[rpre "tmin"] = tmin
     result[rpre "tmax"] = tmax
 }
-function make_sphere(result, center, radius, color, rpre, cpre, copre)
+
+function make_sphere(result, rpre, radius, center, cpre, color, copre)
 {
-    copy_vector(result, center, rpre "center", cpre )
-    copy_vector(result, color , rpre "color" , copre)
+    copy_vector(result, rpre "center", center, cpre )
+    copy_vector(result, rpre "color" , color , copre)
     result[rpre "radius"] = radius
 }
-function dot(a, b, apre, bpre) {
+
+function dot(a, apre, b, bpre) {
     return a[apre "x"] * b[bpre "x"] + a[apre "y"] * b[bpre "y"] + a[apre "z"] * b[bpre "z"] 
 }
+
 function magnitude(a, apre) {
-    return sqrt(dot(a, a, apre, apre))
+    return sqrt(dot(a, apre, a, apre))
 }
-function cross(a, b, result, apre, bre, rpre) {
+
+function cross(result, rpre, a, apre, b, bpre) {
     result[rpre "x"] = a[apre "y"] * b[bpre "z"] - a[apre "z"] * b[bpre "y"]
     result[rpre "y"] = a[apre "z"] * b[bpre "x"] - a[apre "x"] * b[bpre "z"]
     result[rpre "z"] = a[apre "x"] * b[bpre "y"] - a[apre "y"] * b[bpre "x"]
 }
-function scalar_multiply(s, a, result, apre, rpre) {
+
+function scalar_multiply(result, rpre, s, a, apre) {
     result[rpre "x"] = a[apre "x"] * s;
     result[rpre "y"] = a[apre "y"] * s;
     result[rpre "z"] = a[apre "z"] * s;
 }
-function add(a, b, result, apre, bpre, rpre) {
+
+function add(result, rpre, a, apre, b, bpre) {
     result[rpre "x"] = a[apre "x"] + b[bpre "x"]
     result[rpre "y"] = a[apre "y"] + b[bpre "y"]
     result[rpre "z"] = a[apre "z"] + b[bpre "z"]
 }
-function subtract(a, b, result, apre, bpre, rpre) {
+
+function subtract(result, rpre, a, apre, b, bpre) {
     result[rpre "x"] = a[apre "x"] - b[bpre "x"]
     result[rpre "y"] = a[apre "y"] - b[bpre "y"]
     result[rpre "z"] = a[apre "z"] - b[bpre "z"]
 }
-function normalize(a, result, apre, rpre,        mag) {
+
+function normalize(result, rpre, a, apre,        mag) {
     if (mag = magnitude(a, apre))
-        scalar_multiply(1 / mag, a, result, apre, rpre)
+        scalar_multiply(result, rpre, 1 / mag, a, apre)
     else
         make_vector(result, rpre)
 }
+
 function radians(degrees) {
     return degrees * 3.14159265358979323846 / 180
 }
+
 function print_int_vec(vec, pre) {
     printf("%d %d %d ", vec[pre "x"], vec[pre "y"], vec[pre "z"]);
 }
-function print_float_vec(vec, pre) {
-    printf("%f %f %f ", vec[pre "x"], vec[pre "y"], vec[pre "z"]);
-}
+
 
 # find roots, place in r, return number of roots found
-function qroots(a, b, c, r,        q, d)
-{
+function qroots(a, b, c, r,        q, d) {
     d = b * b - 4 * a * c
     if (d <  0) return 0;
     if (d == 0) {
     }
     return 2
 }
-function intersect_sphere(sphere, ray, spre, rpre,        t, ro, a, b, c)
-{
-    subtract(ray, sphere, ro, rpre "origin", spre "center")
+
+function intersect_sphere(sphere, spre, ray, rpre,        t, ro, a, b, c) {
+    subtract(ro, "", ray, rpre "origin", sphere, spre "center")
     a = 1 # direction is normalized. if not: a = dot(ray, ray, "direction", "direction")
-    b = dot(ray, ro, rpre "direction") * 2
-    c = dot(ro, ro) - sphere[spre "radius"] * sphere[spre "radius"]
+    b = dot(ray, rpre "direction", ro, "") * 2
+    c = dot(ro, "", ro, "") - sphere[spre "radius"] * sphere[spre "radius"]
 
     if (!qroots(a, b, c, t)) return 0
     if (t[1] < ray[rpre "tmin"]) {
     ray[rpre "tmax"] = t[1]
     return 1
 }
-function trace(ray, objects, objnames, rpre, color,        hit)
-{
+
+function trace(ray, objects, objnames, color,        hit) {
     hit = "bg"
     for (name in objnames)
-        if (intersect_sphere(objects, ray, name, rpre))
+        if (intersect_sphere(objects, name, ray, rpre))
             hit = name
-    copy_vector(color, objects, "", hit "color")
+    copy_vector(color, "", objects, hit "color")
 }
-function make_primary_ray(camera, x, y, ray,        aspect_ratio, t, pixel)
-{
+
+function make_primary_ray(camera, x, y, ray,        aspect_ratio, t, direction, xdir, ydir) {
     aspect_ratio = camera["xres"] / camera["yres"]
     t = tan(camera["fov"] / 2)
-    make_vector(pixel)
+    make_vector(direction)
 
-    pixel["x"] = (-1 + 2 * (x + rand() / camera["sub"]) / camera["xres"]) * t * aspect_ratio
-    pixel["y"] = ( 1 - 2 * (y + rand() / camera["sub"]) / camera["yres"]) * t
-    pixel["z"] = -1
-    normalize(pixel, pixel)
-    make_ray(ray, camera, pixel, camera["near_plane"], camera["far_plane"], "", "position")
+    make_vector(xdir)
+    make_vector(ydir, "", 0, 1, 0)                 # camera always "right side up"
+    cross(xdir, "", ydir, "", camera, "direction") # perpendicular to Y and gaze
+    cross(ydir, "", camera, "direction", xdir, "") # perpendicular to X and gaze
+    normalize(xdir, "", xdir, "")
+    normalize(ydir, "", ydir, "")
+
+    x = (-1 + 2 * (x + rand() / camera["sub"]) / camera["xres"]) * t * aspect_ratio
+    y = ( 1 - 2 * (y + rand() / camera["sub"]) / camera["yres"]) * t
+    scalar_multiply(xdir, "", x, xdir, "");
+    scalar_multiply(ydir, "", y, ydir, "");
+
+    add(direction, "", xdir, "", ydir, "")
+    add(direction, "", direction, "", camera, "direction")
+    normalize(direction, "", direction, "")
+
+    make_ray(ray, "", camera, "position", direction, "", camera["near_plane"], camera["far_plane"])
 }
-function render(camera, objects, objnames,        s, x, y, subx, suby, color, tmpcolor, ray)
-{
+
+function render(camera, objects, objnames,        s, x, y, subx, suby, color, tmpcolor, ray) {
     for (y = 0; y < camera["yres"]; y++) {
         for (x = 0; x < camera["xres"]; x++) {
             make_vector(color)
                 for (subx = 0; subx < camera["sub"]; subx++) {
                     for (s = 0; s < camera["samples"]; s++) {
                         make_primary_ray(camera, x + subx / camera["sub"], y + suby / camera["sub"], ray)
-                        trace(ray, objects, objnames, "", tmpcolor)
-                        add(color, tmpcolor, color)
+                        trace(ray, objects, objnames, tmpcolor)
+                        add(color, "", color, "", tmpcolor, "")
                     }
                 }
             }
-            scalar_multiply(1 / (camera["samples"] * camera["sub"] * camera["sub"]), color, color)
+            scalar_multiply(color, "", 1 / (camera["samples"] * camera["sub"] * camera["sub"]), color, "")
             print_int_vec(color)
         }
     }
 }
-function print_array(a)
-{
+
+# for debugging
+function print_array(a, pre,        len) {
+    len = 0
     for (k in a)
-        printf("%-20s %8.3f\n", k, a[k])
+        if (index(k, pre) == 1 && length(k) > len)
+            len = length(k)
+
+    for (k in a)
+        if (index(k, pre) != 1)
+            continue
+        else if (match(a[k], /[^[:digit:].+-]/))
+            printf("%-*s \"%s\"\n", len, k, a[k])
+        else
+            printf("%-*s "OFMT"\n", len, k, a[k])
 }
 
-BEGIN {
-    camera["xres"      ] = 640
-    camera["yres"      ] = 480
-    camera["sub"       ] =   2
-    camera["samples"   ] =   1
-    camera["fov"       ] = radians(45)
-    camera["near_plane"] =   1
-    camera["far_plane" ] = 100
-    make_vector(camera, "position")
-    make_vector(camera, "direction", 0, 0, 1)
+# comments
+$1 == "#" {
+    next
+}
 
-    make_vector(objects, "bgcolor")
+# vector name x y z
+$1 == "vector" {
+    make_vector(globals, $2, $3, $4, $5)
+}
 
-    make_vector(center, "",   0, 0, -50)
-    make_vector(color , "", 255, 0,   0)
-    make_sphere(objects, center, 10, color, "sphere1")
-    objnames["sphere1"]
+# sphere name radius center color
+$1 == "sphere" {
+    make_sphere(objects, $2, $3, globals, $4, globals, $5)
+    objnames[$2]
+}
 
-    make_vector(center, "", 7,   7, -45)
-    make_vector(color , "", 0, 255,   0)
-    make_sphere(objects, center, 5, color, "sphere2")
-    objnames["sphere2"]
+# camera xres yres subs samples fov near far position direction
+$1 == "camera" {
+    camera["xres"      ] = $2
+    camera["yres"      ] = $3
+    camera["sub"       ] = $4
+    camera["samples"   ] = $5
+    camera["fov"       ] = radians($6)
+    camera["near_plane"] = $7
+    camera["far_plane" ] = $8
+    copy_vector(camera, "position" , globals,  $9)
+    copy_vector(camera, "direction", globals, $10)
+    normalize(camera, "direction", camera, "direction")
+}
 
+END {
     printf("P3\n%d %d\n%d\n", camera["xres"], camera["yres"], 255)
-
     render(camera, objects, objnames)
+    #print_array(objects)
+    #print_array(camera)
 }
-