Commit f2decef8732f2c6e0a1122f7afbdfac501b67ddb

Thomas de Grivel 2024-01-29T21:11:57

animation

diff --git a/smallpt.cpp b/smallpt.cpp
index cd78b4c..fdc9e21 100644
--- a/smallpt.cpp
+++ b/smallpt.cpp
@@ -115,55 +115,74 @@ struct Sphere {
   }
 };
 
-//Scene: radius, position, emission, color, material
-Sphere g_spheres[] = {
-  Sphere(1e5,                           // Left
-         Vec(1e5 + 1, 40.8, 81.6),
-         Vec(),
-         Vec(1, 1, 1) * 0.8,
-         SPECULAR),
-  Sphere(1e5,                           // Right
-         Vec(-1e5 + 99, 40.8, 81.6),
-         Vec(),
-         Vec(1, 1, 1) * 0.8,
-         SPECULAR),
-  Sphere(1e5,                           // Back
-         Vec(50, 40.8, 1e5),
-         Vec(),
-         Vec(1, 1, 1) * 0.8,
-         SPECULAR),
-  Sphere(1e5,                           // Front
-         Vec(50, 40.8, -1e5 + 170),
-         Vec(),
-         Vec(1, 1, 1) * 0.8,
-         SPECULAR),
-  Sphere(1e5,                           // Bottom
-         Vec(50, 1e5, 81.6),
-         Vec(),
-         Vec(1, 1, 1) * 0.999,
-         SPECULAR),
-  Sphere(1e5,                           // Top
-         Vec(50, -1e5 + 81.6, 81.6),
-         Vec(),
-         Vec(1, 1, 1) * 0.5,
-         DIFFUSE),
-  Sphere(16.5,                          // Mirror ball
-         Vec(27, 16.5, 47),
-         Vec(),
-         Vec(1, 1, 1) * 0.999,
-         SPECULAR),
-  Sphere(16.5,                          // Glass
-         Vec(73, 16.5, 78),
-         Vec(),
-         Vec(1, 1, 1) * 0.999,
-         REFRACTION),
-  Sphere(600,                           // Light
-         Vec(50, 681.6 - 0.27, 81.6),
-         Vec(12, 12, 12),
-         Vec(),
-         DIFFUSE)
+#define SPHERES_COUNT       9
+#define SPHERES_ROT_RADIUS 20.0
+#define SPHERES_ROT_SPEED   0.25
+
+struct Scene {
+  Sphere spheres[SPHERES_COUNT] = {
+    Sphere(16.5,                          // Mirror ball
+           Vec(50.0, 16.5, 50.0),
+           Vec(),
+           Vec(1, 1, 1) * 0.999,
+           SPECULAR),
+    Sphere(16.5,                          // Glass
+           Vec(50, 16.5, 50.0),
+           Vec(),
+           Vec(1, 1, 1) * 0.999,
+           REFRACTION),
+    Sphere(1e5,                           // Left
+           Vec(1e5 + 1, 40.8, 81.6),
+           Vec(),
+           Vec(1, 1, 1) * 0.7,
+           SPECULAR),
+    Sphere(1e5,                           // Right
+           Vec(-1e5 + 99, 40.8, 81.6),
+           Vec(),
+           Vec(1, 1, 1) * 0.7,
+           SPECULAR),
+    Sphere(1e5,                           // Back
+           Vec(50, 40.8, 1e5),
+           Vec(),
+           Vec(1, 1, 1) * 0.7,
+           SPECULAR),
+    Sphere(1e5,                           // Front
+           Vec(50, 40.8, -1e5 + 170),
+           Vec(),
+           Vec(1, 1, 1) * 0.7,
+           SPECULAR),
+    Sphere(1e5,                           // Bottom
+           Vec(50, 1e5, 81.6),
+           Vec(),
+           Vec(1, 0.9, 0.7) * 0.9,
+           SPECULAR),
+    Sphere(1e5,                           // Top
+           Vec(50, -1e5 + 81.6, 81.6),
+           Vec(),
+           Vec(1, 0.9, 0.9) * 0.8,
+           DIFFUSE),
+    Sphere(600,                           // Light
+           Vec(50, 681.6 - 0.27, 81.6),
+           Vec(12, 12, 12),
+           Vec(),
+           DIFFUSE)
+  };
+  
+  void update_time (F time)
+  {
+    F theta = time * SPHERES_ROT_SPEED * M_PI * 2.0;
+    spheres[0].position = Vec(50.0, 16.5, 50.0) +
+      Vec(cos(theta) * SPHERES_ROT_RADIUS, 0.0,
+          sin(theta) * SPHERES_ROT_RADIUS);
+    theta += M_PI;
+    spheres[1].position = Vec(50.0, 16.5, 50.0) +
+      Vec(cos(theta) * SPHERES_ROT_RADIUS, 0.0,
+          sin(theta) * SPHERES_ROT_RADIUS);
+  }
 };
 
+Scene g_scene;
+
 inline F clamp (F x)
 {
   return x < 0 ? 0 : x > 1 ? 1 : x;
@@ -176,12 +195,12 @@ inline int toInt (F x)
 
 inline bool intersect (const Ray &r, F &t, int &id)
 {
-  int i = sizeof(g_spheres) / sizeof(Sphere);
+  int i = SPHERES_COUNT;
   F d;
   F inf = 1e20;
   t = inf;
   while (i--) {
-    if ((d = g_spheres[i].intersect(r)) && d < t) {
+    if ((d = g_scene.spheres[i].intersect(r)) && d < t) {
       t = d;
       id = i;
     }
@@ -195,7 +214,7 @@ Vec radiance (const Ray &r, int depth, unsigned short *Xi)
   int id = 0;                           // Id of intersected object
   if (! intersect(r, t, id))            // If miss, return black
     return Vec();
-  const Sphere &obj = g_spheres[id];      // The hit object
+  const Sphere &obj = g_scene.spheres[id];      // The hit object
   Vec x = r.origin + r.direction * t;
   Vec n = (x - obj.position).normalize();
   Vec nl = n.dot(r.direction) < 0 ? n : n * -1;
@@ -260,14 +279,16 @@ Vec radiance (const Ray &r, int depth, unsigned short *Xi)
 
 int main (int argc, char *argv[])
 {
-  int w = 1024;
-  int h = 768;
-  int samples = argc == 2 ? atoi(argv[1]) / 4 : 1;
+  int w = 800;
+  int h = 600;
+  int samples = argc >= 2 ? atoi(argv[1]) / 4 : 1;
+  F   time = argc >= 3 ? atof(argv[2]) : 0.0;
   Ray camera(Vec(50,52,295.6), Vec(0,-0.042612,-1).normalize());
   Vec cx = Vec(w * .5135 / h);
   Vec cy = (cx % camera.direction).normalize() * .5135;
   Vec r;
   Vec *c = new Vec[w * h];
+  g_scene.update_time(time);
 #pragma omp parallel for schedule(dynamic, 1) private(r)    // OpenMP
   for (int y = 0; y < h; y++) {             // Loop over image rows
     fprintf(stderr, "\rRendering (%d spp) %5.2f%%",
@@ -299,9 +320,13 @@ int main (int argc, char *argv[])
       }
     }
   }
-  FILE *f = fopen("image.ppm", "w");    // Write image to PPM file.
+  char a[1024] = {0};
+  snprintf(a, sizeof(a) - 1, "image_%09.9f.ppm", time);
+  FILE *f = fopen(a, "wb");
   fprintf(f, "P3\n%d %d\n%d\n", w, h, 255);
   for (int i = 0; i < w * h; i++)
     fprintf(f, "%d %d %d ", toInt(c[i].x), toInt(c[i].y),
             toInt(c[i].z));
+  delete[] c;
+  delete g_scene;
 }