D Paste by SnakE
Description: Modified D ray tracer: all struct manipulations are in-place
Hide line numbers

Create new paste
Post a reply
View replies

Paste:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
module tracetest;
import std.math, std.string: atoi;
import std.c.stdio: printf, fprintf, stderr;
import std.gc: malloc;

const double delta; static this() { delta=sqrt(double.epsilon); }

struct Vec {
  double x, y, z;
  Vec* set(ref Vec b) { return set(b.x, b.y, b.z); }
  Vec* set(double a, double b, double c) { x=a; y=b; z=c; return this; }
  Vec* add(ref Vec b) { x+=b.x; y+=b.y; z+=b.z; return this; }
  Vec* sub(ref Vec b) { x-=b.x; y-=b.y; z-=b.z; return this; }
  Vec* mul(double a) { x*=a; y*=a; z*=a; return this; }
  double dot(ref Vec b) { return x*b.x + y*b.y + z*b.z; }
  Vec* unitise() { return mul(1f / sqrt(dot(*this))); }
}

struct Hit {
  double dist;
  Vec pos;
}
struct Ray { Vec orig, dir; }

class Scene {
  abstract void intersect(ref Hit hit, ref Ray ray);
}

template StdConstructor() {
  this(typeof(this.tupleof) p) {
    foreach (index, bogus; this.tupleof) this.tupleof[index]=p[index];
  }
}

final class Sphere : Scene {
  Vec center;
  double radius;
  mixin StdConstructor;
  double ray_sphere(ref Ray ray) {
    auto v = center;
    v.sub(ray.orig);
    double b = v.dot(ray.dir), disc = b*b - v.dot(v) + radius * radius;
    if (disc < 0) return double.infinity;
    double d = sqrt(disc), t2 = b + d;
    if (t2 < 0) return double.infinity;
    auto t1 = b - d;
    return t1 > 0 ? t1 : t2;
  }

  override void intersect(ref Hit hit, ref Ray ray) {
    auto lambda = ray_sphere(ray);
    if (lambda >= hit.dist) return;
    hit.dist = lambda;
    hit.pos.set(ray.dir).mul(lambda).add(ray.orig).sub(center).unitise();
  }
}

final class Group : Scene {
  Sphere bound;
  Scene[] child;
  mixin StdConstructor;
  override void intersect(ref Hit hit, ref Ray ray) {
    double l = bound.ray_sphere(ray);
    if (l < hit.dist)
      for (int i=0; i<child.length; ++i)
        child[i].intersect(hit, ray);
  }
}

Hit intersect(ref Ray ray, Scene s) {
  auto res = Hit(double.infinity, Vec(0, 0, 0));
  s.intersect(res, ray); return res;
}

/* modifies ray for temporary use */
double ray_trace(ref Vec light, ref Ray ray, Scene s) {
  auto hit = intersect(ray, s);
  if (hit.dist == double.infinity) return 0;
  auto g = hit.pos.dot(light);
  if (g >= 0) return 0.;
  /* hit is not needed here already, use as a temporary */
  ray.orig.add(*ray.dir.mul(hit.dist)).add(*hit.pos.mul(delta));
  ray.dir.set(light).mul(-1);
  return (intersect(ray, s).dist < double.infinity ? 0 : -g);
}

Scene create(int level, ref Vec c, double r) {
  auto s = new Sphere(c, r);
  if (level == 1) return s;
  Scene[] child; child~=s; //child.length=1; child[0]=s;
  auto rn = 3f*r/sqrt(12f);
  for (auto dz=-1; dz<=1; dz+=2)
    for (auto dx=-1; dx<=1; dx+=2)
      child~=create(level-1, *Vec(dx, 1, dz).mul(rn).add(c), r/2f);
  return new Group(new Sphere(c, 3*r), child);
}

extern(C) uint clock();

int main(/*string[] args*/) {
  int level = 6, n = 512, ss = 4;
  //if (args.length == 2) level = atoi(args[1]);
  Vec light;
  light.set(-1, -3, 2).unitise();
  auto s=create(level, Vec(0, -1, 0), 1);
  printf("P5\n%i %i\n255\n", n, n);
  Ray ray;
  for (int y=n-1; y>=0; --y)
    for (int x=0; x<n; ++x) {
      double g=0;
      for (int dx=0; dx<ss; ++dx)
        for (int dy=0; dy<ss; ++dy) {
          ray.orig.set(0, 0, -4);
          ray.dir.set(x+dx*1./ss-n/2., y+dy*1./ss-n/2., n).unitise();
          g += ray_trace(light, ray, s);
        }
      if (g!=g) g=0f;
      printf("%c", cast(char)(.5f + 255f * g / (ss*ss)));
    }
  fprintf(stderr, "%u\n", clock());
  return 0;
}

Replies:
Reply by FLYiBRVG
If only there were more cleevr people like you!

    (some replies deleted)