1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "app/app.hh"
|
---|
10 | #include "main/main.hh"
|
---|
11 | #include "window/window.hh"
|
---|
12 | #include "image/image.hh"
|
---|
13 | #include "palette/pal.hh"
|
---|
14 | #include "math/transform.hh"
|
---|
15 | #include "window/wmanager.hh"
|
---|
16 | #include "memory/malloc.hh"
|
---|
17 | #include "device/event.hh"
|
---|
18 | #include "gui/li_pull_menu.hh"
|
---|
19 | #include "menu/pull.hh"
|
---|
20 | #include "r1_api.hh"
|
---|
21 | #include "r1_win.hh"
|
---|
22 | #include "threads/threads.hh"
|
---|
23 | #include "device/keys.hh"
|
---|
24 | #include "window/win_evt.hh"
|
---|
25 | #include "r1_clip.hh"
|
---|
26 | #include "loaders/jpg_write.hh"
|
---|
27 | #include "gui/button.hh"
|
---|
28 | #include "gui/text.hh"
|
---|
29 |
|
---|
30 | r1_render_api_class *api=0;
|
---|
31 |
|
---|
32 | inline float frand() { return ((rand()%5000)-2500.0); }
|
---|
33 |
|
---|
34 | enum {
|
---|
35 | SAVE
|
---|
36 | };
|
---|
37 |
|
---|
38 |
|
---|
39 | struct camera_info
|
---|
40 | {
|
---|
41 | i4_3d_vector position;
|
---|
42 | i4_3d_vector rotation;
|
---|
43 |
|
---|
44 | void calc_transform(i4_transform_class &t)
|
---|
45 | {
|
---|
46 | t.identity();
|
---|
47 | t.mult_rotate_x(rotation.x);
|
---|
48 | t.mult_rotate_y(rotation.y);
|
---|
49 | t.mult_rotate_z(rotation.z);
|
---|
50 | t.mult_translate(position.x, position.y, position.z);
|
---|
51 |
|
---|
52 | }
|
---|
53 |
|
---|
54 |
|
---|
55 | camera_info()
|
---|
56 | {
|
---|
57 | position=i4_3d_vector(0,0,1.5);
|
---|
58 | rotation=i4_3d_vector(0, 0, 0);
|
---|
59 | }
|
---|
60 |
|
---|
61 | };
|
---|
62 |
|
---|
63 |
|
---|
64 |
|
---|
65 |
|
---|
66 |
|
---|
67 | void render_thread_start(void *context);
|
---|
68 |
|
---|
69 | #define S 2.2
|
---|
70 | enum {T_C=1 };
|
---|
71 |
|
---|
72 | i4_3d_vector circles[T_C]={ i4_3d_vector(0,0,0)
|
---|
73 | // i4_3d_vector(-S,0,0)
|
---|
74 | // i4_3d_vector(S,0,0)
|
---|
75 |
|
---|
76 |
|
---|
77 | };
|
---|
78 |
|
---|
79 |
|
---|
80 |
|
---|
81 |
|
---|
82 | float ray_sphere_intersect(i4_3d_vector ray0,
|
---|
83 | i4_3d_vector ray_dir,
|
---|
84 | i4_3d_vector center,
|
---|
85 | float r)
|
---|
86 | {
|
---|
87 | float i=ray_dir.x, j=ray_dir.y, k=ray_dir.z;
|
---|
88 | float l=center.x, m=center.y, n=center.z;
|
---|
89 |
|
---|
90 | float a=i*i + j*j + k*k;
|
---|
91 |
|
---|
92 | float b=2*(i*(ray0.x - l) + j*(ray0.y - m) + k*(ray0.z-n));
|
---|
93 |
|
---|
94 | // float c=l*l + m*m + n*n + ray0.x*ray0.x + ray0.y*ray0.y + ray0.z*ray0.z -
|
---|
95 | // 2*(l*ray0.x + m*ray0.y + n*ray0.z) - r*r;
|
---|
96 |
|
---|
97 | float c=(ray0.x-l)*(ray0.x-l) + (ray0.y-m)*(ray0.y-m) + (ray0.z-n)*(ray0.z-n) - r*r;
|
---|
98 |
|
---|
99 |
|
---|
100 |
|
---|
101 | float descriminant = b*b - 4*a*c;
|
---|
102 | if (descriminant<0)
|
---|
103 | return -1;
|
---|
104 |
|
---|
105 | if (descriminant==0)
|
---|
106 | return -b/(2*a);
|
---|
107 | else
|
---|
108 | {
|
---|
109 | float sd=sqrt(descriminant);
|
---|
110 | float oo_2a=1.0/(2*a);
|
---|
111 | float t1=(-b + sd ) * oo_2a;
|
---|
112 | float t2=(-b - sd ) * oo_2a;
|
---|
113 | if (t1>0)
|
---|
114 | {
|
---|
115 | if (t1<t2 || t2<0)
|
---|
116 | return t1;
|
---|
117 | else
|
---|
118 | return t2;
|
---|
119 | }
|
---|
120 | else return t2;
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 | float spline(float x, int nknots, float *knot)
|
---|
125 | {
|
---|
126 | const float cr[16]={-0.5, 1.5, -1.5, 0.5,
|
---|
127 | 1.0, -2.5, 2.0, -0.5,
|
---|
128 | -0.5, 0.0, 0.5, 0.0,
|
---|
129 | 0.0, 1.0, 0.0, 0.0};
|
---|
130 |
|
---|
131 | int nspans=nknots-3;
|
---|
132 |
|
---|
133 | if (nspans<1)
|
---|
134 | {
|
---|
135 | i4_warning("spline has to few knots");
|
---|
136 | return 0;
|
---|
137 | }
|
---|
138 |
|
---|
139 | if (x<0) x=0;
|
---|
140 | if (x>1) x=1;
|
---|
141 | x*=nspans;
|
---|
142 |
|
---|
143 | int span=(int)x;
|
---|
144 | if (span>=nknots-3)
|
---|
145 | span=nknots-3;
|
---|
146 |
|
---|
147 | x-=span;
|
---|
148 | knot+=span;
|
---|
149 |
|
---|
150 | float c3 = cr[0]*knot[0] + cr[1]*knot[1] + cr[2]*knot[2] + cr[3]*knot[3];
|
---|
151 | float c2 = cr[4]*knot[0] + cr[5]*knot[1] + cr[6]*knot[2] + cr[7]*knot[3];
|
---|
152 | float c1 = cr[8]*knot[0] + cr[9]*knot[1] + cr[10]*knot[2] + cr[11]*knot[3];
|
---|
153 | float c0 = cr[12]*knot[0] + cr[13]*knot[1] + cr[14]*knot[2] + cr[15]*knot[3];
|
---|
154 |
|
---|
155 | return ((c3*x + c2)*x + c1)*x + c0;
|
---|
156 | }
|
---|
157 |
|
---|
158 |
|
---|
159 | struct path_info
|
---|
160 | {
|
---|
161 | i4_3d_vector start,
|
---|
162 | pos, // location in space where vector hit object
|
---|
163 | normal, // normal at surface
|
---|
164 | bump_normal,
|
---|
165 | a,b, // tangent vectors
|
---|
166 | color;
|
---|
167 | };
|
---|
168 |
|
---|
169 | class trace_view;
|
---|
170 | trace_view *trace=0;
|
---|
171 |
|
---|
172 | class trace_view : public i4_window_class
|
---|
173 | {
|
---|
174 | public:
|
---|
175 | i4_transform_class t;
|
---|
176 | camera_info v;
|
---|
177 |
|
---|
178 | int iw,ih;
|
---|
179 | i4_3d_vector light;
|
---|
180 | int mouse_x, mouse_y;
|
---|
181 | float theta;
|
---|
182 | r1_render_window_class *rwin_parent;
|
---|
183 | int rendering, abort_render, reset_render;
|
---|
184 | i4_critical_section_class reset_lock;
|
---|
185 | i4_bool mouse_look_grab;
|
---|
186 | path_info path[10];
|
---|
187 | int path_len;
|
---|
188 |
|
---|
189 | r1_render_window_class *rwin() { return rwin_parent; }
|
---|
190 |
|
---|
191 | ~trace_view()
|
---|
192 | {
|
---|
193 | if (rendering)
|
---|
194 | {
|
---|
195 | abort_render=1;
|
---|
196 | while (rendering)
|
---|
197 | i4_thread_yield();
|
---|
198 | }
|
---|
199 | }
|
---|
200 |
|
---|
201 | struct noise_struct
|
---|
202 | {
|
---|
203 | enum {TSIZE=256};
|
---|
204 | float data[TSIZE];
|
---|
205 | int init;
|
---|
206 | noise_struct() { init=0; }
|
---|
207 |
|
---|
208 | float gnoise(int x, int y, int z)
|
---|
209 | {
|
---|
210 | return data[(x+(y*12345+((z*92831243)&(TSIZE-1))&(TSIZE-1))&(TSIZE-1))];
|
---|
211 | }
|
---|
212 |
|
---|
213 | float bilinear_interp(float p1, float p2, float p3, float p4, float xr, float yr)
|
---|
214 | {
|
---|
215 | float t1=(p2-p1)*xr+p1;
|
---|
216 | float t2=(p4-p3)*xr+p3;
|
---|
217 | return (t2-t1)*yr+t1;
|
---|
218 | }
|
---|
219 |
|
---|
220 | void init_noise()
|
---|
221 | {
|
---|
222 | if (!init)
|
---|
223 | {
|
---|
224 | init=1;
|
---|
225 | for (int i=0; i<TSIZE; i++)
|
---|
226 | data[i]=((rand()&0x7fff)/(double)0x7fff);
|
---|
227 | }
|
---|
228 | }
|
---|
229 |
|
---|
230 | float get(i4_3d_vector p)
|
---|
231 | {
|
---|
232 | init_noise();
|
---|
233 | int ix=(int)p.x, iy=(int)p.y, iz=(int)p.z;
|
---|
234 | float xr=p.x-ix, yr=p.y-iy, zr=p.z-iz;
|
---|
235 | float xknots[4], yknots[4], zknots[4];
|
---|
236 |
|
---|
237 | for (int k=-1; k<=2; k++)
|
---|
238 | {
|
---|
239 | for (int j=-1; j<=2; j++)
|
---|
240 | {
|
---|
241 | for (int i=-1; i<=2; i++)
|
---|
242 | xknots[i+1]=gnoise(ix+i, iy+j, iz+k);
|
---|
243 | yknots[j+1]=spline(xr, 4, xknots);
|
---|
244 | }
|
---|
245 | zknots[k+1]=spline(yr, 4, yknots);
|
---|
246 | }
|
---|
247 | return spline(zr, 4, zknots);
|
---|
248 | }
|
---|
249 |
|
---|
250 | float get1d(float p)
|
---|
251 | {
|
---|
252 | init_noise();
|
---|
253 | int ix=(int)p;
|
---|
254 | float xr=p-ix;
|
---|
255 | float xknots[4];
|
---|
256 |
|
---|
257 | for (int i=-1; i<=2; i++)
|
---|
258 | xknots[i+1]=gnoise(ix+i, 0, 0);
|
---|
259 | return spline(xr, 4, xknots);
|
---|
260 | }
|
---|
261 |
|
---|
262 |
|
---|
263 |
|
---|
264 | } noise;
|
---|
265 |
|
---|
266 |
|
---|
267 | float turbulance1d(float v)
|
---|
268 | {
|
---|
269 | float r=0, f=1.0;
|
---|
270 | for (int t=0; t<4; t++)
|
---|
271 | {
|
---|
272 | r+=(noise.get1d(v)-0.5)/f;
|
---|
273 | f*=2.17;
|
---|
274 | v*=f;
|
---|
275 | }
|
---|
276 |
|
---|
277 | r+=0.5;
|
---|
278 | if (r<0) r=0;
|
---|
279 | if (r>1) r=1;
|
---|
280 |
|
---|
281 | return r;
|
---|
282 | }
|
---|
283 |
|
---|
284 | float turbulance(i4_3d_vector v, int octaves=4)
|
---|
285 | {
|
---|
286 | float r=0, f=1.0;
|
---|
287 | for (int t=0; t<octaves; t++)
|
---|
288 | {
|
---|
289 | r+=(noise.get(v)-0.5)/f;
|
---|
290 | f*=2.17;
|
---|
291 | v*=f;
|
---|
292 | }
|
---|
293 |
|
---|
294 | r+=0.5;
|
---|
295 | if (r<0) r=0;
|
---|
296 | if (r>1) r=1;
|
---|
297 |
|
---|
298 | return r;
|
---|
299 | }
|
---|
300 |
|
---|
301 | void planet_color(float x, i4_3d_vector &c)
|
---|
302 | {
|
---|
303 | float b[5]={0.1, 0, 0.06, 0.0 };
|
---|
304 | float g[5]={0.3, 0.2, 0.2, 0.6 };
|
---|
305 | float r[5]={0.5, 0.8, 0.4, 0.7 };
|
---|
306 |
|
---|
307 | c.x=spline(x, 4,r); c.y=spline(x, 4,g); c.z=spline(x, 4,b);
|
---|
308 | }
|
---|
309 |
|
---|
310 |
|
---|
311 |
|
---|
312 |
|
---|
313 | void marble_color(float x, i4_3d_vector &c)
|
---|
314 | {
|
---|
315 | float b[5]={0.2, 0.12, 0.06, 0.10 };
|
---|
316 | float g[5]={0.3, 0.20, 0.05, 0.31 };
|
---|
317 | float r[5]={0.5, 0.29, 0.12, 0.11 };
|
---|
318 |
|
---|
319 |
|
---|
320 | // x=1.0-x*x; kiwi color
|
---|
321 | // float b[5]={0.5, 0.3, 0.15, 0.1 };
|
---|
322 | // float g[5]={0.5, 0.4, 0.2, 0.1 };
|
---|
323 | // float r[5]={0.5, 0.3, 0.2, 0.5 };
|
---|
324 |
|
---|
325 |
|
---|
326 | c.x=spline(x, 4,r)*2;
|
---|
327 | c.y=spline(x, 4,g)*2;
|
---|
328 | c.z=spline(x, 4,b)*2;
|
---|
329 |
|
---|
330 | }
|
---|
331 |
|
---|
332 |
|
---|
333 |
|
---|
334 | void shade_point(i4_3d_vector eye, path_info &p)
|
---|
335 | {
|
---|
336 | i4_3d_vector bump_pos=p.pos, bpa, bpb;
|
---|
337 | bump_pos.x+=100; bump_pos.y+=100; bump_pos.z+=100;
|
---|
338 | // bump_pos*=4;
|
---|
339 |
|
---|
340 |
|
---|
341 | bpa.x=bump_pos.x+p.a.x*0.0001;
|
---|
342 | bpa.y=bump_pos.y+p.a.y*0.0001;
|
---|
343 | bpa.z=bump_pos.z+p.a.z*0.0001;
|
---|
344 |
|
---|
345 | bpb.x=bump_pos.x+p.b.x*0.0001;
|
---|
346 | bpb.y=bump_pos.y+p.b.y*0.0001;
|
---|
347 | bpb.z=bump_pos.z+p.b.z*0.0001;
|
---|
348 |
|
---|
349 | float bump_h=turbulance(bump_pos,4);
|
---|
350 | float bump_dx=(turbulance(bpa,4)-bump_h)*2.0;
|
---|
351 | float bump_dy=(turbulance(bpb,4)-bump_h)*2.0;
|
---|
352 |
|
---|
353 | p.bump_normal.x=p.normal.x + bpa.x*bump_dx + bpb.x*bump_dy;
|
---|
354 | p.bump_normal.y=p.normal.y + bpa.y*bump_dx + bpb.y*bump_dy;
|
---|
355 | p.bump_normal.z=p.normal.z + bpa.z*bump_dx + bpb.z*bump_dy;
|
---|
356 |
|
---|
357 | p.bump_normal.normalize();
|
---|
358 |
|
---|
359 |
|
---|
360 |
|
---|
361 |
|
---|
362 |
|
---|
363 |
|
---|
364 |
|
---|
365 | float c1=-p.bump_normal.dot(light);
|
---|
366 | i4_3d_vector reflect=i4_3d_vector(light.x + 2*p.bump_normal.x*c1,
|
---|
367 | light.y + 2*p.bump_normal.y*c1,
|
---|
368 | light.z + 2*p.bump_normal.z*c1);
|
---|
369 |
|
---|
370 |
|
---|
371 |
|
---|
372 | float light_v=-light.dot(p.bump_normal)*0.4;
|
---|
373 |
|
---|
374 | i4_3d_vector view_dir=p.pos;
|
---|
375 | view_dir-=eye;
|
---|
376 | view_dir.normalize();
|
---|
377 | float view_dot_r=-view_dir.dot(reflect);
|
---|
378 | if (view_dot_r>=0)
|
---|
379 | {
|
---|
380 | light_v += pow(view_dot_r, 4)*0.5;
|
---|
381 | }
|
---|
382 |
|
---|
383 | light_v+=0.5; // ambient
|
---|
384 |
|
---|
385 | i4_3d_vector c=p.pos;
|
---|
386 | c.x+=100; c.y+=100; c.z+=100;
|
---|
387 | c*=4.0;
|
---|
388 | float v=turbulance(c);
|
---|
389 | // v=((sin(c.x)+sin(c.y)+sin(c.z))*v/3.0);
|
---|
390 |
|
---|
391 |
|
---|
392 | // p.color=i4_3d_vector(v,v,v);
|
---|
393 |
|
---|
394 | /*
|
---|
395 | i4_3d_vector c=p.pos;
|
---|
396 | c.x+=10;
|
---|
397 | c.y+=10;
|
---|
398 | c.z+=10;
|
---|
399 |
|
---|
400 | c*=20.0;
|
---|
401 | float v;
|
---|
402 |
|
---|
403 |
|
---|
404 | float dist=c.length();
|
---|
405 | float q1=cos(c.x+c.y+c.z)*2.0;
|
---|
406 | float q2=sin(c.x-c.y-c.z)*2.0;
|
---|
407 | float q3=sin(dist*4);
|
---|
408 |
|
---|
409 |
|
---|
410 | v=turbulance(i4_3d_vector(c.x,c.y,c.z));
|
---|
411 |
|
---|
412 | v=((sin(c.x)*0.1 + q3*0.9)*0.5+0.5)*v;
|
---|
413 |
|
---|
414 |
|
---|
415 |
|
---|
416 | if (v>1 || v<0)
|
---|
417 | i4_error("bad v");
|
---|
418 |
|
---|
419 | marble_color(v, p.color);
|
---|
420 | */
|
---|
421 |
|
---|
422 | planet_color(v, p.color);
|
---|
423 |
|
---|
424 | p.color*=light_v;
|
---|
425 |
|
---|
426 |
|
---|
427 | if (p.color.x<0) p.color.x=0;
|
---|
428 | if (p.color.x>1) p.color.x=1;
|
---|
429 | if (p.color.y<0) p.color.y=0;
|
---|
430 | if (p.color.y>1) p.color.y=1;
|
---|
431 | if (p.color.z<0) p.color.z=0;
|
---|
432 | if (p.color.z>1) p.color.z=1;
|
---|
433 | }
|
---|
434 |
|
---|
435 |
|
---|
436 | void calc_transform()
|
---|
437 | {
|
---|
438 | v.calc_transform(t);
|
---|
439 | // t.inverse_transform(i4_3d_vector(0,0,0), eye);
|
---|
440 | request_redraw();
|
---|
441 | render();
|
---|
442 |
|
---|
443 |
|
---|
444 | }
|
---|
445 |
|
---|
446 | void move_cam(float x, float y, float z)
|
---|
447 | {
|
---|
448 | i4_3d_vector i,j,k;
|
---|
449 | i4_3d_vector c;
|
---|
450 | t.inverse_transform(i4_3d_vector(0,0,0), c);
|
---|
451 | t.inverse_transform(i4_3d_vector(1,0,0), i); i-=c; i*=x;
|
---|
452 | t.inverse_transform(i4_3d_vector(0,1,0), j); j-=c; j*=y;
|
---|
453 | t.inverse_transform(i4_3d_vector(0,0,1), k); k-=c; k*=z;
|
---|
454 |
|
---|
455 | v.position-=i;
|
---|
456 | v.position-=j;
|
---|
457 | v.position-=k;
|
---|
458 |
|
---|
459 | calc_transform();
|
---|
460 | }
|
---|
461 |
|
---|
462 | void rotate_cam(float x, float y, float z)
|
---|
463 | {
|
---|
464 | v.rotation.x+=x;
|
---|
465 | v.rotation.y+=y;
|
---|
466 | v.rotation.z+=z;
|
---|
467 | calc_transform();
|
---|
468 | }
|
---|
469 |
|
---|
470 |
|
---|
471 |
|
---|
472 | void trace_ray(i4_3d_vector eye, i4_3d_vector r0, i4_3d_vector ray_dir,
|
---|
473 | int depth,
|
---|
474 | float &z,
|
---|
475 | path_info &cpath,
|
---|
476 | i4_bool store_path=i4_F)
|
---|
477 | {
|
---|
478 | if (depth>5)
|
---|
479 | cpath.color=i4_3d_vector(0,0,0);
|
---|
480 |
|
---|
481 | float closest_dist=10000;
|
---|
482 | int closest=-1;
|
---|
483 |
|
---|
484 | for (int i=0; i<T_C; i++)
|
---|
485 | {
|
---|
486 | float time=ray_sphere_intersect(r0, ray_dir, circles[i], 1);
|
---|
487 |
|
---|
488 | if (time>0.001 && time<closest_dist)
|
---|
489 | {
|
---|
490 | closest_dist=time;
|
---|
491 | closest=i;
|
---|
492 | }
|
---|
493 | }
|
---|
494 |
|
---|
495 | if (closest!=-1)
|
---|
496 | {
|
---|
497 | i4_3d_vector i_spot=ray_dir, ti_spot;
|
---|
498 | i_spot*=closest_dist;
|
---|
499 | i_spot+=r0;
|
---|
500 |
|
---|
501 | i4_3d_vector cir=circles[closest];
|
---|
502 | float cr_dist=sqrt((cir.x-i_spot.x)*(cir.x-i_spot.x)+
|
---|
503 | (cir.y-i_spot.y)*(cir.y-i_spot.y)+
|
---|
504 | (cir.z-i_spot.z)*(cir.z-i_spot.z));
|
---|
505 |
|
---|
506 |
|
---|
507 | t.transform(i_spot, ti_spot);
|
---|
508 | z=ti_spot.z;
|
---|
509 |
|
---|
510 |
|
---|
511 |
|
---|
512 | i4_3d_vector normal=i_spot;
|
---|
513 | normal-=circles[closest];
|
---|
514 | normal.normalize();
|
---|
515 |
|
---|
516 |
|
---|
517 | cpath.start=eye;
|
---|
518 | cpath.pos=i_spot;
|
---|
519 | cpath.normal=normal;
|
---|
520 |
|
---|
521 | float phi=acos(i4_3d_vector(0,0,1).dot(normal));
|
---|
522 | float zb=i4_3d_vector(0,0,1).dot(normal);
|
---|
523 |
|
---|
524 | cpath.a.cross(i4_3d_vector(0,0,1),normal);
|
---|
525 |
|
---|
526 | // cpath.a=i4_3d_vector(cos(phi),sin(phi),sin(zb));
|
---|
527 | // cpath.a.normalize();
|
---|
528 | cpath.b.cross(cpath.normal, cpath.a);
|
---|
529 |
|
---|
530 | if (store_path)
|
---|
531 | {
|
---|
532 | path[path_len]=cpath;
|
---|
533 | path_len++;
|
---|
534 | }
|
---|
535 |
|
---|
536 |
|
---|
537 | shade_point(eye, cpath);
|
---|
538 |
|
---|
539 | float c1=-ray_dir.dot(cpath.bump_normal);
|
---|
540 | i4_3d_vector reflect=i4_3d_vector(ray_dir.x + 2*cpath.bump_normal.x*c1,
|
---|
541 | ray_dir.y + 2*cpath.bump_normal.y*c1,
|
---|
542 | ray_dir.z + 2*cpath.bump_normal.z*c1);
|
---|
543 | reflect.normalize();
|
---|
544 |
|
---|
545 |
|
---|
546 | float discard_z;
|
---|
547 | path_info npath;
|
---|
548 | trace_ray(eye, i_spot, reflect, depth+1, discard_z, npath, store_path);
|
---|
549 |
|
---|
550 | npath.color*=0.10;
|
---|
551 | cpath.color+=npath.color;
|
---|
552 |
|
---|
553 | if (cpath.color.x<0) cpath.color.x=0;
|
---|
554 | if (cpath.color.x>1) cpath.color.x=1;
|
---|
555 | if (cpath.color.y<0) cpath.color.y=0;
|
---|
556 | if (cpath.color.y>1) cpath.color.y=1;
|
---|
557 | if (cpath.color.z<0) cpath.color.z=0;
|
---|
558 | if (cpath.color.z>1) cpath.color.z=1;
|
---|
559 | }
|
---|
560 | else
|
---|
561 | cpath.color=i4_3d_vector(0,0,0);
|
---|
562 | }
|
---|
563 |
|
---|
564 | void thread_render()
|
---|
565 | {
|
---|
566 | reset_lock.lock();
|
---|
567 | i4_set_thread_priority(i4_get_thread_id(), I4_THREAD_PRIORITY_LOW);
|
---|
568 |
|
---|
569 | do
|
---|
570 | {
|
---|
571 | reset_render=0;
|
---|
572 | reset_lock.unlock();
|
---|
573 |
|
---|
574 | api->clear_area(0,0, width()-1, height()-1, 0x4f4f4f, 1000);
|
---|
575 |
|
---|
576 | srand(0);
|
---|
577 |
|
---|
578 |
|
---|
579 | i4_3d_vector center;
|
---|
580 | i4_3d_vector xi, yi;
|
---|
581 | i4_3d_vector ray, eye;
|
---|
582 |
|
---|
583 |
|
---|
584 | t.inverse_transform(i4_3d_vector(0,0,0), eye);
|
---|
585 | t.inverse_transform(i4_3d_vector(0,0,1), center);
|
---|
586 | t.inverse_transform(i4_3d_vector(1,0,1), xi); xi-=center;
|
---|
587 | t.inverse_transform(i4_3d_vector(0,1,1), yi); yi-=center;
|
---|
588 |
|
---|
589 | float xm=width()/2.0;
|
---|
590 | float ym=height()/2.0;
|
---|
591 |
|
---|
592 |
|
---|
593 |
|
---|
594 | for (int y=0; y<height(); y++)
|
---|
595 | {
|
---|
596 | float fy=(y-ym)/ym;
|
---|
597 |
|
---|
598 | i4_3d_vector ya=yi;
|
---|
599 | ya*=fy;
|
---|
600 |
|
---|
601 |
|
---|
602 | for (int x=0; x<width(); x++)
|
---|
603 | {
|
---|
604 | float fx=(x-xm)/xm;
|
---|
605 |
|
---|
606 | i4_3d_vector xa=xi;
|
---|
607 | xa*=fx;
|
---|
608 |
|
---|
609 | i4_3d_vector r1=center;
|
---|
610 | r1+=xa;
|
---|
611 | r1+=ya;
|
---|
612 | r1-=eye;
|
---|
613 |
|
---|
614 | float z=10000;
|
---|
615 | path_info c;
|
---|
616 | trace_ray(eye, eye, r1, 1, z, c);
|
---|
617 |
|
---|
618 |
|
---|
619 | r1_vert v;
|
---|
620 | v.px=x;
|
---|
621 | v.py=y;
|
---|
622 | v.v.z=z;
|
---|
623 |
|
---|
624 | v.r=c.color.x;
|
---|
625 | v.g=c.color.y;
|
---|
626 | v.b=c.color.z;
|
---|
627 |
|
---|
628 |
|
---|
629 | v.a=1;
|
---|
630 | api->render_pixel(&v);
|
---|
631 |
|
---|
632 | }
|
---|
633 |
|
---|
634 | if (abort_render || reset_render)
|
---|
635 | break;
|
---|
636 | }
|
---|
637 |
|
---|
638 |
|
---|
639 | if (!reset_render && !abort_render)
|
---|
640 | {
|
---|
641 | for (int i=0; i<path_len; i++)
|
---|
642 | {
|
---|
643 | w32 colors[5]={0x7f0000, 0xff0000, 0x007f00, 0xff00, 0x7f7f00 };
|
---|
644 | for (i=0; i<path_len; i++)
|
---|
645 | {
|
---|
646 | i4_3d_vector dir=path[i].pos;
|
---|
647 | dir-=path[i].start;
|
---|
648 |
|
---|
649 | draw_vector(path[i].start, dir, colors[0]);
|
---|
650 | draw_vector(path[i].pos, path[i].normal, colors[1]);
|
---|
651 | draw_vector(path[i].pos, path[i].a, colors[2]);
|
---|
652 | draw_vector(path[i].pos, path[i].b, colors[3]);
|
---|
653 | }
|
---|
654 |
|
---|
655 |
|
---|
656 | }
|
---|
657 | }
|
---|
658 |
|
---|
659 | reset_lock.lock();
|
---|
660 | } while (reset_render);
|
---|
661 |
|
---|
662 |
|
---|
663 | rwin()->end_render();
|
---|
664 | rendering=0;
|
---|
665 | request_redraw();
|
---|
666 | reset_lock.unlock();
|
---|
667 | }
|
---|
668 |
|
---|
669 | void render()
|
---|
670 | {
|
---|
671 | reset_lock.lock();
|
---|
672 |
|
---|
673 | if (rendering)
|
---|
674 | reset_render=1;
|
---|
675 | else
|
---|
676 | {
|
---|
677 | rwin()->begin_render();
|
---|
678 | rendering=1;
|
---|
679 | i4_add_thread(render_thread_start, 200*1024, this);
|
---|
680 | }
|
---|
681 |
|
---|
682 | reset_lock.unlock();
|
---|
683 | }
|
---|
684 |
|
---|
685 | void draw_vector(i4_3d_vector pos, i4_3d_vector dir, w32 color, i4_draw_context_class *context=0)
|
---|
686 | {
|
---|
687 | i4_3d_vector end=pos;
|
---|
688 | end+=dir;
|
---|
689 | draw_3d_line(pos, end, color, context);
|
---|
690 |
|
---|
691 | i4_3d_vector xs, ys;
|
---|
692 | if (dir.x>dir.y && dir.x>dir.z)
|
---|
693 | {
|
---|
694 | xs.cross(dir, i4_3d_vector(0,1,0));
|
---|
695 | ys.cross(dir, i4_3d_vector(0,0,1));
|
---|
696 | }
|
---|
697 | else if (dir.y>dir.z)
|
---|
698 | {
|
---|
699 | xs.cross(dir, i4_3d_vector(1,0,0));
|
---|
700 | ys.cross(dir, i4_3d_vector(0,0,1));
|
---|
701 | }
|
---|
702 | else
|
---|
703 | {
|
---|
704 | xs.cross(dir, i4_3d_vector(1,0,0));
|
---|
705 | ys.cross(dir, i4_3d_vector(0,1,0));
|
---|
706 | }
|
---|
707 |
|
---|
708 | i4_3d_vector p5=dir;
|
---|
709 | p5*=0.8; p5+=pos;
|
---|
710 |
|
---|
711 | xs.normalize();
|
---|
712 | ys.normalize();
|
---|
713 |
|
---|
714 | xs*=0.1;
|
---|
715 | ys*=0.1;
|
---|
716 | i4_3d_vector p1=p5,p2=p5,p3=p5,p4=p5;
|
---|
717 | p1+=xs; p1+=ys;
|
---|
718 | p2-=xs; p2+=ys;
|
---|
719 | p3-=xs; p3-=ys;
|
---|
720 | p4+=xs; p4-=ys;
|
---|
721 |
|
---|
722 |
|
---|
723 | draw_3d_line(p1,p2, color, context);
|
---|
724 | draw_3d_line(p2,p3, color, context);
|
---|
725 | draw_3d_line(p3,p4, color, context);
|
---|
726 | draw_3d_line(p4,p1, color, context);
|
---|
727 |
|
---|
728 | draw_3d_line(p1,end, color, context);
|
---|
729 | draw_3d_line(p2,end, color, context);
|
---|
730 | draw_3d_line(p3,end, color, context);
|
---|
731 | draw_3d_line(p4,end, color, context);
|
---|
732 | }
|
---|
733 |
|
---|
734 | void draw_wire_3d_sphere(i4_3d_vector pos, float r, i4_draw_context_class *context)
|
---|
735 | {
|
---|
736 | draw_3d_line(i4_3d_vector(pos.x-r, pos.y, pos.z),
|
---|
737 | i4_3d_vector(pos.x+r, pos.y, pos.z), 0xffffff, context);
|
---|
738 | draw_3d_line(i4_3d_vector(pos.x, pos.y-r, pos.z),
|
---|
739 | i4_3d_vector(pos.x, pos.y+r, pos.z), 0xffffff, context);
|
---|
740 | draw_3d_line(i4_3d_vector(pos.x, pos.y, pos.z-r),
|
---|
741 | i4_3d_vector(pos.x, pos.y, pos.z+r), 0xffffff, context);
|
---|
742 |
|
---|
743 | }
|
---|
744 |
|
---|
745 | void draw_3d_line(i4_3d_vector p1, i4_3d_vector p2, w32 color, i4_draw_context_class *context)
|
---|
746 | {
|
---|
747 | if (!context)
|
---|
748 | {
|
---|
749 | r1_vert v[2];
|
---|
750 | v[0].a=1;
|
---|
751 | v[0].r=((color&0xff0000)>>16)/255.0;
|
---|
752 | v[0].g=((color&0xff00)>>8)/255.0;
|
---|
753 | v[0].b=((color&0xff)>>0)/255.0;
|
---|
754 |
|
---|
755 | v[1]=v[0];
|
---|
756 |
|
---|
757 | if (project_point(p1, v[0]) &&
|
---|
758 | project_point(p2, v[1]))
|
---|
759 | r1_clip_render_lines(1, v, width()/2, height()/2, api);
|
---|
760 | }
|
---|
761 | else
|
---|
762 | {
|
---|
763 | r1_vert tp1, tp2;
|
---|
764 | if (project_point(p1,tp1) && project_point(p2,tp2))
|
---|
765 | local_image->line((int)tp1.px, (int)tp1.py,
|
---|
766 | (int)tp2.px, (int)tp2.py, color, *context);
|
---|
767 | }
|
---|
768 |
|
---|
769 | }
|
---|
770 |
|
---|
771 |
|
---|
772 | void draw(i4_draw_context_class &context)
|
---|
773 | {
|
---|
774 | if (rendering)
|
---|
775 | {
|
---|
776 | local_image->clear(0,context);
|
---|
777 | int i;
|
---|
778 | for (i=0; i<T_C; i++)
|
---|
779 | draw_wire_3d_sphere(circles[i], 1, &context);
|
---|
780 |
|
---|
781 | w32 colors[5]={0x7f0000, 0xff0000, 0x007f00, 0xff00, 0x7f7f00 };
|
---|
782 |
|
---|
783 | for (i=0; i<path_len; i++)
|
---|
784 | {
|
---|
785 | i4_3d_vector dir=path[i].pos;
|
---|
786 | dir-=path[i].start;
|
---|
787 | draw_vector(path[i].start, dir, colors[0], &context);
|
---|
788 | draw_vector(path[i].pos, path[i].normal, colors[1], &context);
|
---|
789 | draw_vector(path[i].pos, path[i].a, colors[2], &context);
|
---|
790 | draw_vector(path[i].pos, path[i].b, colors[3], &context);
|
---|
791 | }
|
---|
792 |
|
---|
793 | draw_vector(i4_3d_vector(0,0,0), i4_3d_vector(1,0,0), 0xff0000, &context);
|
---|
794 | draw_vector(i4_3d_vector(0,0,0), i4_3d_vector(0,1,0), 0x00ff00, &context);
|
---|
795 | draw_vector(i4_3d_vector(0,0,0), i4_3d_vector(0,0,1), 0x0000ff, &context);
|
---|
796 |
|
---|
797 | draw_vector(i4_3d_vector(0,0,0), light, 0xffff00, &context);
|
---|
798 |
|
---|
799 |
|
---|
800 | // draw_3d_line(i4_3d_vector(-1, 0, 0), i4_3d_vector(1,0,0), 0xff0000, context);
|
---|
801 | // draw_3d_line(i4_3d_vector(0, -1, 0), i4_3d_vector(0,1,0), 0x00ff00, context);
|
---|
802 | // draw_3d_line(i4_3d_vector(0, 0, -1), i4_3d_vector(0,0,1), 0x0000ff, context);
|
---|
803 |
|
---|
804 |
|
---|
805 |
|
---|
806 | }
|
---|
807 | i4_window_class::draw(context);
|
---|
808 |
|
---|
809 |
|
---|
810 |
|
---|
811 | }
|
---|
812 |
|
---|
813 |
|
---|
814 | char *name() { return "trace_view"; }
|
---|
815 | trace_view(int w, int h, r1_render_window_class *rwin_parent)
|
---|
816 | : i4_window_class(w,h), rwin_parent(rwin_parent)
|
---|
817 | {
|
---|
818 | path_len=0;
|
---|
819 | mouse_look_grab=i4_F;
|
---|
820 | theta=0;
|
---|
821 | rendering=0;
|
---|
822 | abort_render=0;
|
---|
823 |
|
---|
824 | i4_pixel_format fmt;
|
---|
825 | fmt.default_format();
|
---|
826 | fmt.alpha_mask=0;
|
---|
827 | fmt.calc_shift();
|
---|
828 |
|
---|
829 | v.calc_transform(t);
|
---|
830 | light=i4_3d_vector(0,4,1);
|
---|
831 | light.normalize();
|
---|
832 |
|
---|
833 | render();
|
---|
834 |
|
---|
835 | }
|
---|
836 |
|
---|
837 |
|
---|
838 | void get_mouse_ray(int mx, int my, i4_3d_vector &ray)
|
---|
839 | {
|
---|
840 | float w2=width()/2.0, h2=height()/2.0;
|
---|
841 | i4_3d_vector eye_space_ray((mx-w2)/w2, (my-h2)/h2, 1);
|
---|
842 | eye_space_ray.normalize();
|
---|
843 |
|
---|
844 | i4_3d_vector eye;
|
---|
845 | t.inverse_transform(i4_3d_vector(0,0,0), eye);
|
---|
846 | t.inverse_transform(eye_space_ray, ray);
|
---|
847 |
|
---|
848 | ray-=eye;
|
---|
849 | }
|
---|
850 |
|
---|
851 | i4_bool project_point(i4_3d_vector v, r1_vert &q)
|
---|
852 | {
|
---|
853 | t.transform(v, q.v);
|
---|
854 | if (q.v.z>0)
|
---|
855 | {
|
---|
856 | float ooz=1.0/q.v.z;
|
---|
857 | q.px=q.v.x * ooz * width()/2.0 + width()/2.0;
|
---|
858 | q.py=q.v.y * ooz * height()/2.0 + height()/2.0;
|
---|
859 | return i4_T;
|
---|
860 | }
|
---|
861 | return i4_F;
|
---|
862 |
|
---|
863 | }
|
---|
864 |
|
---|
865 |
|
---|
866 | void save()
|
---|
867 | {
|
---|
868 | i4_draw_context_class context(0,0, width()-1, height()-1);
|
---|
869 |
|
---|
870 | i4_image_class *im=i4_create_image(width(), height(), local_image->pal);
|
---|
871 | local_image->put_part(im, 0,0, x(), y(), x()+width()-1, y()+height()-1, context);
|
---|
872 |
|
---|
873 |
|
---|
874 | i4_file_class *fp=i4_open("im.jpg", I4_WRITE);
|
---|
875 | i4_write_jpeg(im, fp, 100);
|
---|
876 | delete fp;
|
---|
877 | delete im;
|
---|
878 | }
|
---|
879 |
|
---|
880 | void receive_event(i4_event *ev)
|
---|
881 | {
|
---|
882 |
|
---|
883 | switch (ev->type())
|
---|
884 | {
|
---|
885 | case i4_event::USER_MESSAGE :
|
---|
886 | {
|
---|
887 | CAST_PTR(uev, i4_user_message_event_class, ev);
|
---|
888 | switch (uev->sub_type)
|
---|
889 | {
|
---|
890 | case SAVE:
|
---|
891 | save();
|
---|
892 | break;
|
---|
893 | }
|
---|
894 |
|
---|
895 | } break;
|
---|
896 |
|
---|
897 | case i4_event::MOUSE_MOVE :
|
---|
898 | {
|
---|
899 | CAST_PTR(mev, i4_mouse_move_event_class, ev);
|
---|
900 | if (mouse_look_grab)
|
---|
901 | {
|
---|
902 | rotate_cam((mev->ly-mev->y)/200.0,
|
---|
903 | (mev->x-mev->lx)/200.0,
|
---|
904 | 0);
|
---|
905 | }
|
---|
906 | } break;
|
---|
907 |
|
---|
908 | case i4_event::MOUSE_BUTTON_DOWN :
|
---|
909 | {
|
---|
910 | CAST_PTR(bev, i4_mouse_button_event_class, ev);
|
---|
911 | if (bev->right())
|
---|
912 | {
|
---|
913 | mouse_look_grab=i4_T;
|
---|
914 |
|
---|
915 | i4_window_request_mouse_grab_class grab(this);
|
---|
916 | i4_kernel.send_event(parent, &grab);
|
---|
917 | // i4_current_app->get_display()->set_mouse_raw_mode(i4_T);
|
---|
918 | }
|
---|
919 | else if (bev->left())
|
---|
920 | {
|
---|
921 | i4_3d_vector ray_dir;
|
---|
922 | get_mouse_ray(bev->x, bev->y, ray_dir);
|
---|
923 |
|
---|
924 | path_len=0;
|
---|
925 | float z;
|
---|
926 |
|
---|
927 | path_info c;
|
---|
928 | i4_3d_vector eye;
|
---|
929 | t.inverse_transform(i4_3d_vector(0,0,0), eye);
|
---|
930 | trace_ray(eye, eye, ray_dir, 1, z, c, i4_T);
|
---|
931 | calc_transform();
|
---|
932 | }
|
---|
933 |
|
---|
934 |
|
---|
935 | } break;
|
---|
936 |
|
---|
937 | case i4_event::MOUSE_BUTTON_UP :
|
---|
938 | {
|
---|
939 | CAST_PTR(bev, i4_mouse_button_event_class, ev);
|
---|
940 | if (bev->right() && mouse_look_grab)
|
---|
941 | {
|
---|
942 | mouse_look_grab=i4_F;
|
---|
943 | // i4_current_app->get_display()->set_mouse_raw_mode(i4_F);
|
---|
944 | i4_window_request_mouse_ungrab_class ungrab(this);
|
---|
945 | i4_kernel.send_event(parent, &ungrab);
|
---|
946 | }
|
---|
947 |
|
---|
948 | } break;
|
---|
949 |
|
---|
950 |
|
---|
951 |
|
---|
952 | case i4_event::KEY_PRESS :
|
---|
953 | {
|
---|
954 | CAST_PTR(kev, i4_key_press_event_class, ev);
|
---|
955 | switch (kev->key)
|
---|
956 | {
|
---|
957 | case I4_UP : move_cam(0,0,0.5); break;
|
---|
958 | case I4_DOWN : move_cam(0,0,-0.5); break;
|
---|
959 | case I4_LEFT : move_cam(-0.5,0,0); break;
|
---|
960 | case I4_RIGHT : move_cam(0.5,0,0); break;
|
---|
961 | case 'z' : rotate_cam(-0.1, 0,0); break;
|
---|
962 | case 'x' : rotate_cam(0.1, 0,0); break;
|
---|
963 | case 'c' : rotate_cam(0, -0.1,0); break;
|
---|
964 | case 'v' : rotate_cam(0, 0.1,0); break;
|
---|
965 | case 'w' :
|
---|
966 | case ' ' :
|
---|
967 | {
|
---|
968 | light.x+=0.1; light.normalize(); calc_transform();
|
---|
969 | } break;
|
---|
970 | }
|
---|
971 |
|
---|
972 | }
|
---|
973 |
|
---|
974 | default:
|
---|
975 | i4_window_class::receive_event(ev);
|
---|
976 | }
|
---|
977 | }
|
---|
978 | };
|
---|
979 |
|
---|
980 |
|
---|
981 | void render_thread_start(void *context)
|
---|
982 | {
|
---|
983 | ((trace_view *)context)->thread_render();
|
---|
984 | }
|
---|
985 |
|
---|
986 |
|
---|
987 |
|
---|
988 |
|
---|
989 | i4_window_class *create_view(int w, int h)
|
---|
990 | {
|
---|
991 | r1_render_window_class *win=api->create_render_window(w,h);
|
---|
992 | trace=new trace_view(w,h, win);
|
---|
993 | win->add_child(0,0, trace);
|
---|
994 | return win;
|
---|
995 | }
|
---|
996 |
|
---|
997 |
|
---|
998 | class ray_tracer_app : public i4_application_class
|
---|
999 | {
|
---|
1000 | public:
|
---|
1001 | i4_bool get_display_name(char *name, int max_len)
|
---|
1002 | {
|
---|
1003 | strcpy(name, "Windowed GDI");
|
---|
1004 | return i4_T;
|
---|
1005 | }
|
---|
1006 |
|
---|
1007 | void init()
|
---|
1008 | {
|
---|
1009 | i4_application_class::init();
|
---|
1010 |
|
---|
1011 | i4_pull_menu_class *menu=li_create_pull_menu("menu.scm");
|
---|
1012 | menu->show(wm, 0,0);
|
---|
1013 |
|
---|
1014 | api=r1_create_api(get_display(), "Software Z Buffer");
|
---|
1015 | if (!api)
|
---|
1016 | i4_error("no render api");
|
---|
1017 |
|
---|
1018 | i4_graphical_style_class *style=get_style();
|
---|
1019 | i4_window_class *w=create_view(400, 400);
|
---|
1020 |
|
---|
1021 | i4_parent_window_class *p;
|
---|
1022 | p=style->create_mp_window(0, menu->height(), w->width(), w->height(), "Render");
|
---|
1023 | p->add_child(0,0, w);
|
---|
1024 |
|
---|
1025 |
|
---|
1026 | i4_button_class *b=new i4_button_class(0, new i4_text_window_class("Save", style), style,
|
---|
1027 | new i4_event_reaction_class(trace, SAVE));
|
---|
1028 | wm->add_child(wm->width()-b->width(), wm->height()-b->height(), b);
|
---|
1029 | }
|
---|
1030 |
|
---|
1031 | void calc_model()
|
---|
1032 | {
|
---|
1033 | if (trace->path_len)
|
---|
1034 | {
|
---|
1035 | float z=10000;
|
---|
1036 | path_info c;
|
---|
1037 | i4_3d_vector dir=trace->path[0].pos;
|
---|
1038 | dir-=trace->path[0].start;
|
---|
1039 | i4_3d_vector eye;
|
---|
1040 | trace->t.inverse_transform(i4_3d_vector(0,0,0), eye);
|
---|
1041 | trace->trace_ray(eye, trace->path[0].start, dir, 1, z, c);
|
---|
1042 | }
|
---|
1043 |
|
---|
1044 | }
|
---|
1045 |
|
---|
1046 | void uninit()
|
---|
1047 | {
|
---|
1048 | trace->abort_render=1;
|
---|
1049 | i4_application_class::uninit();
|
---|
1050 | }
|
---|
1051 |
|
---|
1052 |
|
---|
1053 | char *name() { return "ray tracer"; }
|
---|
1054 | };
|
---|
1055 |
|
---|
1056 |
|
---|
1057 | void i4_main(w32 argc, i4_const_str *argv)
|
---|
1058 | {
|
---|
1059 | ray_tracer_app test;
|
---|
1060 | test.run();
|
---|
1061 | }
|
---|
1062 |
|
---|
1063 |
|
---|