Mercurial > projects > ldc
annotate demos/ray.d @ 650:aa6a0b7968f7
Added test case for bug #100
Removed dubious check for not emitting static private global in other modules without access. This should be handled properly somewhere else, it's causing unresolved global errors for stuff that should work (in MiniD)
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Sun, 05 Oct 2008 17:28:15 +0200 |
parents | 718ddecc053c |
children | eef8ac26c66c |
rev | line source |
---|---|
165
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
1 import tango.stdc.stdio; |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
2 |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
3 alias char[] string; |
92 | 4 |
5 int atoi(char[] s) { | |
6 int i, fac=1; | |
7 bool neg = (s.length) && (s[0] == '-'); | |
8 char[] a = neg ? s[1..$] : s; | |
9 foreach_reverse(c; a) { | |
10 i += (c-'0') * fac; | |
11 fac *= 10; | |
12 } | |
13 return !neg ? i : -i; | |
14 } | |
15 | |
165
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
16 version(LLVMDC) |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
17 { |
620
718ddecc053c
Fix downs' raytracer demo to use new intrinsics.
Christian Kamm <kamm incasoftware de>
parents:
166
diff
changeset
|
18 pragma(intrinsic, "llvm.sqrt.f64") |
92 | 19 double sqrt(double val); |
165
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
20 } |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
21 else |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
22 { |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
23 import tango.stdc.math; |
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
24 } |
92 | 25 |
26 double delta; | |
27 static this() { delta=sqrt(real.epsilon); } | |
28 | |
29 struct Vec { | |
30 double x, y, z; | |
31 Vec opAdd(ref Vec other) { return Vec(x+other.x, y+other.y, z+other.z); } | |
32 Vec opSub(ref Vec other) { return Vec(x-other.x, y-other.y, z-other.z); } | |
33 Vec opMul(double a) { return Vec(x*a, y*a, z*a); } | |
34 double dot(ref Vec other) { return x*other.x+y*other.y+z*other.z; } | |
35 Vec unitise() { return opMul(1.0/sqrt(dot(*this))); } | |
36 } | |
37 | |
38 struct Pair(T, U) { T first; U second; } | |
39 typedef Pair!(double, Vec) Hit; | |
40 | |
41 struct Ray { Vec orig, dir; } | |
42 | |
43 class Scene { | |
44 //abstract void intersect(ref Hit, ref Ray); | |
45 void intersect(ref Hit, ref Ray) {} | |
46 } | |
47 | |
48 class Sphere : Scene { | |
49 Vec center; | |
50 double radius; | |
51 //mixin This!("center, radius"); | |
52 this(ref Vec c, double r) | |
53 { | |
54 center = c; | |
55 radius = r; | |
56 } | |
57 double ray_sphere(ref Ray ray) { | |
58 auto v = center - ray.orig, b = v.dot(ray.dir), disc=b*b - v.dot(v) + radius*radius; | |
59 if (disc < 0) return double.infinity; | |
60 auto d = sqrt(disc), t2 = b + d; | |
61 if (t2 < 0) return double.infinity; | |
62 auto t1 = b - d; | |
63 return (t1 > 0 ? t1 : t2); | |
64 } | |
65 void intersect(ref Hit hit, ref Ray ray) { | |
66 auto lambda = ray_sphere(ray); | |
67 if (lambda < hit.first) | |
68 hit = Hit(lambda, (ray.orig + lambda*ray.dir - center).unitise); | |
69 } | |
70 } | |
71 | |
72 class Group : Scene { | |
73 Sphere bound; | |
74 Scene[] children; | |
75 //mixin This!("bound, children"); | |
76 this (Sphere s, Scene[] c) | |
77 { | |
78 bound = s; | |
79 children = c; | |
80 } | |
81 void intersect(ref Hit hit, ref Ray ray) { | |
82 auto l = bound.ray_sphere(ray); | |
83 if (l < hit.first) foreach (child; children) child.intersect(hit, ray); | |
84 } | |
85 } | |
86 | |
87 double ray_trace(ref Vec light, ref Ray ray, Scene s) { | |
88 auto hit=Hit(double.infinity, Vec(0, 0, 0)); | |
89 s.intersect(hit, ray); | |
90 if (hit.first == double.infinity) return 0.0; | |
91 auto g = hit.second.dot(light); | |
92 if (g >= 0) return 0.0; | |
93 auto p = ray.orig + ray.dir*hit.first + hit.second*delta; | |
94 auto hit2=Hit(double.infinity, Vec(0, 0, 0)); | |
95 s.intersect(hit2, Ray(p, light*-1.0)); | |
96 return (hit2.first < double.infinity ? 0 : -g); | |
97 } | |
98 | |
99 Scene create(int level, ref Vec c, double r) { | |
100 auto s = new Sphere(c, r); | |
101 if (level == 1) return s; | |
94
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
92
diff
changeset
|
102 Scene[] children; |
61615fa85940
[svn r98] Added support for std.c.stdlib.alloca via pragma(LLVM_internal, "alloca").
lindquist
parents:
92
diff
changeset
|
103 children ~= s; |
92 | 104 double rn = 3*r/sqrt(12.0); |
105 for (int dz=-1; dz<=1; dz+=2) | |
106 for (int dx=-1; dx<=1; dx+=2) | |
107 children~=create(level-1, c + Vec(dx, 1, dz)*rn, r/2); | |
108 return new Group(new Sphere(c, 3*r), children); | |
109 } | |
110 | |
111 void main(string[] args) { | |
112 int level = (args.length==3 ? args[1].atoi() : 9), | |
113 n = (args.length==3 ? args[2].atoi() : 512), ss = 4; | |
114 auto light = Vec(-1, -3, 2).unitise(); | |
115 auto s=create(level, Vec(0, -1, 0), 1); | |
166
a2c4dc388d5e
[svn r182] Oups, the PGM output for the raytracer demo was borked.
lindquist
parents:
165
diff
changeset
|
116 printf("P5\n%d %d\n255\n", n,n); |
92 | 117 for (int y=n-1; y>=0; --y) |
118 for (int x=0; x<n; ++x) { | |
119 double g=0; | |
120 for (int d=0; d<ss*ss; ++d) { | |
121 auto dir=Vec(x+(d%ss)*1.0/ss-n/2.0, y+(d/ss)*1.0/ss-n/2.0, n).unitise(); | |
165
9922b9982552
[svn r181] Updated the raytracer demo by downs to work with tango :) My quick
lindquist
parents:
100
diff
changeset
|
122 g += ray_trace(light, Ray(Vec(0, 0, -4), dir), s); |
92 | 123 } |
124 printf("%c", cast(ubyte)(0.5 + 255.0 * g / (ss*ss))); | |
125 } | |
126 } |