source: golgotha/src/test/ray_tracer/ray_tracer.cc @ 80

Last change on this file since 80 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 24.7 KB
Line 
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
30r1_render_api_class *api=0;
31
32inline float frand() { return ((rand()%5000)-2500.0); }
33
34enum {
35  SAVE
36};
37
38
39struct 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
67void render_thread_start(void *context);
68
69#define S 2.2
70enum {T_C=1 };
71
72i4_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
82float 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
124float 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
159struct 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
169class trace_view;
170trace_view *trace=0;
171
172class trace_view : public i4_window_class
173{
174public:
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
981void render_thread_start(void *context)
982{
983  ((trace_view *)context)->thread_render();
984}
985
986
987
988
989i4_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
998class ray_tracer_app : public i4_application_class
999{
1000public:
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
1057void i4_main(w32 argc, i4_const_str *argv)
1058{
1059  ray_tracer_app test;
1060  test.run();
1061}
1062
1063
Note: See TracBrowser for help on using the repository browser.