r1_softz.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. #include "r1_api.hh"
  9. #include "r1_win.hh"
  10. #include "image/image.hh"
  11. #include "palette/pal.hh"
  12. #include "threads/threads.hh"
  13. #include "tmanage.hh"
  14. #include "time/time.hh"
  15. // this lock prevents 2 threads from drawing at the same time
  16. static i4_critical_section_class softz_lock;
  17. static int defer_draws=0;
  18. static i4_pixel_format softz_pixel_fmt;
  19. class r1_softz_window;
  20. static r1_softz_window *cur_win=0;
  21. class r1_softz_window : public r1_render_window_class
  22. {
  23. public:
  24. i4_image_class *im;
  25. float *zbuffer;
  26. i4_draw_context_class ctext;
  27. volatile int rendering;
  28. r1_softz_window(int w, int h, r1_expand_type type);
  29. void clear_z(int x1, int y1, int x2, int y2, float z)
  30. {
  31. float *s=zbuffer + y1*width()+x1;
  32. int t=(x2-x1+1);
  33. for (int y=y1; y<=y2; y++)
  34. {
  35. for (int i=0; i<t; i++)
  36. s[i]=z;
  37. s+=width();
  38. }
  39. }
  40. void draw(i4_draw_context_class &context)
  41. {
  42. if (!rendering)
  43. im->put_image(local_image, 0,0, context);
  44. r1_render_window_class::draw(context);
  45. }
  46. virtual void begin_render()
  47. {
  48. softz_lock.lock();
  49. rendering=1;
  50. cur_win=this;
  51. if (cur_win->width()!=cur_win->im->width() ||
  52. cur_win->height()!=cur_win->im->height())
  53. i4_error("image wrong size");
  54. }
  55. virtual void end_render()
  56. {
  57. cur_win=0;
  58. rendering=0;
  59. softz_lock.unlock();
  60. }
  61. char *name() { return "softz_window"; }
  62. virtual void private_resize(w16 new_width, w16 new_height)
  63. {
  64. r1_render_window_class::private_resize(new_width, new_height);
  65. delete im;
  66. i4_free(zbuffer);
  67. zbuffer=(float *)i4_malloc(new_width* new_height*sizeof(float), "");
  68. im=i4_create_image(new_width, new_height, i4_pal_man.register_pal(&softz_pixel_fmt));
  69. }
  70. ~r1_softz_window()
  71. {
  72. while (rendering)
  73. {
  74. i4_warning("waiting on render to finish");
  75. i4_sleep(1);
  76. }
  77. delete im;
  78. i4_free(zbuffer);
  79. }
  80. };
  81. class r1_softz_tman : public r1_texture_manager_class
  82. {
  83. public:
  84. r1_softz_tman(const i4_pal *pal) : r1_texture_manager_class(pal) {}
  85. virtual void init() {}
  86. virtual void uninit() {}
  87. virtual void next_frame() {}
  88. virtual void reset() {}
  89. virtual void toggle_texture_loading() {}
  90. virtual r1_miplevel_t *get_texture(r1_texture_handle handle,
  91. w32 frame_counter,
  92. sw32 desired_width,
  93. sw32 &w, sw32 &h)
  94. {
  95. return 0;
  96. }
  97. virtual i4_bool valid_handle(r1_texture_handle handle)
  98. {
  99. return i4_F;
  100. }
  101. public:
  102. virtual i4_bool immediate_mip_load(r1_mip_load_info *load_info) { return i4_T; }
  103. virtual i4_bool async_mip_load(r1_mip_load_info *load_info) { return i4_T; }
  104. virtual void free_mip(r1_vram_handle_type vram_handle) {}
  105. };
  106. class r1_softz_api : public r1_render_api_class
  107. {
  108. public:
  109. char *name() { return "Software Z Buffer"; }
  110. virtual void use_texture(r1_texture_handle material_ref,
  111. sw32 desired_width,
  112. w32 frame)
  113. {}
  114. virtual void disable_texture() {}
  115. virtual void set_z_range(float near_z, float far_z) {}
  116. virtual void render_poly(int t_verts, r1_vert *verts)
  117. {
  118. render_lines(t_verts-1, verts);
  119. r1_vert l[2];
  120. l[0]=verts[0];
  121. l[1]=verts[t_verts-1];
  122. render_lines(1, l);
  123. }
  124. r1_softz_api()
  125. {
  126. softz_pixel_fmt.default_format();
  127. softz_pixel_fmt.alpha_mask=0;
  128. softz_pixel_fmt.calc_shift();
  129. }
  130. i4_bool init(i4_display_class *display)
  131. {
  132. tmanager=new r1_softz_tman(display->get_palette());
  133. return i4_T;
  134. }
  135. void uninit()
  136. {
  137. delete tmanager;
  138. }
  139. virtual void render_pixel(r1_vert *pixel)
  140. {
  141. int iw=cur_win->width();
  142. float *zbuffer=cur_win->zbuffer;
  143. int off=(int)pixel->px + ((int)pixel->py)*iw;
  144. if (write_mask & R1_COMPARE_W)
  145. if (zbuffer[off]<=pixel->v.z)
  146. return ;
  147. w32 *im_data=(w32 *)cur_win->im->data;
  148. if (write_mask & R1_WRITE_COLOR)
  149. {
  150. int r=(int)(pixel->r*255.0),
  151. g=(int)(pixel->g*255.0),
  152. b=(int)(pixel->b*255.0);
  153. w32 c=(r<<16)|(g<<8)|b;
  154. im_data[off]=c;
  155. }
  156. if (write_mask & R1_WRITE_W)
  157. zbuffer[off]=pixel->v.z;
  158. }
  159. virtual void render_lines(int t_lines, r1_vert *verts)
  160. {
  161. w32 *im_data=(w32 *)cur_win->im->data;
  162. int iw=cur_win->im->width();
  163. float *zbuffer=cur_win->zbuffer;
  164. for (int i=0; i<t_lines; i++)
  165. {
  166. float x=verts[i].px, y=verts[i].py, z=verts[i].v.z;
  167. float xd=(int)fabs(verts[i+1].px-x), yd=(int)fabs(verts[i+1].py-y);
  168. int steps = xd>yd ? xd+1 : yd+1;
  169. float r=verts[i].r, g=verts[i].g, b=verts[i].b;
  170. float rs=(verts[i+1].r-r)/(float)steps;
  171. float gs=(verts[i+1].g-g)/(float)steps;
  172. float bs=(verts[i+1].b-b)/(float)steps;
  173. float xs=(verts[i+1].px-x)/(float)steps;
  174. float ys=(verts[i+1].py-y)/(float)steps;
  175. float zs=(verts[i+1].v.z-z)/(float)steps;
  176. for (int j=0; j<steps; j++)
  177. {
  178. int off=(int)x + ((int)y)*iw;
  179. if ((write_mask & R1_COMPARE_W)==0 || zbuffer[off]>z)
  180. {
  181. if (write_mask & R1_WRITE_COLOR)
  182. {
  183. int ir=(int)(r*255.0), ig=(int)(g*255.0), ib=(int)(b*255.0);
  184. w32 c=(ir<<16)|(ig<<8)|ib;
  185. im_data[off]=c;
  186. r+=rs;
  187. g+=gs;
  188. b+=bs;
  189. }
  190. if (write_mask & R1_WRITE_W)
  191. zbuffer[off]=z;
  192. }
  193. x+=xs;
  194. y+=ys;
  195. z+=zs;
  196. }
  197. }
  198. }
  199. virtual i4_image_class *create_compatible_image(w16 w, w16 h)
  200. {
  201. return i4_create_image(w,h, i4_pal_man.register_pal(&softz_pixel_fmt));
  202. }
  203. virtual void clear_area(int x1, int y1, int x2, int y2, w32 color, float z)
  204. {
  205. if (write_mask & R1_WRITE_COLOR)
  206. cur_win->im->bar(x1,y1,x2,y2, color, cur_win->ctext);
  207. if (write_mask & R1_WRITE_W)
  208. cur_win->clear_z(x1,y1,x2,y2, z);
  209. }
  210. virtual r1_render_window_class *create_render_window(int visable_w, int visable_h,
  211. r1_expand_type type)
  212. {
  213. return new r1_softz_window(visable_w, visable_h, type);
  214. }
  215. virtual void copy_part(i4_image_class *im,
  216. int x, int y, // position on screen
  217. int x1, int y1, // area of image to copy
  218. int x2, int y2) {}
  219. };
  220. static r1_softz_api softz;
  221. r1_softz_window::r1_softz_window(int w, int h, r1_expand_type type)
  222. : r1_render_window_class(w,h, type, &softz),
  223. ctext(0,0,w-1,h-1)
  224. {
  225. zbuffer=(float *)i4_malloc(w*h*sizeof(float), "");
  226. im=i4_create_image(w,h, i4_pal_man.register_pal(&softz_pixel_fmt));
  227. rendering=0;
  228. }