SHOW:
|
|
- or go back to the newest paste.
1 | //----Render loop-----// | |
2 | this.canvas = this.surfaceHolder.lockCanvas(); | |
3 | ||
4 | int width = canvas.getWidth(); | |
5 | int height = canvas.getHeight(); | |
6 | ||
7 | float fov = 160.0f * (float)Math.PI / 180.0f; | |
8 | float zdir = 1.0f / (float)Math.tan(fov); | |
9 | float aspect = (float)height / (float)width; | |
10 | ||
11 | for(int x = 0; x < width; x++){ | |
12 | for(int y = 0; y < height; y++){ | |
13 | float xdir = (x / (float)width) * 2.0f - 1.0f; | |
14 | float ydir = ((y / (float)height) * 2.0f - 1.0f) * aspect; | |
15 | ||
16 | Vector3D direction = new Vector3D(xdir, ydir, zdir).normalize(); | |
17 | Ray ray = new Ray(Camera, direction); | |
18 | ||
19 | float r = 0, g = 0, b = 0; | |
20 | for(int i = 0; i < RAYS_PER_PIXEL; i++){ | |
21 | CColor color = Trace(ray, 0); | |
22 | r += color.r; | |
23 | g += color.g; | |
24 | b += color.b; | |
25 | } | |
26 | ||
27 | r/= RAYS_PER_PIXEL; | |
28 | g/= RAYS_PER_PIXEL; | |
29 | b/= RAYS_PER_PIXEL; | |
30 | ||
31 | Paint paint = new Paint(); | |
32 | paint.setColor(Color.argb(255,(int)r,(int)g,(int)b)); | |
33 | canvas.drawPoint(x,y,paint); | |
34 | ||
35 | ||
36 | //---Trace Function---// | |
37 | ||
38 | public CColor Trace(Ray ray, int depth){ | |
39 | float hitDistance = 5000.0f; | |
40 | BaseObject hitObject = null; | |
41 | ||
42 | for(BaseObject obj: scene.SceneObjects){ | |
43 | float intersect = obj.intersect(ray); | |
44 | if(intersect < hitDistance && intersect > -1.0f) { | |
45 | hitDistance = intersect; | |
46 | hitObject = obj; | |
47 | } | |
48 | } | |
49 | ||
50 | if(hitDistance == 5000.0f) { | |
51 | return new CColor(0,0,0); | |
52 | } | |
53 | ||
54 | if(hitObject.isEmitter) { | |
55 | return hitObject.color; | |
56 | } | |
57 | ||
58 | if(depth == MAX_DEPTH) { | |
59 | return new CColor(0,0,0); | |
60 | } | |
61 | ||
62 | Vector3D hitPoint = ray.origin.add(ray.direction.mult(hitDistance * 0.99f)); | |
63 | Vector3D normal = hitObject.normal(hitPoint); | |
64 | ||
65 | Vector3D randomVector = Vector3D.getRandomVectorInHemisphere(); | |
66 | if(randomVector.dot(normal) < 0.0f) | |
67 | randomVector = randomVector.negate(); | |
68 | ||
69 | Ray reflectionRay = new Ray(hitPoint, randomVector.normalize()); | |
70 | ||
71 | CColor returnColor = Trace(reflectionRay, depth + 1); | |
72 | ||
73 | float r = hitObject.color.r * returnColor.r; | |
74 | float g = hitObject.color.g * returnColor.g; | |
75 | float b = hitObject.color.b * returnColor.b; | |
76 | ||
77 | r /= 255.0f; | |
78 | g /= 255.0f; | |
79 | b /= 255.0f; | |
80 | ||
81 | return new CColor(r,g,b); | |
82 | } | |
83 | ||
84 | //---Vector Class---// | |
85 | ||
86 | public class Vector3D { | |
87 | public float x; | |
88 | public float y; | |
89 | public float z; | |
90 | private static Random rnd = new Random(new Date().getTime()); | |
91 | ||
92 | public Vector3D(float x, float y, float z){ | |
93 | this.x = x; | |
94 | this.y = y; | |
95 | this.z = z; | |
96 | } | |
97 | ||
98 | public Vector3D add(Vector3D addVector){ | |
99 | return new Vector3D(this.x + addVector.x, this.y + addVector.y, this.z + addVector.z); | |
100 | } | |
101 | ||
102 | public Vector3D sub(Vector3D subVector){ | |
103 | return new Vector3D(this.x - subVector.x, this.y - subVector.y, this.z - subVector.z); | |
104 | } | |
105 | ||
106 | public Vector3D mult(Vector3D multVector){ | |
107 | return new Vector3D(this.x * multVector.x, this.y * multVector.y, this.z * multVector.z); | |
108 | } | |
109 | ||
110 | public Vector3D mult(float mult){ | |
111 | return mult(new Vector3D(mult,mult,mult)); | |
112 | } | |
113 | ||
114 | public float dot(Vector3D dotVector){ | |
115 | return this.x * dotVector.x + this.y * dotVector.y + this.z * dotVector.z; | |
116 | } | |
117 | ||
118 | public Vector3D normalize(){ | |
119 | float f = (float)(1.0f / Math.sqrt(this.dot(this))); | |
120 | ||
121 | x *= f; | |
122 | y *= f; | |
123 | z *= f; | |
124 | ||
125 | return new Vector3D(x,y,z); | |
126 | } | |
127 | ||
128 | public Vector3D negate(){ | |
129 | return new Vector3D(this.x = -x, this.y = -y, this.z = -z); | |
130 | } | |
131 | ||
132 | public static Vector3D getRandomVectorInHemisphere(){ | |
133 | float x = (float)rnd.nextDouble() * 2.0f - 1.0f; | |
134 | float y = (float)rnd.nextDouble() * 2.0f - 1.0f; | |
135 | float z = (float)rnd.nextDouble() * 2.0f - 1.0f; | |
136 | ||
137 | int negate = rnd.nextInt(); | |
138 | ||
139 | if(negate % 2 > 0){ | |
140 | x *= -1; | |
141 | y *= -1; | |
142 | z *= -1; | |
143 | } | |
144 | ||
145 | return new Vector3D(x,y,z).normalize(); | |
146 | } | |
147 | } | |
148 | ||
149 | //---Sphere---// | |
150 | ||
151 | public class Sphere extends BaseObject { | |
152 | public Vector3D center; | |
153 | public float radius; | |
154 | ||
155 | public Sphere(CColor color, boolean isEmitter, Vector3D center, float radius){ | |
156 | this.color = color; | |
157 | this.isEmitter = isEmitter; | |
158 | this.center = center; | |
159 | this.radius = radius; | |
160 | } | |
161 | ||
162 | public float intersect(Ray ray){ | |
163 | Vector3D v = ray.origin.sub(this.center); | |
164 | ||
165 | float a = ray.direction.dot(ray.direction); | |
166 | float b = 2.0f * ray.direction.dot(v); | |
167 | float c = v.dot(v) - (this.radius * this.radius); | |
168 | ||
169 | float discriminant = (b*b) - (4.0f * a * c); | |
170 | ||
171 | if(discriminant > 0){ | |
172 | float x1 = (-b - (float)Math.sqrt(discriminant) / (2.0f * a)); | |
173 | float x2 = (-b + (float)Math.sqrt(discriminant) / (2.0f * a)); | |
174 | ||
175 | ||
176 | if (x1 >= 0 && x2 >= 0) return x1; | |
177 | if (x1 < 0 && x2 >= 0) return x2; | |
178 | else return -1.0f; | |
179 | } | |
180 | else | |
181 | return -1.0f; | |
182 | } | |
183 | ||
184 | public Vector3D normal(Vector3D intersectionVector){ | |
185 | return intersectionVector.sub(this.center).normalize(); | |
186 | } | |
187 | } |