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