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 "map.hh"
|
---|
10 | #include "map_man.hh"
|
---|
11 | #include "map_vert.hh"
|
---|
12 | #include "map_cell.hh"
|
---|
13 | #include "div_table.cc"
|
---|
14 | #include "camera.hh"
|
---|
15 | #include "r1_api.hh"
|
---|
16 | #include "tmanage.hh"
|
---|
17 | #include "r1_clip.hh"
|
---|
18 | #include "g1_render.hh"
|
---|
19 | #include "tile.hh"
|
---|
20 | #include "controller.hh"
|
---|
21 | #include "statistics.hh"
|
---|
22 | #include "lisp/li_class.hh"
|
---|
23 | #include "resources.hh"
|
---|
24 | #include "time/profile.hh"
|
---|
25 | #include "light.hh"
|
---|
26 |
|
---|
27 | static i4_profile_class pf_map_fast("map_fast"),
|
---|
28 | pf_calc_map_lod("calc_map_lod"),
|
---|
29 | pf_gather_objects("gather_objects"),
|
---|
30 | pf_draw_tri("draw_tri");
|
---|
31 |
|
---|
32 |
|
---|
33 | i4_image_class *render_map_section(int x1, int y1, int x2, int y2, int im_w, int im_h);
|
---|
34 |
|
---|
35 | inline float fmin(float a, float b) { return (a<b)?a:b; }
|
---|
36 | inline float fmax(float a, float b) { return (a>b)?a:b; }
|
---|
37 |
|
---|
38 | class texture_context
|
---|
39 | {
|
---|
40 | public:
|
---|
41 | i4_float x1,y1; // offset in the map
|
---|
42 | i4_float sx, sy; // scale factors to get [0,1] texture coords.
|
---|
43 | r1_texture_handle texture; // texture to use
|
---|
44 | };
|
---|
45 |
|
---|
46 | class lod_node
|
---|
47 | {
|
---|
48 | public:
|
---|
49 | w16 x1,y1,x2,y2; // bounding box for this LOD node
|
---|
50 | i4_float z1,z2;
|
---|
51 | i4_float metric; // metric for determining LOD "importance"
|
---|
52 | lod_node *child[2]; // orthogonal BSP children
|
---|
53 | w8 texture_context; // which texture context to use or 0 for 1x1
|
---|
54 |
|
---|
55 | w8 flags;
|
---|
56 | enum
|
---|
57 | {
|
---|
58 | CLIPPED = 1<<0, // this node is completely out of the view
|
---|
59 | IN_VIEW = 1<<1, // in the view
|
---|
60 | CLIP_FLAGS = CLIPPED | IN_VIEW,
|
---|
61 | V_SPLIT = 1<<2, // node split vertically
|
---|
62 | };
|
---|
63 |
|
---|
64 | lod_node(w16 x1,w16 y1,w16 x2,w16 y2, i4_float metric=0)
|
---|
65 | : x1(x1), y1(y1), x2(x2), y2(y2), metric(metric)
|
---|
66 | {
|
---|
67 | child[0] = 0;
|
---|
68 | child[1] = 0;
|
---|
69 | }
|
---|
70 | };
|
---|
71 |
|
---|
72 | class g1_lod_context_class
|
---|
73 | {
|
---|
74 | public:
|
---|
75 | // texture contexts for the large subdivided texture used to cover the whole map
|
---|
76 | texture_context map_texture[5];
|
---|
77 | int num_context, last_context;
|
---|
78 |
|
---|
79 | // LOD tree
|
---|
80 | lod_node *root;
|
---|
81 |
|
---|
82 | // breadth first ordering of the lod_nodes
|
---|
83 | lod_node *queue[150*100*2];
|
---|
84 | int num_queued, front;
|
---|
85 |
|
---|
86 | // lod_nodes submitted for drawing
|
---|
87 | lod_node *quad[150*100];
|
---|
88 | int num_quads;
|
---|
89 |
|
---|
90 | // current controller
|
---|
91 | g1_object_controller_class *cont;
|
---|
92 | i4_3d_vector pos;
|
---|
93 |
|
---|
94 | g1_lod_context_class() : root(0) {}
|
---|
95 |
|
---|
96 | void init_lod()
|
---|
97 | // make LOD tree
|
---|
98 | {
|
---|
99 | if (root)
|
---|
100 | delete_lod_tree(root);
|
---|
101 |
|
---|
102 | num_context=0;
|
---|
103 | make_lod_node(&root,0,0,0,g1_get_map()->width(),g1_get_map()->height());
|
---|
104 |
|
---|
105 | for (int i=1; i<=num_context; i++)
|
---|
106 | {
|
---|
107 | int x1,y1,x2,y2;
|
---|
108 |
|
---|
109 | x1 = i4_f_to_i(map_texture[i].x1);
|
---|
110 | y1 = i4_f_to_i(map_texture[i].y1);
|
---|
111 | x2 = x1 + i4_f_to_i(1.0/map_texture[i].sx + 0.5);
|
---|
112 | y2 = y1 + i4_f_to_i(1.0/map_texture[i].sy + 0.5);
|
---|
113 | i4_image_class *im = render_map_section(x1,y1,x2,y2, 256,256);
|
---|
114 | map_texture[i].texture = g1_render.r_api->get_tmanager()->register_image(im);
|
---|
115 | delete im;
|
---|
116 | }
|
---|
117 | }
|
---|
118 |
|
---|
119 | void uninit_lod()
|
---|
120 | {
|
---|
121 | delete_lod_tree(root);
|
---|
122 | }
|
---|
123 |
|
---|
124 | void use_controller(g1_object_controller_class *_cont) { cont = _cont; }
|
---|
125 |
|
---|
126 | int test_clip(lod_node *p)
|
---|
127 | // test bounding region of lod_node against the view frustrum
|
---|
128 | {
|
---|
129 | const i4_float MAX_FLY_HEIGHT=3.0;
|
---|
130 | int clip = cont->test_clip(i4_3d_vector(p->x1,p->y1,p->z1),
|
---|
131 | i4_3d_vector(p->x2,p->y2,p->z2+MAX_FLY_HEIGHT));
|
---|
132 |
|
---|
133 | w8 flags =
|
---|
134 | (clip<0)? lod_node::CLIPPED :
|
---|
135 | (clip>0)? lod_node::IN_VIEW :
|
---|
136 | 0;
|
---|
137 |
|
---|
138 | p->flags = (p->flags & ~lod_node::CLIP_FLAGS) | flags;
|
---|
139 |
|
---|
140 | return clip>=0;
|
---|
141 | }
|
---|
142 |
|
---|
143 | void make_lod_node(lod_node **pp, lod_node *parent, int x1, int y1, int x2, int y2, int level=0)
|
---|
144 | {
|
---|
145 | int dx = x2-x1, dy = y2-y1;
|
---|
146 | int mx = (x1+x2)/2, my = (y1+y2)/2;
|
---|
147 |
|
---|
148 | if (dx==0 || dy==0)
|
---|
149 | return;
|
---|
150 |
|
---|
151 | lod_node *p;
|
---|
152 | *pp = p = new lod_node(x1,y1,x2,y2);
|
---|
153 |
|
---|
154 | // hack to get texture contexts
|
---|
155 | if (level<2)
|
---|
156 | p->texture_context = 0;
|
---|
157 | else if (level==2)
|
---|
158 | {
|
---|
159 | p->texture_context = ++num_context;
|
---|
160 | map_texture[num_context].x1 = x1;
|
---|
161 | map_texture[num_context].y1 = y1;
|
---|
162 | map_texture[num_context].sx = 1.0*div_table[x2-x1];
|
---|
163 | map_texture[num_context].sy = 1.0*div_table[y2-y1];
|
---|
164 | }
|
---|
165 | else
|
---|
166 | p->texture_context = parent->texture_context;
|
---|
167 |
|
---|
168 | if (dx>1 || dy>1)
|
---|
169 | {
|
---|
170 | if (dx>=dy)
|
---|
171 | {
|
---|
172 | p->flags |= lod_node::V_SPLIT;
|
---|
173 | make_lod_node(&p->child[0], p, x1,y1,mx,y2, level+1);
|
---|
174 | make_lod_node(&p->child[1], p, mx,y1,x2,y2, level+1);
|
---|
175 | }
|
---|
176 | else
|
---|
177 | {
|
---|
178 | p->flags &= ~lod_node::V_SPLIT;
|
---|
179 | make_lod_node(&p->child[0], p, x1,y1,x2,my, level+1);
|
---|
180 | make_lod_node(&p->child[1], p, x1,my,x2,y2, level+1);
|
---|
181 | }
|
---|
182 | p->z1 = fmin(p->child[0]->z1, p->child[1]->z1);
|
---|
183 | p->z2 = fmax(p->child[0]->z2, p->child[1]->z2);
|
---|
184 |
|
---|
185 | // area metric
|
---|
186 | p->metric = p->child[0]->metric + p->child[1]->metric;
|
---|
187 | }
|
---|
188 | else
|
---|
189 | {
|
---|
190 | i4_float
|
---|
191 | z11 = g1_get_map()->vertex(x1,y1)->get_height(),
|
---|
192 | z21 = g1_get_map()->vertex(x2,y1)->get_height(),
|
---|
193 | z12 = g1_get_map()->vertex(x1,y2)->get_height(),
|
---|
194 | z22 = g1_get_map()->vertex(x2,y2)->get_height();
|
---|
195 |
|
---|
196 | p->z1 = p->z2 = z11;
|
---|
197 | p->z1 = fmin(p->z1, z21);
|
---|
198 | p->z2 = fmax(p->z2, z21);
|
---|
199 | p->z1 = fmin(p->z1, z12);
|
---|
200 | p->z2 = fmax(p->z2, z12);
|
---|
201 | p->z1 = fmin(p->z1, z22);
|
---|
202 | p->z2 = fmax(p->z2, z22);
|
---|
203 |
|
---|
204 | // area metric
|
---|
205 | i4_float dz1,dz2;
|
---|
206 |
|
---|
207 | dz1 = z22 - z21;
|
---|
208 | dz2 = z11 - z21;
|
---|
209 | p->metric = sqrt(dz1*dz1 + dz2*dz2 + 1);
|
---|
210 | dz1 = z22 - z12;
|
---|
211 | dz2 = z11 - z12;
|
---|
212 | p->metric += dz1*dz1 + dz2*dz2 + 1;
|
---|
213 | }
|
---|
214 | }
|
---|
215 |
|
---|
216 | void delete_lod_tree(lod_node *p)
|
---|
217 | {
|
---|
218 | if (!p)
|
---|
219 | return;
|
---|
220 | delete_lod_tree(p->child[0]);
|
---|
221 | delete_lod_tree(p->child[1]);
|
---|
222 | delete p;
|
---|
223 | }
|
---|
224 |
|
---|
225 | void calculate_lod(lod_node *p)
|
---|
226 | {
|
---|
227 | // cont->view.get_camera_pos(pos);
|
---|
228 | cont->get_pos(pos);
|
---|
229 |
|
---|
230 | num_quads=0;
|
---|
231 | front = num_queued = 0;
|
---|
232 | queue[num_queued++] = p;
|
---|
233 | root->flags = 0;
|
---|
234 |
|
---|
235 | while (front<num_queued)
|
---|
236 | {
|
---|
237 | p = queue[front++];
|
---|
238 | int x1=p->x1,y1=p->y1,x2=p->x2,y2=p->y2;
|
---|
239 | w8 sub_flags=p->flags & lod_node::IN_VIEW;
|
---|
240 |
|
---|
241 | // do some kind of clip test
|
---|
242 | if (!sub_flags)
|
---|
243 | if (test_clip(p))
|
---|
244 | sub_flags=p->flags & lod_node::IN_VIEW;
|
---|
245 | else
|
---|
246 | continue;
|
---|
247 |
|
---|
248 | // int dx = x2-x1, dy = y2-y1;
|
---|
249 | int mx = (x1+x2)/2, my = (y1+y2)/2;
|
---|
250 |
|
---|
251 | i4_float fx = pos.x - mx, fy = pos.y - my, fz = pos.z - g1_get_vertex(mx,my)->get_height();
|
---|
252 | i4_float d1 = fx*fx+fy*fy+fz*fz;
|
---|
253 | i4_float d2 = p->metric*20;
|
---|
254 |
|
---|
255 | if (p->child[0] && d1<d2)
|
---|
256 | {
|
---|
257 | p->child[0]->flags = (p->child[0]->flags & ~lod_node::CLIP_FLAGS) | sub_flags;
|
---|
258 | p->child[1]->flags = (p->child[1]->flags & ~lod_node::CLIP_FLAGS) | sub_flags;
|
---|
259 | queue[num_queued++] = p->child[0];
|
---|
260 | queue[num_queued++] = p->child[1];
|
---|
261 |
|
---|
262 | // count & mark t splits
|
---|
263 | lod_node *q = p->child[0];
|
---|
264 | if (p->flags & lod_node::V_SPLIT)
|
---|
265 | {
|
---|
266 | g1_get_vertex(q->x2,q->y1)->flags ^= g1_map_vertex_class::T_INTERSECTION;
|
---|
267 | g1_get_vertex(q->x2,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
|
---|
268 | }
|
---|
269 | else
|
---|
270 | {
|
---|
271 | g1_get_vertex(q->x1,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
|
---|
272 | g1_get_vertex(q->x2,q->y2)->flags ^= g1_map_vertex_class::T_INTERSECTION;
|
---|
273 | }
|
---|
274 | }
|
---|
275 | else
|
---|
276 | {
|
---|
277 | g1_map_vertex_class *v11, *v12, *v21, *v22;
|
---|
278 |
|
---|
279 | v11 = g1_get_vertex(x1,y1);
|
---|
280 | v21 = g1_get_vertex(x2,y1);
|
---|
281 | v12 = g1_get_vertex(x1,y2);
|
---|
282 | v22 = g1_get_vertex(x2,y2);
|
---|
283 |
|
---|
284 | v11->t_height = v11->get_height();
|
---|
285 | v21->t_height = v21->get_height();
|
---|
286 | v12->t_height = v12->get_height();
|
---|
287 | v22->t_height = v22->get_height();
|
---|
288 | quad[num_quads++] = p;
|
---|
289 | }
|
---|
290 | }
|
---|
291 |
|
---|
292 | // T intersection fixing
|
---|
293 |
|
---|
294 | // Map of directions
|
---|
295 | // dzdx2
|
---|
296 | // z22* ----> *
|
---|
297 | // ^ ^
|
---|
298 | // dzdy1 | | dzdy2
|
---|
299 | // | |
|
---|
300 | // z12* ----> *
|
---|
301 | // z11 dzdx1 z21
|
---|
302 | for (int test=0; test<2; test++)
|
---|
303 | for (front = 0; front<num_quads; front++)
|
---|
304 | {
|
---|
305 | int
|
---|
306 | x1=quad[front]->x1,y1=quad[front]->y1,
|
---|
307 | x2=quad[front]->x2,y2=quad[front]->y2;
|
---|
308 | int i,j;
|
---|
309 | i4_float z11,z12,z21,z22;
|
---|
310 | i4_float dzdx1,dzdx2,dzdy1,dzdy2;
|
---|
311 |
|
---|
312 | z11 = g1_get_vertex(x1,y1)->t_height;
|
---|
313 | z21 = g1_get_vertex(x2,y1)->t_height;
|
---|
314 | z12 = g1_get_vertex(x1,y2)->t_height;
|
---|
315 | z22 = g1_get_vertex(x2,y2)->t_height;
|
---|
316 |
|
---|
317 | dzdx1 = (z21 - z11)*div_table[x2 - x1];
|
---|
318 | dzdx2 = (z22 - z12)*div_table[x2 - x1];
|
---|
319 | dzdy1 = (z12 - z11)*div_table[y2 - y1];
|
---|
320 | dzdy2 = (z22 - z21)*div_table[y2 - y1];
|
---|
321 |
|
---|
322 | z22 = z12;
|
---|
323 | z12 = z11;
|
---|
324 |
|
---|
325 | i4_float adj1,adj2;
|
---|
326 |
|
---|
327 | #define DEPIXEL_ADJ 0.1
|
---|
328 |
|
---|
329 | adj1 = (pos.x<x1)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
|
---|
330 | adj2 = (pos.x>x2)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
|
---|
331 | for (j=y1+1; j<y2; j++)
|
---|
332 | {
|
---|
333 | z11 += dzdy1;
|
---|
334 | z21 += dzdy2;
|
---|
335 |
|
---|
336 | // if (g1_get_vertex(x1,j)->flags & g1_map_vertex_class::T_INTERSECTION)
|
---|
337 | g1_get_vertex(x1,j)->t_height = z11 + adj1;
|
---|
338 | // if (g1_get_vertex(x2,j)->flags & g1_map_vertex_class::T_INTERSECTION)
|
---|
339 | g1_get_vertex(x2,j)->t_height = z21 + adj2;
|
---|
340 | }
|
---|
341 |
|
---|
342 | adj1 = (pos.y<y1)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
|
---|
343 | adj2 = (pos.y>y2)?DEPIXEL_ADJ:-DEPIXEL_ADJ;
|
---|
344 | for (i=x1+1; i<x2; i++)
|
---|
345 | {
|
---|
346 | z12 += dzdx1;
|
---|
347 | z22 += dzdx2;
|
---|
348 | // if (g1_get_vertex(i,y1)->flags & g1_map_vertex_class::T_INTERSECTION)
|
---|
349 | g1_get_vertex(i,y1)->t_height = z12 + adj1;
|
---|
350 | // if (g1_get_vertex(i,y2)->flags & g1_map_vertex_class::T_INTERSECTION)
|
---|
351 | g1_get_vertex(i,y2)->t_height = z22 + adj2;
|
---|
352 | }
|
---|
353 | }
|
---|
354 | }
|
---|
355 |
|
---|
356 | } g1_lod;
|
---|
357 |
|
---|
358 | void g1_map_class::init_lod()
|
---|
359 | {
|
---|
360 | g1_lod.init_lod();
|
---|
361 | }
|
---|
362 |
|
---|
363 | void g1_map_class::calc_map_lod(g1_object_controller_class *cont)
|
---|
364 | {
|
---|
365 | pf_calc_map_lod.start();
|
---|
366 |
|
---|
367 | g1_lod.use_controller(cont);
|
---|
368 | g1_lod.calculate_lod(g1_lod.root);
|
---|
369 |
|
---|
370 | pf_calc_map_lod.stop();
|
---|
371 | }
|
---|
372 |
|
---|
373 | static r1_texture_ref g1_default_texture("tron_grid");
|
---|
374 | const w32 g1_max_objs_in_view = 256;
|
---|
375 | w32 g1_num_objs_in_view = 0;
|
---|
376 | w32 g1_objs_in_view[g1_max_objs_in_view];
|
---|
377 | r1_vert temp_buf_1[9];
|
---|
378 | r1_vert temp_buf_2[9];
|
---|
379 |
|
---|
380 | i4_array<i4_transform_class> g1_obj_transforms_in_view(0, g1_max_objs_in_view);
|
---|
381 | class transform_killer_class : public i4_init_class
|
---|
382 | {
|
---|
383 | //fix this trey! can't have global i4_array's without something to clean it up.
|
---|
384 | void uninit() { g1_obj_transforms_in_view.uninit(); }
|
---|
385 | } transform_killer;
|
---|
386 |
|
---|
387 |
|
---|
388 | i4_bool g1_draw_tri(r1_vert *points,
|
---|
389 | w16 a, w16 b, w16 c,
|
---|
390 | r1_texture_handle texture, w16 clip=1)
|
---|
391 | //{{{
|
---|
392 | {
|
---|
393 | pf_draw_tri.start();
|
---|
394 |
|
---|
395 | g1_stat_counter.increment(g1_statistics_counter_class::TERRAIN_POLYS);
|
---|
396 | g1_stat_counter.increment(g1_statistics_counter_class::TOTAL_POLYS);
|
---|
397 |
|
---|
398 | i4_bool ret = i4_F;
|
---|
399 | r1_render_api_class *api = g1_render.r_api;
|
---|
400 | i4_float size=0;
|
---|
401 | sw32 num_poly_verts = 3;
|
---|
402 | r1_vert *clipped_poly, *v;
|
---|
403 | w16 *clipped_refs;
|
---|
404 | static w16 clipping_refs[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
|
---|
405 | w16 refs[3];
|
---|
406 | i4_float near_w=0.0001;
|
---|
407 | int i,j;
|
---|
408 |
|
---|
409 | refs[0] = a;
|
---|
410 | refs[1] = b;
|
---|
411 | refs[2] = c;
|
---|
412 | clipped_poly = points;
|
---|
413 | clipped_refs = &refs[0];
|
---|
414 |
|
---|
415 | // hacked backface culling (should do this in worldspace before projection...)
|
---|
416 | i4_3d_vector vt1(clipped_poly[a].v),vt2(clipped_poly[c].v),normal;
|
---|
417 |
|
---|
418 | vt1 -= clipped_poly[b].v;
|
---|
419 | vt2 -= clipped_poly[b].v;
|
---|
420 | normal.cross(vt2,vt1);
|
---|
421 | if (normal.dot(clipped_poly[b].v)>0)
|
---|
422 | {
|
---|
423 | pf_draw_tri.stop();
|
---|
424 | return i4_F;
|
---|
425 | }
|
---|
426 |
|
---|
427 | if ((clipped_poly[a].outcode | clipped_poly[b].outcode | clipped_poly[c].outcode)==0)
|
---|
428 | {
|
---|
429 | for (j=0; j<num_poly_verts; j++)
|
---|
430 | {
|
---|
431 | v = &clipped_poly[clipped_refs[j]];
|
---|
432 | if (v->w > near_w)
|
---|
433 | near_w=v->w;
|
---|
434 | }
|
---|
435 | }
|
---|
436 | else
|
---|
437 | {
|
---|
438 | clipped_poly = api->clip_poly(&num_poly_verts,
|
---|
439 | clipped_poly,
|
---|
440 | clipped_refs,
|
---|
441 | temp_buf_1,
|
---|
442 | temp_buf_2,
|
---|
443 | R1_CLIP_NO_CALC_OUTCODE);
|
---|
444 |
|
---|
445 | if (!clipped_poly || num_poly_verts<3)
|
---|
446 | num_poly_verts=0;
|
---|
447 |
|
---|
448 | if (num_poly_verts)
|
---|
449 | {
|
---|
450 | clipped_refs = clipping_refs;
|
---|
451 |
|
---|
452 | for (j=0; j<num_poly_verts; j++)
|
---|
453 | {
|
---|
454 | v = &clipped_poly[j];
|
---|
455 |
|
---|
456 | float ooz = r1_ooz(v->v.z);
|
---|
457 |
|
---|
458 | v->px = v->v.x*ooz*g1_render.center_x + g1_render.center_x;
|
---|
459 | v->py = v->v.y*ooz*g1_render.center_y + g1_render.center_y;
|
---|
460 | v->w = ooz;
|
---|
461 | if (v->w > near_w)
|
---|
462 | near_w=v->w;
|
---|
463 | }
|
---|
464 | }
|
---|
465 | }
|
---|
466 |
|
---|
467 | if (num_poly_verts)
|
---|
468 | {
|
---|
469 | if (texture)
|
---|
470 | {
|
---|
471 | sw32 texture_size=i4_f_to_i(g1_render.center_x * near_w * 0.5 * 0.5);
|
---|
472 | api->use_texture(texture, texture_size, 0);
|
---|
473 | }
|
---|
474 |
|
---|
475 | if (g1_render.draw_mode==g1_render_class::WIREFRAME)
|
---|
476 | {
|
---|
477 | api->set_constant_color(0x7f7f7f);
|
---|
478 | api->disable_texture();
|
---|
479 | api->set_shading_mode(R1_SHADE_DISABLED);
|
---|
480 |
|
---|
481 | r1_vert v[4];
|
---|
482 | v[0]=clipped_poly[0];
|
---|
483 | v[1]=clipped_poly[1];
|
---|
484 | v[2]=clipped_poly[2];
|
---|
485 | v[3]=clipped_poly[0];
|
---|
486 |
|
---|
487 | r1_clip_render_lines(3, v, g1_render.center_x, g1_render.center_y, api);
|
---|
488 | api->set_shading_mode(R1_WHITE_SHADING);
|
---|
489 | }
|
---|
490 | else
|
---|
491 | api->render_poly(num_poly_verts, clipped_poly, clipped_refs);
|
---|
492 |
|
---|
493 | ret = i4_T;
|
---|
494 | }
|
---|
495 |
|
---|
496 | pf_draw_tri.stop();
|
---|
497 | return ret;
|
---|
498 | }
|
---|
499 |
|
---|
500 | static void gather_objects(int x1, int y1, int x2, int y2)
|
---|
501 | {
|
---|
502 | pf_gather_objects.start();
|
---|
503 |
|
---|
504 | for (int y=y1; y<y2; y++)
|
---|
505 | {
|
---|
506 | g1_map_cell_class *map_cell=g1_get_cell(x1,y);
|
---|
507 |
|
---|
508 | for (int x=x1; x<x2; x++, map_cell++)
|
---|
509 | {
|
---|
510 | // collect objects
|
---|
511 | for (g1_object_chain_class *o=map_cell->get_obj_list(); o; o=o->next)
|
---|
512 | {
|
---|
513 | g1_object_class *obj=o->object;
|
---|
514 |
|
---|
515 | if (!obj->get_flag(g1_object_class::SCRATCH_BIT))
|
---|
516 | {
|
---|
517 | if (g1_num_objs_in_view<g1_max_objs_in_view)
|
---|
518 | {
|
---|
519 |
|
---|
520 | g1_objs_in_view[g1_num_objs_in_view] = obj->global_id;
|
---|
521 | obj->world_transform = g1_obj_transforms_in_view.add();
|
---|
522 |
|
---|
523 | g1_num_objs_in_view++;
|
---|
524 |
|
---|
525 | //have the object update his transform
|
---|
526 | obj->calc_world_transform(g1_render.frame_ratio);
|
---|
527 | obj->set_flag(g1_object_class::SCRATCH_BIT, 1);
|
---|
528 | }
|
---|
529 | }
|
---|
530 | }
|
---|
531 | }
|
---|
532 | }
|
---|
533 |
|
---|
534 | pf_gather_objects.stop();
|
---|
535 | }
|
---|
536 |
|
---|
537 |
|
---|
538 | static i4_transform_class comp_t;
|
---|
539 | int object_compare(const void *a, const void *b)
|
---|
540 | {
|
---|
541 | g1_object_class
|
---|
542 | *oa = g1_global_id.get(*((w32*)a)),
|
---|
543 | *ob = g1_global_id.get(*((w32*)b));
|
---|
544 |
|
---|
545 |
|
---|
546 | // sort objects with alpha last
|
---|
547 | if (oa->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
|
---|
548 | {
|
---|
549 | if (!ob->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
|
---|
550 | return -1;
|
---|
551 | }
|
---|
552 | else if (ob->get_type()->get_flag(g1_object_definition_class::HAS_ALPHA))
|
---|
553 | return 1;
|
---|
554 |
|
---|
555 |
|
---|
556 | i4_float
|
---|
557 | za = comp_t.x.z*oa->x + comp_t.y.z*oa->y + comp_t.z.z*oa->h + comp_t.t.z,
|
---|
558 | zb = comp_t.x.z*ob->x + comp_t.y.z*ob->y + comp_t.z.z*ob->h + comp_t.t.z;
|
---|
559 |
|
---|
560 | if (za>zb)
|
---|
561 | return 1;
|
---|
562 | else
|
---|
563 | return -1;
|
---|
564 | }
|
---|
565 |
|
---|
566 | void g1_map_class::fast_draw_cells(g1_draw_context_class *context)
|
---|
567 | {
|
---|
568 | pf_map_fast.start();
|
---|
569 |
|
---|
570 | r1_render_api_class *api = g1_render.r_api;
|
---|
571 | i4_transform_class t(*context->transform);
|
---|
572 | i4_3d_vector pos;
|
---|
573 |
|
---|
574 |
|
---|
575 | // g1_lod.cont->view.get_camera_pos(pos);
|
---|
576 | pos = g1_lod.pos;
|
---|
577 |
|
---|
578 | g1_num_objs_in_view = 0;
|
---|
579 | g1_obj_transforms_in_view.clear();
|
---|
580 |
|
---|
581 | if (g1_render.draw_mode==g1_render_class::SOLID)
|
---|
582 | api->use_texture(g1_default_texture.get(), 1, 0);
|
---|
583 |
|
---|
584 | int i=0,j;
|
---|
585 | g1_map_vertex_class *vt[4];
|
---|
586 | g1_map_vertex_class *v=verts;
|
---|
587 |
|
---|
588 | g1_lod.last_context=0;
|
---|
589 | for (j=0; j<g1_lod.num_quads; j++)
|
---|
590 | {
|
---|
591 | lod_node *p = g1_lod.quad[j];
|
---|
592 | int
|
---|
593 | x1 = p->x1, y1 = p->y1,
|
---|
594 | x2 = p->x2, y2 = p->y2,
|
---|
595 | clip = !(p->flags & lod_node::IN_VIEW);
|
---|
596 |
|
---|
597 | sw32 mw_p1=width()+1;
|
---|
598 |
|
---|
599 | vt[0]=v + x1 + y1 * mw_p1;
|
---|
600 | vt[1]=v + x2 + y1 * mw_p1;
|
---|
601 | vt[2]=v + x2 + y2 * mw_p1;
|
---|
602 | vt[3]=v + x1 + y2 * mw_p1;
|
---|
603 |
|
---|
604 | vt[0]->transform(t, x1, y1, g1_render.scale_x,g1_render.scale_y);
|
---|
605 | vt[1]->transform(t, x2, y1, g1_render.scale_x,g1_render.scale_y);
|
---|
606 | vt[2]->transform(t, x2, y2, g1_render.scale_x,g1_render.scale_y);
|
---|
607 | vt[3]->transform(t, x1, y2, g1_render.scale_x,g1_render.scale_y);
|
---|
608 |
|
---|
609 | if (vt[0]->calc_clip_code()==0)
|
---|
610 | vt[0]->project(g1_render.center_x, g1_render.center_y);
|
---|
611 | if (vt[1]->calc_clip_code()==0)
|
---|
612 | vt[1]->project(g1_render.center_x, g1_render.center_y);
|
---|
613 | if (vt[2]->calc_clip_code()==0)
|
---|
614 | vt[2]->project(g1_render.center_x, g1_render.center_y);
|
---|
615 | if (vt[3]->calc_clip_code()==0)
|
---|
616 | vt[3]->project(g1_render.center_x, g1_render.center_y);
|
---|
617 |
|
---|
618 | // collect objects
|
---|
619 | i4_3d_vector mid(i4_float(x2+x1)/2.0,i4_float(y2+y1)/2.0,i4_float(p->z2+p->z1)/2.0);
|
---|
620 | mid -= pos;
|
---|
621 |
|
---|
622 |
|
---|
623 | if (mid.dot(mid) < g1_resources.lod_disappear_dist)
|
---|
624 | gather_objects(x1,y1,x2,y2);
|
---|
625 | else
|
---|
626 | i++;
|
---|
627 |
|
---|
628 | if (x1+1==x2 && y1+1==y2)
|
---|
629 | {
|
---|
630 | // single cell
|
---|
631 | g1_map_cell_class *map_cell=cells + x1 + y1*width();
|
---|
632 |
|
---|
633 | g1_lod.last_context=0;
|
---|
634 | r1_texture_handle han = g1_tile_man.get_texture(map_cell->type);
|
---|
635 | if (han && han!=g1_tile_man.get_pink())
|
---|
636 | {
|
---|
637 | static float u[4]={0,1,1,0},v[4]={1,1,0,0};
|
---|
638 | int uv_on=map_cell->get_rotation();
|
---|
639 | int uv_dir=map_cell->mirrored() ? 3 : 1;
|
---|
640 | r1_vert poly[4];
|
---|
641 |
|
---|
642 | for (int i=0; i<4; i++)
|
---|
643 | {
|
---|
644 | vt[i]->set_r1_vert(&poly[i]);
|
---|
645 | poly[i].s=u[uv_on];
|
---|
646 | poly[i].t=v[uv_on];
|
---|
647 | poly[i].a=1.0;
|
---|
648 | uv_on=(uv_on+uv_dir)&3;
|
---|
649 | }
|
---|
650 | vt[0]->get_rgb(poly[0].r, poly[0].g, poly[0].b, x1, y1);
|
---|
651 | vt[1]->get_rgb(poly[1].r, poly[1].g, poly[1].b, x2, y1);
|
---|
652 | vt[2]->get_rgb(poly[2].r, poly[2].g, poly[2].b, x2, y2);
|
---|
653 | vt[3]->get_rgb(poly[3].r, poly[3].g, poly[3].b, x1, y2);
|
---|
654 |
|
---|
655 | if (post_cell_draw)
|
---|
656 | post_cell_draw(x1,y1, post_cell_draw_context);
|
---|
657 |
|
---|
658 | if (g1_draw_tri(poly, 0,1,2, han))
|
---|
659 | han = 0;
|
---|
660 | g1_draw_tri(poly, 0,2,3, han);
|
---|
661 | }
|
---|
662 | }
|
---|
663 | else
|
---|
664 | {
|
---|
665 | // larger LOD cell
|
---|
666 |
|
---|
667 | texture_context *tc = &g1_lod.map_texture[p->texture_context];
|
---|
668 | r1_texture_handle han;
|
---|
669 |
|
---|
670 | if (g1_lod.last_context==p->texture_context)
|
---|
671 | han = 0;
|
---|
672 | else
|
---|
673 | han = tc->texture;
|
---|
674 |
|
---|
675 | r1_vert poly[4];
|
---|
676 |
|
---|
677 | for (int i=0; i<4; i++)
|
---|
678 | {
|
---|
679 | vt[i]->set_r1_vert(&poly[i]);
|
---|
680 | poly[i].a=1.0;
|
---|
681 | }
|
---|
682 | vt[0]->get_rgb(poly[0].r, poly[0].g, poly[0].b, x1, y1);
|
---|
683 | vt[1]->get_rgb(poly[1].r, poly[1].g, poly[1].b, x2, y1);
|
---|
684 | vt[2]->get_rgb(poly[2].r, poly[2].g, poly[2].b, x2, y2);
|
---|
685 | vt[3]->get_rgb(poly[3].r, poly[3].g, poly[3].b, x1, y2);
|
---|
686 |
|
---|
687 | poly[0].s=(x1 - tc->x1)*tc->sx;
|
---|
688 | poly[0].t=(y1 - tc->y1)*tc->sy;
|
---|
689 | poly[1].s=(x2 - tc->x1)*tc->sx;
|
---|
690 | poly[1].t=(y1 - tc->y1)*tc->sy;
|
---|
691 | poly[2].s=(x2 - tc->x1)*tc->sx;
|
---|
692 | poly[2].t=(y2 - tc->y1)*tc->sy;
|
---|
693 | poly[3].s=(x1 - tc->x1)*tc->sx;
|
---|
694 | poly[3].t=(y2 - tc->y1)*tc->sy;
|
---|
695 |
|
---|
696 | if (g1_draw_tri(poly, 0,1,2, han))
|
---|
697 | han = 0;
|
---|
698 | if (g1_draw_tri(poly, 0,2,3, han))
|
---|
699 | han = 0;
|
---|
700 | if (han==0)
|
---|
701 | g1_lod.last_context = p->texture_context;
|
---|
702 | }
|
---|
703 | }
|
---|
704 |
|
---|
705 | for (i=0; i<g1_num_objs_in_view; i++)
|
---|
706 | {
|
---|
707 | g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
|
---|
708 | if (o)
|
---|
709 | o->set_flag(g1_object_class::SCRATCH_BIT, 0);
|
---|
710 | }
|
---|
711 |
|
---|
712 |
|
---|
713 | li_class *old_this=li_this;
|
---|
714 | //draw the objects BACK TO FRONT
|
---|
715 | comp_t = *context->transform;
|
---|
716 | qsort(g1_objs_in_view, g1_num_objs_in_view, sizeof(g1_objs_in_view[0]), object_compare);
|
---|
717 |
|
---|
718 | for (i=g1_num_objs_in_view-1;i>=0;i--)
|
---|
719 | {
|
---|
720 | g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
|
---|
721 | if (o)
|
---|
722 | {
|
---|
723 | li_this=o->vars;
|
---|
724 |
|
---|
725 | o->set_flag(g1_object_class::SCRATCH_BIT, 0);
|
---|
726 | if (o->world_transform!=0)
|
---|
727 | o->draw(context);
|
---|
728 | else
|
---|
729 | i4_warning("null transform");
|
---|
730 | }
|
---|
731 | }
|
---|
732 |
|
---|
733 | if (context->draw_editor_stuff)
|
---|
734 | {
|
---|
735 | for (i=g1_num_objs_in_view-1;i>=0;i--)
|
---|
736 | {
|
---|
737 | g1_object_class *o=g1_global_id.checked_get(g1_objs_in_view[i]);
|
---|
738 | if (o)
|
---|
739 | {
|
---|
740 | li_this=o->vars;
|
---|
741 | o->editor_draw(context);
|
---|
742 | }
|
---|
743 | }
|
---|
744 | }
|
---|
745 |
|
---|
746 | li_this=old_this;
|
---|
747 |
|
---|
748 | for (j=0; j<g1_lod.num_quads; j++)
|
---|
749 | {
|
---|
750 | lod_node *p = g1_lod.quad[j];
|
---|
751 | int
|
---|
752 | x1 = p->x1, y1 = p->y1,
|
---|
753 | x2 = p->x2, y2 = p->y2;
|
---|
754 |
|
---|
755 | sw32 mw_p1=width()+1;
|
---|
756 |
|
---|
757 | vt[0]=v + x1 + y1 * mw_p1;
|
---|
758 | vt[1]=v + x2 + y1 * mw_p1;
|
---|
759 | vt[2]=v + x2 + y2 * mw_p1;
|
---|
760 | vt[3]=v + x1 + y2 * mw_p1;
|
---|
761 |
|
---|
762 | vt[0]->clear_calculations();
|
---|
763 | vt[1]->clear_calculations();
|
---|
764 | vt[2]->clear_calculations();
|
---|
765 | vt[3]->clear_calculations();
|
---|
766 | }
|
---|
767 |
|
---|
768 | g1_stat_counter.increment(g1_statistics_counter_class::FRAMES);
|
---|
769 |
|
---|
770 | pf_map_fast.stop();
|
---|
771 | }
|
---|
772 |
|
---|
773 |
|
---|
774 | class num_in_view_reset_class : public g1_global_id_reset_notifier
|
---|
775 | {
|
---|
776 | public:
|
---|
777 | virtual void reset()
|
---|
778 | {
|
---|
779 | g1_num_objs_in_view=0;
|
---|
780 | }
|
---|
781 | } num_in_view_reset_inst;
|
---|