D Paste by flithm
Description: None
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  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
module tracetest;
import tango.math.Math;
import tango.core.Memory;
import tango.stdc.stdio;
import tango.stdc.string;

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

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

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) {
    Vec v = void;
    Vec.sub(center, ray.orig, v);
    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;
  }

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

final class Group : Scene {
  Sphere bound;
  Scene[] child;
  mixin StdConstructor;
  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);
  }
}

void intersect(ref Ray ray, Scene s, ref Hit res) {
  res.dist = double.infinity;
  memset(cast(void *) &res.pos, 0, Vec.sizeof);
  s.intersect(res, ray);
}

double ray_trace(ref Vec light, ref Ray ray, Scene s) {
  Hit hit = void;
  intersect(ray, s, hit);
  if (hit.dist == double.infinity) return 0;
  auto g = hit.pos.dot(light);
  if (g >= 0) return 0.;
  Vec mulVec = void;
  Vec.mul(hit.pos, delta, mulVec);
  Vec mulVec1 = void;
  Vec.mul(ray.dir, hit.dist, mulVec1);
  Vec p = void;
  Vec.add(ray.orig, mulVec1, p);
  Vec.add(p, mulVec, p);
  Vec mulVec2 = void;
  Vec.mul(light, -1.0, mulVec2);
  Ray r = void;
  r.orig = p;
  r.dir = mulVec2;
  intersect(r, s, hit);
  return (hit.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) {
      Vec mulVec = void;
      Vec.mul(Vec(dx, 1, dz), rn * rn, mulVec);
      Vec v = void;
      Vec.add(c, mulVec, v);
      child~=create(level-1, v, r/2f);
    }
  return new Group(new Sphere(c, 3*r), child);
}

int main(/*string[] args*/) {
  GC.disable();
  int level = 6, n = 512, ss = 4;
  //if (args.length == 2) level = atoi(args[1]);
  auto light = Vec(-1, -3, 2);
  Vec.unitise(light, light);
  auto s=create(level, Vec(0, -1, 0), 1);
  printf("P5\n%i %i\n255\n", n, n);
  const Vec rVec = Vec(0, 0, -4);
  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) {
          Vec dir= void;
          dir.x = x+dx*1./ss-n/2.;
          dir.y = y+dy*1./ss-n/2.;
          dir.z = n;
          Vec.unitise(dir, dir);
          Ray r = void;
          r.orig = rVec;
          r.dir = dir;
          g += ray_trace(light, r, s);
        }
      if (g!=g) g=0f;
      printf("%d", .5 + 255.0 * g / (ss*ss));
    }
  return 0;
}

Replies:
No replies posted yet