1 /*
2 SCOTTISH_TEXTURES.C
3
4 Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
5 and the "Aleph One" developers.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 This license is contained in the file "COPYING",
18 which is included with this source code; it is available online at
19 http://www.gnu.org/licenses/gpl.html
20
21 Wednesday, April 20, 1994 9:35:36 AM
22
23 this is not your father�s texture mapping library.
24 (in fact it isn�t yours either, dillweed)
25
26 Wednesday, April 20, 1994 3:39:21 PM
27 vertical repeats would be difficult because it would require testing repeats in the
28 innermost loop of the pixel mapper (a compare and branch we can do without).
29 Saturday, April 23, 1994 10:42:41 AM
30 (on the plane to santa clara) finished the slower version of the trapezoid mapper (we
31 need to handle stretching with a degenerate switch statement like marathon used to) but
32 the whole sampling process is now mathematically correct except for the squared function
33 we use to calculate the x texture position and the shading table (but this is accurate to
34 within 1/64k and doesn't accumulate error so who cares).
35 Sunday, April 24, 1994 10:12:47 AM
36 (waiting for the CGDC to start at 9:00 PST) added all polygon stuff. it struck me this
37 morning that clipping against the view cone must be deterministic (that is, line segments
38 of polygons and line segments of walls must be clipped in the same manner) or our
39 edges won't meet up. ordered dither darkening will look really cool but will be slow in c.
40 Sunday, April 24, 1994 11:21:47 PM
41 still need transparent trapezoids, dither darkening, faster DDA for trapezoid mapping.
42 Wednesday, April 27, 1994 9:49:55 AM
43 i'm just looking for one divine hammer (to bang it all day). solid polygons are currently
44 unaffected by darkening. i'm not entirely certain we'll even use them.
45 Sunday, May 8, 1994 8:32:11 AM
46 LISP�s lexical contours kick C firmly and painfully in the ass. everything is fast now
47 except the landscape mapper which has just been routed and is in full retreat.
48 Friday, May 13, 1994 10:05:08 AM
49 low-level unification of trapezoids and rectangles, transparent runs in shapes are run-length
50 encoded now. maintaining run tables was slower than generating d, delta_d and delta_d_prime
51 and using them on the fly.
52 Wednesday, May 18, 1994 2:16:26 PM
53 scope matters (at WWDC).
54 Sunday, May 22, 1994 12:32:02 PM
55 drawing things in column order to cached (i.e., non-screen) memory is like crapping in the
56 data cache, right? maybe drawing rectangles in column-order wasn't such a great idea after all.
57 it also occurs to me that i know nothing about how to order instructions for the �040 pipelines.
58 Thursday, June 16, 1994 9:56:14 PM
59 modified _render_textured_polygon_line to handle elevation.
60 Thursday, July 7, 1994 1:23:09 PM
61 changed MAXIMUM_SCRATCH_TABLE_ENTRIES from 4k to 1200. Modified render code to work as well,
62 now the problem is floor/ceiling matching with trapezoids, which should fall out with the
63 rewrite...
64 Tuesday, July 26, 1994 3:42:16 PM
65 OBSOLETE�ed nearly the entire file (fixed_pixels are no more). rewriting texture_rectangle.
66 will do 16bit mapping, soon. a while ago i rewrote everything in 68k.
67 Friday, September 16, 1994 6:03:11 PM (Jason')
68 texture_rectangle() now respects top and bottom clips
69 Tuesday, September 20, 1994 9:58:30 PM (Jason')
70 if we�re so close to a rectangle that n>LARGEST_N then we don�t draw anything
71 Wednesday, October 26, 1994 3:18:59 PM (Jason)
72 for non-convex or otherwise weird lines (dx<=0, dy<=0) we don�t draw anything (somebody�ll
73 notice that for sure).
74 Friday, November 4, 1994 7:35:48 PM (Jason')
75 pretexture_horizontal_polygon_lines() now respects the (x,y) polygon origin and uses z as height.
76
77 Jan 30, 2000 (Loren Petrich):
78 Added some typecasts
79
80 Feb. 4, 2000 (Loren Petrich):
81 Changed halt() to assert(false) for better debugging
82
83 Mar 24, 2000 (Loren Petrich):
84 Using a special "landscape yaw" for the landscape texturing, so that the landscape center
85 will stay put.
86
87 May 23, 2000 (Loren Petrich):
88 Adding support for different size scales for landscapes
89
90 Jul 6, 2000 (Loren Petrich):
91 Added some slop to MAXIMUM_SCRATCH_TABLE_ENTRIES, because displays are now bigger;
92 its size got upped by 2
93
94 Aug 9, 2000 (Loren Petrich):
95 Rasterizer_SW object introduced (software subclass of rasterizer object)
96
97 May 16, 2002 (Woody Zenfell):
98 MSVC doesn't like "void f(); void g() { return f(); }"... fixed.
99 */
100
101 /*
102 rectangle shrinking has vertical error and appears to randomly shear the bitmap
103 pretexture_horizontal_polygon_lines() has integer error in large height cases
104
105 _static_transfer doesn�t work for ceilings and floors (because they call the wall mapper)
106 build_y_table and build_x_table could both be sped up in nearly-horizontal and nearly-vertical cases (respectively)
107 _pretexture_vertical_polygon_lines() takes up to half the time _texture_vertical_polygon_lines() does
108 not only that, but texture_horizontal_polygon() is actually faster than texture_vertical_polygon()
109
110 //calculate_shading_table() needs to be inlined in a macro
111 */
112
113 #include "cseries.h"
114 #include "low_level_textures.h"
115 #include "render.h"
116 #include "Rasterizer_SW.h"
117
118 #include <stdlib.h>
119 #include <limits.h>
120
121 #include "preferences.h"
122 #include "SW_Texture_Extras.h"
123
124
125 /* ---------- constants */
126
127 // boosted to cope with big displays
128 #define MAXIMUM_SCRATCH_TABLE_ENTRIES 8192
129 #define MAXIMUM_PRECALCULATION_TABLE_ENTRY_SIZE (MAX(sizeof(_vertical_polygon_data), sizeof(_horizontal_polygon_line_data)))
130
131 #define SHADE_TO_SHADING_TABLE_INDEX(shade) ((shade)>>(FIXED_FRACTIONAL_BITS-shading_table_fractional_bits))
132 #define DEPTH_TO_SHADE(d) (((_fixed)(d))<<(FIXED_FRACTIONAL_BITS-WORLD_FRACTIONAL_BITS-3))
133
134 #define LARGEST_N 24
135
136 /* ---------- macros */
137
138 #if defined(DEBUG) && defined(DEBUG_FAST_CODE)
139 #define VHALT_DEBUG(message) vhalt(message)
140 #else
141 #define VHALT_DEBUG(message) ((void)0)
142 #endif
143
144 // i0 + i1 == MAX(i0, i1) + MIN(i0, i1)/2
145 //#define calculate_shading_table(result, view, shading_tables, depth, ambient_shade)
calculate_shading_table(void * & result,view_data * view,void * shading_tables,short depth,_fixed ambient_shade)146 static void calculate_shading_table(void * &result,view_data *view, void *shading_tables, short depth,_fixed ambient_shade)
147 {
148 short table_index;
149 _fixed shade;
150
151 if ((ambient_shade)<0)
152 {
153 table_index= SHADE_TO_SHADING_TABLE_INDEX(-(ambient_shade));
154 }
155 else
156 {
157 shade= (view)->maximum_depth_intensity - DEPTH_TO_SHADE(depth);
158 shade= PIN(shade, 0, FIXED_ONE);
159 table_index= SHADE_TO_SHADING_TABLE_INDEX((ambient_shade>shade) ? (ambient_shade + (shade>>1)) : (shade + (ambient_shade>>1)));
160 }
161
162 switch (bit_depth)
163 {
164 case 8: result= ((byte*)(shading_tables)) + MAXIMUM_SHADING_TABLE_INDEXES*sizeof(pixel8)*
165 CEILING(table_index, number_of_shading_tables-1); break;
166 case 16: result= ((byte*)(shading_tables)) + MAXIMUM_SHADING_TABLE_INDEXES*sizeof(pixel16)*
167 CEILING(table_index, number_of_shading_tables-1); break;
168 case 32: result= ((byte*)(shading_tables)) + MAXIMUM_SHADING_TABLE_INDEXES*sizeof(pixel32)*
169 CEILING(table_index, number_of_shading_tables-1); break;
170 }
171 }
172
173 /* ---------- globals */
174
175 /* these tables are used by the polygon rasterizer (to store the x-coordinates of the left and
176 right lines of the current polygon), the trapezoid rasterizer (to store the y-coordinates
177 of the top and bottom of the current trapezoid) and the rectangle mapper (for it�s
178 vertical and if necessary horizontal distortion tables). these are not necessary as
179 globals, just as global storage. */
180 static short *scratch_table0 = NULL, *scratch_table1 = NULL;
181 static void *precalculation_table = NULL;
182
183 /* ---------- private prototypes */
184
185 static void _pretexture_horizontal_polygon_lines(struct polygon_definition *polygon,
186 struct bitmap_definition *screen, struct view_data *view, struct _horizontal_polygon_line_data *data,
187 short y0, short *x0_table, short *x1_table, short line_count);
188
189 static void _pretexture_vertical_polygon_lines(struct polygon_definition *polygon,
190 struct bitmap_definition *screen, struct view_data *view, struct _vertical_polygon_data *data,
191 short x0, short *y0_table, short *y1_table, short line_count);
192
193 static short *build_x_table(short *table, short x0, short y0, short x1, short y1);
194 static short *build_y_table(short *table, short x0, short y0, short x1, short y1);
195
196 static void _prelandscape_horizontal_polygon_lines(struct polygon_definition *polygon,
197 struct bitmap_definition *screen, struct view_data *view, struct _horizontal_polygon_line_data *data,
198 short y0, short *x0_table, short *x1_table, short line_count);
199
200 /* ---------- code */
201
202 /* set aside memory at launch for two line tables (remember, we precalculate all the y-values
203 for trapezoids and two lines worth of x-values for polygons before mapping them) */
allocate_texture_tables(void)204 void allocate_texture_tables(
205 void)
206 {
207 scratch_table0= new short[MAXIMUM_SCRATCH_TABLE_ENTRIES];
208 scratch_table1= new short[MAXIMUM_SCRATCH_TABLE_ENTRIES];
209 precalculation_table= (void*)new char[MAXIMUM_PRECALCULATION_TABLE_ENTRY_SIZE*MAXIMUM_SCRATCH_TABLE_ENTRIES];
210 fc_assert(scratch_table0&&scratch_table1&&precalculation_table);
211 }
212
texture_horizontal_polygon(polygon_definition & textured_polygon)213 void Rasterizer_SW_Class::texture_horizontal_polygon(polygon_definition& textured_polygon)
214 {
215 polygon_definition *polygon = &textured_polygon; // Reference to pointer
216 short vertex, highest_vertex, lowest_vertex;
217 point2d *vertices= polygon->vertices;
218
219 fc_assert(polygon->vertex_count>=MINIMUM_VERTICES_PER_SCREEN_POLYGON&&polygon->vertex_count<MAXIMUM_VERTICES_PER_SCREEN_POLYGON);
220
221 /* if we get static, tinted or landscaped transfer modes punt to the vertical polygon mapper */
222 if (polygon->transfer_mode == _static_transfer) {
223 texture_vertical_polygon(textured_polygon);
224 return;
225 }
226
227 /* locate the vertically highest (closest to zero) and lowest (farthest from zero) vertices */
228 highest_vertex= lowest_vertex= 0;
229 for (vertex= 0; vertex<polygon->vertex_count; ++vertex)
230 {
231 if (!(vertices[vertex].x>=0&&vertices[vertex].x<=screen->width&&vertices[vertex].y>=0&&vertices[vertex].y<=screen->height))
232 {
233 // dprintf("vertex #%d/#%d out of bounds:;dm %x %x;g;", vertex, polygon->vertex_count, polygon->vertices, polygon->vertex_count*sizeof(point2d));
234 return;
235 }
236 if (vertices[vertex].y<vertices[highest_vertex].y) highest_vertex= vertex;
237 else if (vertices[vertex].y>vertices[lowest_vertex].y) lowest_vertex= vertex;
238 }
239
240 /* if this polygon is not a horizontal line, draw it */
241 if (highest_vertex!=lowest_vertex)
242 {
243 short left_line_count, right_line_count, total_line_count;
244 short aggregate_left_line_count, aggregate_right_line_count, aggregate_total_line_count;
245 short left_vertex, right_vertex;
246 short *left_table= scratch_table0, *right_table= scratch_table1;
247
248 left_line_count= right_line_count= 0; /* zero counts so the left and right lines get initialized */
249 aggregate_left_line_count= aggregate_right_line_count= 0; /* we�ve precalculated nothing initially */
250 left_vertex= right_vertex= highest_vertex; /* both sides start at the highest vertex */
251 total_line_count= vertices[lowest_vertex].y-vertices[highest_vertex].y; /* calculate vertical line count */
252
253 fc_assert(total_line_count<MAXIMUM_SCRATCH_TABLE_ENTRIES); /* make sure we have enough scratch space */
254
255 /* precalculate high and low y-coordinates for every x-coordinate */
256 aggregate_total_line_count= total_line_count;
257 while (total_line_count>0)
258 {
259
260 /* if we�re out of scan lines on the left side, get a new vertex and build a table
261 of x-coordinates so we can walk toward the new vertex */
262 if (left_line_count<=0)
263 {
264 do /* counter-clockwise vertex search */
265 {
266 vertex= left_vertex ? (left_vertex-1) : (polygon->vertex_count-1);
267 left_line_count= vertices[vertex].y-vertices[left_vertex].y;
268 if (!build_x_table(left_table+aggregate_left_line_count, vertices[left_vertex].x, vertices[left_vertex].y, vertices[vertex].x, vertices[vertex].y)) return;
269 aggregate_left_line_count+= left_line_count;
270 left_vertex= vertex;
271 // dprintf("add %d left", left_line_count);
272 }
273 while (!left_line_count);
274 }
275
276 /* if we�re out of scan lines on the right side, get a new vertex and build a table
277 of x-coordinates so we can walk toward the new vertex */
278 if (right_line_count<=0)
279 {
280 do /* clockwise vertex search */
281 {
282 vertex= (right_vertex==polygon->vertex_count-1) ? 0 : (right_vertex+1);
283 right_line_count= vertices[vertex].y-vertices[right_vertex].y;
284 if (!build_x_table(right_table+aggregate_right_line_count, vertices[right_vertex].x, vertices[right_vertex].y, vertices[vertex].x, vertices[vertex].y)) return;
285 aggregate_right_line_count+= right_line_count;
286 right_vertex= vertex;
287 // dprintf("add %d right", right_line_count);
288 }
289 while (!right_line_count);
290 }
291 //AS: moving delta declaration up to where it's needed. Isn't C++ wonderful?
292 /* advance by the minimum of left_line_count and right_line_count */
293 short delta= MIN(left_line_count, right_line_count);
294 fc_assert(delta);
295 // dprintf("tc=%d lc=%d rc=%d delta=%d", total_line_count, left_line_count, right_line_count, delta);
296 total_line_count-= delta;
297 left_line_count-= delta;
298 right_line_count-= delta;
299
300 fc_assert(delta||!total_line_count); /* if our delta is zero, we�d better be out of lines */
301 }
302
303 /* make sure every coordinate is accounted for in our tables */
304 fc_assert(aggregate_right_line_count==aggregate_total_line_count);
305 fc_assert(aggregate_left_line_count==aggregate_total_line_count);
306
307 /* precalculate mode-specific data */
308 switch (polygon->transfer_mode)
309 {
310 case _textured_transfer:
311 _pretexture_horizontal_polygon_lines(polygon, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
312 vertices[highest_vertex].y, left_table, right_table,
313 aggregate_total_line_count);
314 break;
315
316 case _big_landscaped_transfer:
317 _prelandscape_horizontal_polygon_lines(polygon, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
318 vertices[highest_vertex].y, left_table, right_table,
319 aggregate_total_line_count);
320 break;
321
322 default:
323 VHALT_DEBUG(csprintf(temporary, "horizontal_polygons dont support mode #%d", polygon->transfer_mode));
324 }
325
326 /* render all lines */
327 switch (bit_depth)
328 {
329 case 8:
330 switch (polygon->transfer_mode)
331 {
332
333 case _textured_transfer:
334 texture_horizontal_polygon_lines<pixel8, _sw_alpha_off>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
335 vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
336 break;
337 case _big_landscaped_transfer:
338 landscape_horizontal_polygon_lines<pixel8>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
339 vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
340 break;
341
342 default:
343 fc_assert(false);
344 break;
345 }
346 break;
347
348 case 16:
349 switch (polygon->transfer_mode)
350 {
351 case _textured_transfer:
352 {
353 SW_Texture *sw_texture = 0;
354 if (graphics_preferences->software_alpha_blending)
355 {
356 sw_texture = SW_Texture_Extras::instance()->GetTexture(polygon->ShapeDesc);
357 }
358 if (sw_texture && !polygon->VoidPresent && sw_texture->opac_type())
359 {
360 if (graphics_preferences->software_alpha_blending == _sw_alpha_fast) {
361 texture_horizontal_polygon_lines<pixel16, _sw_alpha_fast>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table, vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
362 }
363 else if (graphics_preferences->software_alpha_blending == _sw_alpha_nice) {
364 texture_horizontal_polygon_lines<pixel16, _sw_alpha_nice>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *) precalculation_table, vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count, sw_texture->opac_table());
365 }
366 } else {
367 texture_horizontal_polygon_lines<pixel16, _sw_alpha_off>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
368 vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
369 }
370 }
371 break;
372
373 case _big_landscaped_transfer:
374 landscape_horizontal_polygon_lines<pixel16>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
375 vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
376 break;
377 default:
378 fc_assert(false);
379 break;
380 }
381 break;
382
383 case 32:
384 switch (polygon->transfer_mode)
385 {
386 case _textured_transfer:
387 {
388 SW_Texture *sw_texture = 0;
389 if (graphics_preferences->software_alpha_blending)
390 {
391 sw_texture = SW_Texture_Extras::instance()->GetTexture(polygon->ShapeDesc);
392 }
393 if (sw_texture && sw_texture->opac_type() && !polygon->VoidPresent)
394 {
395 if (graphics_preferences->software_alpha_blending == _sw_alpha_fast)
396 {
397 texture_horizontal_polygon_lines<pixel32, _sw_alpha_fast>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table, vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
398 }
399 else if (graphics_preferences->software_alpha_blending == _sw_alpha_nice)
400 {
401 texture_horizontal_polygon_lines<pixel32, _sw_alpha_nice>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *) precalculation_table, vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count, sw_texture->opac_table());
402 }
403 }
404 else
405 {
406 texture_horizontal_polygon_lines<pixel32, _sw_alpha_off>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
407 vertices[highest_vertex].y, left_table, right_table,
408 aggregate_total_line_count);
409 }
410 }
411 break;
412 case _big_landscaped_transfer:
413 landscape_horizontal_polygon_lines<pixel32>(polygon->texture, screen, view, (struct _horizontal_polygon_line_data *)precalculation_table,
414 vertices[highest_vertex].y, left_table, right_table, aggregate_total_line_count);
415 break;
416
417 default:
418 fc_assert(false);
419 break;
420 }
421 break;
422
423 default:
424 fc_assert(false);
425 break;
426 }
427 }
428 }
429
texture_vertical_polygon(polygon_definition & textured_polygon)430 void Rasterizer_SW_Class::texture_vertical_polygon(polygon_definition& textured_polygon)
431 {
432 polygon_definition *polygon = &textured_polygon; // Reference to pointer
433 short vertex, highest_vertex, lowest_vertex;
434 point2d *vertices= polygon->vertices;
435
436 fc_assert(polygon->vertex_count>=MINIMUM_VERTICES_PER_SCREEN_POLYGON&&polygon->vertex_count<MAXIMUM_VERTICES_PER_SCREEN_POLYGON);
437
438 if (polygon->transfer_mode == _big_landscaped_transfer) {
439 texture_horizontal_polygon(textured_polygon);
440 return;
441 }
442
443 /* locate the horizontally highest (closest to zero) and lowest (farthest from zero) vertices */
444 highest_vertex= lowest_vertex= 0;
445 for (vertex=1;vertex<polygon->vertex_count;++vertex)
446 {
447 if (vertices[vertex].x<vertices[highest_vertex].x) highest_vertex= vertex;
448 if (vertices[vertex].x>vertices[lowest_vertex].x) lowest_vertex= vertex;
449 }
450
451 for (vertex=0;vertex<polygon->vertex_count;++vertex)
452 {
453 if (!(vertices[vertex].x>=0&&vertices[vertex].x<=screen->width&&vertices[vertex].y>=0&&vertices[vertex].y<=screen->height))
454 {
455 // dprintf("vertex #%d/#%d out of bounds:;dm %x %x;g;", vertex, polygon->vertex_count, polygon->vertices, polygon->vertex_count*sizeof(point2d));
456 return;
457 }
458 }
459
460 /* if this polygon is not a vertical line, draw it */
461 if (highest_vertex!=lowest_vertex)
462 {
463 short left_line_count, right_line_count, total_line_count;
464 short aggregate_left_line_count, aggregate_right_line_count, aggregate_total_line_count;
465 short left_vertex, right_vertex;
466 short *left_table= scratch_table0, *right_table= scratch_table1;
467
468 left_line_count= right_line_count= 0; /* zero counts so the left and right lines get initialized */
469 aggregate_left_line_count= aggregate_right_line_count= 0; /* we�ve precalculated nothing initially */
470 left_vertex= right_vertex= highest_vertex; /* both sides start at the highest vertex */
471 total_line_count= vertices[lowest_vertex].x-vertices[highest_vertex].x; /* calculate vertical line count */
472
473 fc_assert(total_line_count<MAXIMUM_SCRATCH_TABLE_ENTRIES); /* make sure we have enough scratch space */
474
475 /* precalculate high and low y-coordinates for every x-coordinate */
476 aggregate_total_line_count= total_line_count;
477 while (total_line_count>0)
478 {
479 /* if we�re out of scan lines on the left side, get a new vertex and build a table
480 of y-coordinates so we can walk toward the new vertex */
481 if (left_line_count<=0)
482 {
483 do /* clockwise vertex search */
484 {
485 vertex= (left_vertex==polygon->vertex_count-1) ? 0 : (left_vertex+1);
486 left_line_count= vertices[vertex].x-vertices[left_vertex].x;
487 // dprintf("left line (%d,%d) to (%d,%d) for %d points", vertices[left_vertex].x, vertices[left_vertex].y, vertices[vertex].x, vertices[vertex].y, left_line_count);
488 if (!build_y_table(left_table+aggregate_left_line_count, vertices[left_vertex].x, vertices[left_vertex].y, vertices[vertex].x, vertices[vertex].y)) return;
489 aggregate_left_line_count+= left_line_count;
490 left_vertex= vertex;
491 }
492 while (!left_line_count);
493 }
494
495 /* if we�re out of scan lines on the right side, get a new vertex and build a table
496 of y-coordinates so we can walk toward the new vertex */
497 if (right_line_count<=0)
498 {
499 do /* counter-clockwise vertex search */
500 {
501 vertex= right_vertex ? (right_vertex-1) : (polygon->vertex_count-1);
502 right_line_count= vertices[vertex].x-vertices[right_vertex].x;
503 // dprintf("right line (%d,%d) to (%d,%d) for %d points", vertices[right_vertex].x, vertices[right_vertex].y, vertices[vertex].x, vertices[vertex].y, right_line_count);
504 if (!build_y_table(right_table+aggregate_right_line_count, vertices[right_vertex].x, vertices[right_vertex].y, vertices[vertex].x, vertices[vertex].y)) return;
505 aggregate_right_line_count+= right_line_count;
506 right_vertex= vertex;
507 }
508 while (!right_line_count);
509 }
510
511 /* advance by the minimum of left_line_count and right_line_count */
512 short delta= MIN(left_line_count, right_line_count);
513 fc_assert(delta);
514 total_line_count-= delta;
515 left_line_count-= delta;
516 right_line_count-= delta;
517
518 fc_assert(delta||!total_line_count); /* if our delta is zero, we�d better be out of lines */
519 }
520
521 /* make sure every coordinate is accounted for in our tables */
522 fc_assert(aggregate_right_line_count==aggregate_total_line_count);
523 fc_assert(aggregate_left_line_count==aggregate_total_line_count);
524
525 /* precalculate mode-specific data */
526
527 if ((polygon->transfer_mode == _textured_transfer) || (polygon->transfer_mode == _static_transfer))
528 {
529 _pretexture_vertical_polygon_lines(polygon, screen, view, (struct _vertical_polygon_data *)precalculation_table, vertices[highest_vertex].x, left_table, right_table, aggregate_total_line_count);
530 }
531 else VHALT_DEBUG(csprintf(temporary, "vertical_polygons dont support mode #%d", polygon->transfer_mode));
532
533 /* render all lines */
534 switch (bit_depth)
535 {
536 case 8:
537 switch (polygon->transfer_mode)
538 {
539 case _textured_transfer:
540 if (polygon->texture->flags&_TRANSPARENT_BIT)
541 texture_vertical_polygon_lines<pixel8, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
542 else
543 texture_vertical_polygon_lines<pixel8, _sw_alpha_off, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
544 break;
545 case _static_transfer:
546 if (polygon->texture->flags&_TRANSPARENT_BIT)
547 randomize_vertical_polygon_lines<pixel8, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
548 else
549 randomize_vertical_polygon_lines<pixel8, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
550 break;
551
552 default:
553 fc_assert(false);
554 break;
555 }
556 break;
557
558 case 16:
559 switch (polygon->transfer_mode)
560 {
561 case _textured_transfer:
562 {
563 SW_Texture *sw_texture =0 ;
564 if (graphics_preferences->software_alpha_blending)
565 {
566 sw_texture = SW_Texture_Extras::instance()->GetTexture(polygon->ShapeDesc);
567 }
568 if (sw_texture && !polygon->VoidPresent && sw_texture->opac_type())
569 {
570 if (graphics_preferences->software_alpha_blending == _sw_alpha_fast) {
571 if (polygon->texture->flags & _TRANSPARENT_BIT) {
572 texture_vertical_polygon_lines<pixel16, _sw_alpha_fast, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
573 } else {
574 texture_vertical_polygon_lines<pixel16, _sw_alpha_fast, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
575 }
576 }
577 else if (graphics_preferences->software_alpha_blending == _sw_alpha_nice) {
578 if (polygon->texture->flags & _TRANSPARENT_BIT) {
579 texture_vertical_polygon_lines<pixel16, _sw_alpha_nice, true>(screen, view, (struct _vertical_polygon_data *) precalculation_table, left_table, right_table, sw_texture->opac_table());
580 } else {
581 texture_vertical_polygon_lines<pixel16, _sw_alpha_nice, false>(screen, view, (struct _vertical_polygon_data *) precalculation_table, left_table, right_table, sw_texture->opac_table());
582 }
583 }
584 } else {
585 if (polygon->texture->flags & _TRANSPARENT_BIT) {
586 texture_vertical_polygon_lines<pixel16, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
587 } else {
588 texture_vertical_polygon_lines<pixel16, _sw_alpha_off, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
589 }
590 }
591 }
592 break;
593 case _static_transfer:
594 if (polygon->texture->flags & _TRANSPARENT_BIT) {
595 randomize_vertical_polygon_lines<pixel16, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
596 } else {
597 randomize_vertical_polygon_lines<pixel16, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
598 }
599 break;
600 default:
601 fc_assert(false);
602 break;
603 }
604 break;
605
606 case 32:
607 switch (polygon->transfer_mode)
608 {
609 case _textured_transfer:
610 {
611 SW_Texture *sw_texture = 0;
612 if (graphics_preferences->software_alpha_blending)
613 {
614 sw_texture = SW_Texture_Extras::instance()->GetTexture(polygon->ShapeDesc);
615 }
616 if (sw_texture && !polygon->VoidPresent && sw_texture->opac_type())
617 {
618 if (graphics_preferences->software_alpha_blending == _sw_alpha_fast) {
619 if (polygon->texture->flags&_TRANSPARENT_BIT)
620 texture_vertical_polygon_lines<pixel32, _sw_alpha_fast, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
621 else
622 texture_vertical_polygon_lines<pixel32, _sw_alpha_fast, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
623 }
624 else if (graphics_preferences->software_alpha_blending == _sw_alpha_nice)
625 {
626 if (polygon->texture->flags & _TRANSPARENT_BIT)
627 texture_vertical_polygon_lines<pixel32, _sw_alpha_nice, true>(screen, view, (struct _vertical_polygon_data *) precalculation_table, left_table, right_table, sw_texture->opac_table());
628 else
629 texture_vertical_polygon_lines<pixel32, _sw_alpha_nice, false>(screen, view, (struct _vertical_polygon_data *) precalculation_table, left_table, right_table, sw_texture->opac_table());
630 }
631 } else {
632 if (polygon->texture->flags & _TRANSPARENT_BIT)
633 texture_vertical_polygon_lines<pixel32, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
634 else
635 texture_vertical_polygon_lines<pixel32, _sw_alpha_off, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table);
636 }
637 break;
638 }
639 case _static_transfer:
640 if (polygon->texture->flags & _TRANSPARENT_BIT)
641 randomize_vertical_polygon_lines<pixel32, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
642 else
643 randomize_vertical_polygon_lines<pixel32, false>(screen, view, (struct _vertical_polygon_data *)precalculation_table, left_table, right_table, polygon->transfer_data);
644 break;
645
646 default:
647 fc_assert(false);
648 break;
649 }
650 break;
651
652 default:
653 fc_assert(false);
654 break;
655 }
656 }
657 }
658
texture_rectangle(rectangle_definition & textured_rectangle)659 void Rasterizer_SW_Class::texture_rectangle(rectangle_definition& textured_rectangle)
660 {
661 rectangle_definition *rectangle = &textured_rectangle; // Reference to pointer
662
663 if (rectangle->x0<rectangle->x1 && rectangle->y0<rectangle->y1)
664 {
665 /* subsume screen boundaries into clipping parameters */
666 if (rectangle->clip_left<0) rectangle->clip_left= 0;
667 if (rectangle->clip_right>screen->width) rectangle->clip_right= screen->width;
668 if (rectangle->clip_top<0) rectangle->clip_top= 0;
669 if (rectangle->clip_bottom>screen->height) rectangle->clip_bottom= screen->height;
670
671 /* subsume left and right sides of the rectangle into clipping parameters */
672 if (rectangle->clip_left<rectangle->x0) rectangle->clip_left= rectangle->x0;
673 if (rectangle->clip_right>rectangle->x1) rectangle->clip_right= rectangle->x1;
674 if (rectangle->clip_top<rectangle->y0) rectangle->clip_top= rectangle->y0;
675 if (rectangle->clip_bottom>rectangle->y1) rectangle->clip_bottom= rectangle->y1;
676
677 /* only continue if we have a non-empty rectangle, at least some of which is on the screen */
678 if (rectangle->clip_left<rectangle->clip_right && rectangle->clip_top<rectangle->clip_bottom &&
679 rectangle->clip_right>0 && rectangle->clip_left<screen->width &&
680 rectangle->clip_bottom>0 && rectangle->clip_top<screen->height)
681 {
682 short delta; /* scratch */
683 short screen_width= rectangle->x1-rectangle->x0;
684 short screen_height= rectangle->y1-rectangle->y0;
685 short screen_x= rectangle->x0;
686 struct bitmap_definition *texture= rectangle->texture;
687
688 short *y0_table= scratch_table0, *y1_table= scratch_table1;
689 struct _vertical_polygon_data *header= (struct _vertical_polygon_data *)precalculation_table;
690 struct _vertical_polygon_line_data *data= (struct _vertical_polygon_line_data *) (header+1);
691
692 _fixed texture_dx= INTEGER_TO_FIXED(texture->width)/screen_width;
693 _fixed texture_x= texture_dx>>1;
694
695 _fixed texture_dy= INTEGER_TO_FIXED(texture->height)/screen_height;
696 _fixed texture_y0= 0;
697 _fixed texture_y1;
698
699 if (texture_dx&&texture_dy)
700 {
701 /* handle horizontal mirroring */
702 if (rectangle->flip_horizontal)
703 {
704 texture_dx= -texture_dx;
705 texture_x= INTEGER_TO_FIXED(texture->width)+(texture_dx>>1);
706 }
707
708 /* left clipping */
709 if ((delta= rectangle->clip_left-rectangle->x0)>0)
710 {
711 texture_x+= delta*texture_dx;
712 screen_width-= delta;
713 screen_x= rectangle->clip_left;
714 }
715 /* right clipping */
716 if ((delta= rectangle->x1-rectangle->clip_right)>0)
717 {
718 screen_width-= delta;
719 }
720
721 /* top clipping */
722 if ((delta= rectangle->clip_top-rectangle->y0)>0)
723 {
724 texture_y0+= delta*texture_dy;
725 screen_height-= delta;
726 }
727
728 /* bottom clipping */
729 if ((delta= rectangle->y1-rectangle->clip_bottom)>0)
730 {
731 screen_height-= delta;
732 }
733
734 texture_y1= texture_y0 + screen_height*texture_dy;
735
736 header->downshift= FIXED_FRACTIONAL_BITS;
737 header->width= screen_width;
738 header->x0= screen_x;
739
740 /* calculate shading table, once */
741 void *shading_table = NULL;
742 switch (rectangle->transfer_mode)
743 {
744 case _textured_transfer:
745 if (!(rectangle->flags&_SHADELESS_BIT))
746 {
747 // LP change:
748 // Made this more long-distance friendly
749 calculate_shading_table(shading_table, view, rectangle->shading_tables, (short)MIN(rectangle->depth, SHRT_MAX), rectangle->ambient_shade);
750 break;
751 }
752 /* if shadeless, fall through to a single shading table, ignoring depth */
753 case _tinted_transfer:
754 case _static_transfer:
755 shading_table= rectangle->shading_tables;
756 break;
757
758 default:
759 VHALT_DEBUG(csprintf(temporary, "rectangles dont support mode #%d", rectangle->transfer_mode));
760 }
761
762 for (; screen_width; --screen_width)
763 {
764 byte *read= texture->row_addresses[FIXED_INTEGERAL_PART(texture_x)];
765 // CB: first/last are stored in big-endian order
766 uint16 first = *read++ << 8;
767 first |= *read++;
768 uint16 last = *read++ << 8;
769 last |= *read++;
770 _fixed texture_y= texture_y0;
771 short y0= rectangle->clip_top, y1= rectangle->clip_bottom;
772
773 if (FIXED_INTEGERAL_PART(texture_y0)<first)
774 {
775 delta= (INTEGER_TO_FIXED(first) - texture_y0)/texture_dy + 1;
776 fc_vassert(delta>=0, csprintf(temporary, "[%x,%x] �=%x (#%d,#%d)", texture_y0, texture_y1, texture_dy, first, last));
777
778 y0= MIN(y1, y0+delta);
779 texture_y+= delta*texture_dy;
780 }
781
782 if (FIXED_INTEGERAL_PART(texture_y1)>last)
783 {
784 delta= (texture_y1 - INTEGER_TO_FIXED(last))/texture_dy + 1;
785 fc_vassert(delta>=0, csprintf(temporary, "[%x,%x] �=%x (#%d,#%d)", texture_y0, texture_y1, texture_dy, first, last));
786
787 y1= MAX(y0, y1-delta);
788 }
789
790 data->texture_y= texture_y - INTEGER_TO_FIXED(first);
791 data->texture_dy= texture_dy;
792 data->shading_table= shading_table;
793 data->texture= (unsigned char *)read;
794
795 texture_x+= texture_dx;
796 data+= 1;
797
798 *y0_table++= y0;
799 *y1_table++= y1;
800
801 fc_assert(y0<=y1);
802 fc_assert(y0>=0 && y1>=0);
803 fc_assert(y0<=screen->height);
804 fc_assert(y1<=screen->height);
805 }
806
807 switch (bit_depth)
808 {
809 case 8:
810 switch (rectangle->transfer_mode)
811 {
812 case _textured_transfer:
813 texture_vertical_polygon_lines<pixel8, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
814 scratch_table0, scratch_table1);
815 break;
816
817 case _static_transfer:
818 randomize_vertical_polygon_lines<pixel8, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
819 scratch_table0, scratch_table1, rectangle->transfer_data);
820 break;
821
822 case _tinted_transfer:
823 tint_vertical_polygon_lines<pixel8>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
824 scratch_table0, scratch_table1, rectangle->transfer_data);
825 break;
826
827 default:
828 fc_assert(false);
829 break;
830 }
831 break;
832
833 case 16:
834 switch (rectangle->transfer_mode)
835 {
836 case _textured_transfer:
837 texture_vertical_polygon_lines<pixel16, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table, scratch_table0, scratch_table1);
838 break;
839
840 case _static_transfer:
841 randomize_vertical_polygon_lines<pixel16, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
842 scratch_table0, scratch_table1, rectangle->transfer_data);
843 break;
844
845 case _tinted_transfer:
846 tint_vertical_polygon_lines<pixel16>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
847 scratch_table0, scratch_table1, rectangle->transfer_data);
848 break;
849
850 default:
851 fc_assert(false);
852 break;
853 }
854 break;
855
856 case 32:
857 switch (rectangle->transfer_mode)
858 {
859 case _textured_transfer:
860 texture_vertical_polygon_lines<pixel32, _sw_alpha_off, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
861 scratch_table0, scratch_table1);
862 break;
863
864 case _static_transfer:
865 randomize_vertical_polygon_lines<pixel32, true>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
866 scratch_table0, scratch_table1, rectangle->transfer_data);
867 break;
868
869 case _tinted_transfer:
870 tint_vertical_polygon_lines<pixel32>(screen, view, (struct _vertical_polygon_data *)precalculation_table,
871 scratch_table0, scratch_table1, rectangle->transfer_data);
872 break;
873
874 default:
875 fc_assert(false);
876 break;
877 }
878 break;
879
880 default:
881 fc_assert(false);
882 break;
883 }
884 }
885 }
886 }
887 }
888
889 /* ---------- private code */
890
891 /* starting at x0 and for line_count vertical lines between *y0 and *y1, precalculate all the
892 information _texture_vertical_polygon_lines will need to work */
_pretexture_vertical_polygon_lines(struct polygon_definition * polygon,struct bitmap_definition * screen,struct view_data * view,struct _vertical_polygon_data * data,short x0,short * y0_table,short * y1_table,short line_count)893 static void _pretexture_vertical_polygon_lines(
894 struct polygon_definition *polygon,
895 struct bitmap_definition *screen,
896 struct view_data *view,
897 struct _vertical_polygon_data *data,
898 short x0,
899 short *y0_table,
900 short *y1_table,
901 short line_count)
902 {
903 short screen_x= x0-view->half_screen_width;
904 int32 dz0= view->world_to_screen_y*polygon->origin.z;
905 int32 unadjusted_ty_denominator= view->world_to_screen_y*polygon->vector.k;
906 int32 tx_numerator, tx_denominator, tx_numerator_delta, tx_denominator_delta;
907 struct _vertical_polygon_line_data *line= (struct _vertical_polygon_line_data *) (data+1);
908
909 (void) (screen);
910
911 fc_assert(sizeof(struct _vertical_polygon_line_data)<=MAXIMUM_PRECALCULATION_TABLE_ENTRY_SIZE);
912
913 data->downshift= VERTICAL_TEXTURE_DOWNSHIFT;
914 data->x0= x0;
915 data->width= line_count;
916
917 /* calculate and rescale tx_numerator, tx_denominator, etc. */
918 tx_numerator= view->world_to_screen_x*polygon->origin.y - screen_x*polygon->origin.x;
919 tx_denominator= screen_x*polygon->vector.i - view->world_to_screen_x*polygon->vector.j;
920 tx_numerator_delta= -polygon->origin.x;
921 tx_denominator_delta= polygon->vector.i;
922
923 while (--line_count>=0)
924 {
925 _fixed tx;
926 // LP change: made this quantity more long-distance friendly;
927 // have to avoid doing INTEGER_TO_FIXED on this one, however
928 int32 world_x;
929 short x0, y0= *y0_table++;
930 short screen_y0= view->half_screen_height-y0+view->dtanpitch;
931 int32 ty_numerator, ty_denominator;
932 _fixed ty, ty_delta;
933
934 /* would our precision be greater here if we shifted the numerator up to $7FFFFFFF and
935 then downshifted only the numerator? too bad we can�t use BFFFO in 68k */
936 {
937 int32 adjusted_tx_denominator= tx_denominator;
938 int32 adjusted_tx_numerator= tx_numerator;
939
940 while (adjusted_tx_numerator>((1<<(31-VERTICAL_TEXTURE_WIDTH_BITS))-1) ||
941 adjusted_tx_numerator<((-1)<<(31-VERTICAL_TEXTURE_WIDTH_BITS)))
942 {
943 adjusted_tx_numerator>>= 1, adjusted_tx_denominator>>= 1;
944 }
945 if (!adjusted_tx_denominator) adjusted_tx_denominator= 1; /* -1 will still be -1 */
946 x0= ((adjusted_tx_numerator<<VERTICAL_TEXTURE_WIDTH_BITS)/adjusted_tx_denominator)&(VERTICAL_TEXTURE_WIDTH-1);
947
948 while (adjusted_tx_numerator>INT16_MAX||adjusted_tx_numerator<INT16_MIN)
949 {
950 adjusted_tx_numerator>>= 1, adjusted_tx_denominator>>= 1;
951 }
952 if (!adjusted_tx_denominator) adjusted_tx_denominator= 1; /* -1 will still be -1 */
953 tx= INTEGER_TO_FIXED(adjusted_tx_numerator)/adjusted_tx_denominator;
954 }
955
956 world_x = polygon->origin.x + (int32(1LL*tx*polygon->vector.i) >> FIXED_FRACTIONAL_BITS);
957 if (world_x<0) world_x= -world_x; /* it is mostly unclear what we�re supposed to do with negative x values */
958
959 /* calculate and rescale ty_numerator, ty_denominator and calculate ty */
960 ty_numerator= world_x*screen_y0 - dz0;
961 ty_denominator= unadjusted_ty_denominator;
962 while (ty_numerator>INT16_MAX||ty_numerator<INT16_MIN)
963 {
964 ty_numerator>>= 1, ty_denominator>>= 1;
965 }
966 if (!ty_denominator) ty_denominator= 1; /* -1 will still be -1 */
967 ty= INTEGER_TO_FIXED(ty_numerator)/ty_denominator;
968
969 // LP change:
970 // Use the same reduction hack used earlier,
971 // because otherwise, INTEGER_TO_FIXED would cause world_x to wrap around.
972 int32 adjusted_world_x = world_x;
973 int32 adjusted_ty_denominator = unadjusted_ty_denominator>>8;
974
975 // LP: remember that world_x is always >= 0
976 while(adjusted_world_x > INT16_MAX)
977 {
978 adjusted_world_x >>= 1; adjusted_ty_denominator >>= 1;
979 }
980 if (!adjusted_ty_denominator) adjusted_ty_denominator= 1; /* -1 will still be -1 */
981 ty_delta= - INTEGER_TO_FIXED(adjusted_world_x)/adjusted_ty_denominator;
982
983 fc_vassert(ty_delta>=0, csprintf(temporary, "ty_delta=W2F(%d)/%d=%d", world_x, unadjusted_ty_denominator, ty_delta));
984
985 /* calculate the shading table for this column */
986 if (polygon->flags&_SHADELESS_BIT)
987 {
988 line->shading_table= polygon->shading_tables;
989 }
990 else
991 {
992 // LP change: made this more long-distance friendly
993 calculate_shading_table(line->shading_table, view, polygon->shading_tables, (short)MIN(world_x, SHRT_MAX), polygon->ambient_shade);
994 // calculate_shading_table(line->shading_table, view, polygon->shading_tables, world_x, polygon->ambient_shade);
995 }
996
997 // if (ty_delta)
998 {
999 /* calculate texture_y and texture_dy (floor-mapper style) */
1000 // data->n= VERTICAL_TEXTURE_DOWNSHIFT;
1001 line->texture_y= ty<<VERTICAL_TEXTURE_FREE_BITS;
1002 line->texture_dy= ty_delta<<(VERTICAL_TEXTURE_FREE_BITS-8);
1003 line->texture= polygon->texture->row_addresses[x0];
1004
1005 line+= 1;
1006 }
1007
1008 tx_numerator+= tx_numerator_delta;
1009 tx_denominator+= tx_denominator_delta;
1010
1011 screen_x+= 1;
1012 }
1013 }
1014
_pretexture_horizontal_polygon_lines(struct polygon_definition * polygon,struct bitmap_definition * screen,struct view_data * view,struct _horizontal_polygon_line_data * data,short y0,short * x0_table,short * x1_table,short line_count)1015 static void _pretexture_horizontal_polygon_lines(
1016 struct polygon_definition *polygon,
1017 struct bitmap_definition *screen,
1018 struct view_data *view,
1019 struct _horizontal_polygon_line_data *data,
1020 short y0,
1021 short *x0_table,
1022 short *x1_table,
1023 short line_count)
1024 {
1025 int32 hcosine, dhcosine;
1026 int32 hsine, dhsine;
1027 int32 hworld_to_screen;
1028 bool higher_precision= polygon->origin.z>-WORLD_ONE && polygon->origin.z<WORLD_ONE;
1029
1030 (void) (screen);
1031
1032 /* precalculate a bunch of multiplies */
1033 hcosine= cosine_table[view->yaw];
1034 hsine= sine_table[view->yaw];
1035 if (higher_precision)
1036 {
1037 hcosine*= polygon->origin.z;
1038 hsine*= polygon->origin.z;
1039 }
1040 hworld_to_screen= polygon->origin.z*view->world_to_screen_y;
1041 dhcosine= view->world_to_screen_y*hcosine;
1042 dhsine= view->world_to_screen_y*hsine;
1043
1044 while ((line_count-=1)>=0)
1045 {
1046 // LP change: made this more long-distance-friendly
1047 int32 depth;
1048 // world_distance depth;
1049 short screen_x, screen_y;
1050 short x0= *x0_table++;
1051
1052 /* calculate screen_x,screen_y */
1053 screen_x= x0-view->half_screen_width;
1054 screen_y= view->half_screen_height-y0+view->dtanpitch;
1055 if (!screen_y) screen_y= 1; /* this will avoid division by zero and won't change rendering */
1056
1057 /* calculate source_x, source_y, source_dx, source_dy */
1058
1059 int32 source_x, source_y, source_dx, source_dy;
1060
1061 /* calculate texture origins and deltas (source_x,source_dx,source_y,source_dy) */
1062 if (higher_precision)
1063 {
1064 source_x= (dhcosine - screen_x*hsine)/screen_y + (polygon->origin.x<<TRIG_SHIFT);
1065 source_dx= - hsine/screen_y;
1066 source_y= (screen_x*hcosine + dhsine)/screen_y + (polygon->origin.y<<TRIG_SHIFT);
1067 source_dy= hcosine/screen_y;
1068 }
1069 else
1070 {
1071 source_x= ((dhcosine - screen_x*hsine)/screen_y)*polygon->origin.z + (polygon->origin.x<<TRIG_SHIFT);
1072 source_dx= - (hsine*polygon->origin.z)/screen_y;
1073 source_y= ((screen_x*hcosine + dhsine)/screen_y)*polygon->origin.z + (polygon->origin.y<<TRIG_SHIFT);
1074 source_dy= (hcosine*polygon->origin.z)/screen_y;
1075 }
1076
1077 /* voodoo so x,y texture wrapping is handled automatically by downshifting
1078 (subtract one from HORIZONTAL_FREE_BITS to double scale) */
1079 data->source_x= source_x<<HORIZONTAL_FREE_BITS, data->source_dx= source_dx<<HORIZONTAL_FREE_BITS;
1080 data->source_y= source_y<<HORIZONTAL_FREE_BITS, data->source_dy= source_dy<<HORIZONTAL_FREE_BITS;
1081
1082
1083 /* get shading table (with absolute value of depth) */
1084 if ((depth= hworld_to_screen/screen_y)<0) depth= -depth;
1085 if (polygon->flags&_SHADELESS_BIT)
1086 {
1087 data->shading_table= polygon->shading_tables;
1088 }
1089 else
1090 {
1091 calculate_shading_table(data->shading_table, view, polygon->shading_tables, (short)MIN(depth, SHRT_MAX), polygon->ambient_shade);
1092 }
1093
1094 data++;
1095 y0++;
1096 }
1097 }
1098
1099
1100 // height must be determined emperically (texture is vertically centered at 0�)
1101 // #define LANDSCAPE_REPEAT_BITS 1
_prelandscape_horizontal_polygon_lines(struct polygon_definition * polygon,struct bitmap_definition * screen,struct view_data * view,struct _horizontal_polygon_line_data * data,short y0,short * x0_table,short * x1_table,short line_count)1102 static void _prelandscape_horizontal_polygon_lines(
1103 struct polygon_definition *polygon,
1104 struct bitmap_definition *screen,
1105 struct view_data *view,
1106 struct _horizontal_polygon_line_data *data,
1107 short y0,
1108 short *x0_table,
1109 short *x1_table,
1110 short line_count)
1111 {
1112 // LP change: made this more general:
1113 short landscape_width_bits= NextLowerExponent(polygon->texture->height);
1114 short texture_height= polygon->texture->width;
1115 _fixed ambient_shade= FIXED_ONE; // MPW C died if we passed the constant directly to the macro
1116
1117 // Get the landscape-texturing options
1118 LandscapeOptions *LandOpts = View_GetLandscapeOptions(polygon->ShapeDesc);
1119
1120 // LP change: separate horizontal and vertical pixel deltas:
1121 // LP change: using a "landscape yaw" that's at the left edge of the screen.
1122 _fixed first_horizontal_pixel= (view->landscape_yaw + LandOpts->Azimuth)<<(landscape_width_bits+(LandOpts->HorizExp)+FIXED_FRACTIONAL_BITS-ANGULAR_BITS);
1123 _fixed horizontal_pixel_delta= (view->half_cone<<(1+landscape_width_bits+(LandOpts->HorizExp)+FIXED_FRACTIONAL_BITS-ANGULAR_BITS))/view->standard_screen_width;
1124 _fixed vertical_pixel_delta= (view->half_cone<<(1+landscape_width_bits+(LandOpts->VertExp)+FIXED_FRACTIONAL_BITS-ANGULAR_BITS))/view->standard_screen_width;
1125 short landscape_free_bits= 32-FIXED_FRACTIONAL_BITS-landscape_width_bits;
1126
1127 (void) (screen);
1128
1129 /* calculate the shading table */
1130 void *shading_table = NULL;
1131 if (polygon->flags&_SHADELESS_BIT)
1132 {
1133 shading_table= polygon->shading_tables;
1134 }
1135 else
1136 {
1137 calculate_shading_table(shading_table, view, polygon->shading_tables, 0, ambient_shade);
1138 }
1139
1140 // Find the height to repeat over; use value used for OpenGL texture setup
1141 short texture_width= polygon->texture->height;
1142 short repeat_texture_height = texture_width >> LandOpts->OGL_AspRatExp;
1143
1144 short height_reduced = texture_height - 1;
1145 short height_shift = texture_height >> 1;
1146 short height_repeat_mask = repeat_texture_height - 1;
1147 short height_repeat_shift = repeat_texture_height >> 1;
1148
1149 y0-= view->half_screen_height + view->dtanpitch; /* back to virtual screen coordinates */
1150 while ((line_count-= 1)>=0)
1151 {
1152 short x0= *x0_table++;
1153
1154 data->shading_table= shading_table;
1155 // LP change: using vertical pixel delta
1156 // Also using vertical repeat if selected;
1157 // fold the height into the range (-repeat_height/2, repeat_height)
1158 short y_txtr_offset= FIXED_INTEGERAL_PART(y0*vertical_pixel_delta);
1159 if (LandOpts->VertRepeat)
1160 y_txtr_offset = ((y_txtr_offset + height_repeat_shift) & height_repeat_mask) -
1161 height_repeat_shift;
1162 data->source_y= texture_height - PIN(y_txtr_offset + height_shift, 0, height_reduced) - 1;
1163 // LP change: using horizontal pixel delta
1164 data->source_x= (first_horizontal_pixel + x0*horizontal_pixel_delta)<<landscape_free_bits;
1165 data->source_dx= horizontal_pixel_delta<<landscape_free_bits;
1166
1167 data+= 1;
1168 y0+= 1;
1169 }
1170 }
1171
1172 /* y0<y1; this is for vertical polygons */
build_x_table(short * table,short x0,short y0,short x1,short y1)1173 static short *build_x_table(
1174 short *table,
1175 short x0,
1176 short y0,
1177 short x1,
1178 short y1)
1179 {
1180 short dx, dy, adx, ady; /* 'a' prefix means absolute value */
1181 short x, y; /* x,y screen positions */
1182 short d, delta_d, d_max; /* descriminator, delta_descriminator, descriminator_maximum */
1183 short *record;
1184
1185 /* calculate SGN(dx),SGN(dy) and the absolute values of dx,dy */
1186 dx= x1-x0, adx= ABS(dx), dx= SGN(dx);
1187 dy= y1-y0, ady= ABS(dy), dy= SGN(dy);
1188
1189 fc_assert(ady<MAXIMUM_SCRATCH_TABLE_ENTRIES); /* can't overflow table */
1190 if (dy>0)
1191 {
1192 /* setup initial (x,y) location and initialize a pointer to our table */
1193 x= x0, y= y0;
1194 record= table;
1195
1196 if (adx>=ady)
1197 {
1198 /* x-dominant line (we need to record x every time y changes) */
1199
1200 d= adx-ady, delta_d= - 2*ady, d_max= 2*adx;
1201 while ((adx-=1)>=0)
1202 {
1203 if (d<0) y+= 1, d+= d_max, *record++= x, ady-= 1;
1204 x+= dx, d+= delta_d;
1205 }
1206 if (ady==1) *record++= x; else fc_assert(!ady);
1207 }
1208 else
1209 {
1210 /* y-dominant line (we need to record x every iteration) */
1211
1212 d= ady-adx, delta_d= - 2*adx, d_max= 2*ady;
1213 while ((ady-=1)>=0)
1214 {
1215 if (d<0) x+= dx, d+= d_max;
1216 *record++= x;
1217 y+= 1, d+= delta_d;
1218 }
1219 }
1220 }
1221 else
1222 {
1223 /* can�t build a table for negative dy */
1224 if (dy<0) return NULL;
1225 }
1226
1227 return table;
1228 }
1229
1230 /* x0<x1; this is for horizontal polygons */
build_y_table(short * table,short x0,short y0,short x1,short y1)1231 static short *build_y_table(
1232 short *table,
1233 short x0,
1234 short y0,
1235 short x1,
1236 short y1)
1237 {
1238 short dx, dy, adx, ady; /* 'a' prefix means absolute value */
1239 short x, y; /* x,y screen positions */
1240 short d, delta_d, d_max; /* descriminator, delta_descriminator, descriminator_maximum */
1241 short *record;
1242
1243 /* calculate SGN(dx),SGN(dy) and the absolute values of dx,dy */
1244 dx= x1-x0, adx= ABS(dx), dx= SGN(dx);
1245 dy= y1-y0, ady= ABS(dy), dy= SGN(dy);
1246
1247 fc_assert(adx<MAXIMUM_SCRATCH_TABLE_ENTRIES); /* can't overflow table */
1248 if (dx>=0) /* vertical lines allowed */
1249 {
1250 /* setup initial (x,y) location and initialize a pointer to our table */
1251 if (dy>=0)
1252 {
1253 x= x0, y= y0;
1254 record= table;
1255 }
1256 else
1257 {
1258 x= x1, y= y1;
1259 record= table+adx;
1260 }
1261
1262 if (adx>=ady)
1263 {
1264 /* x-dominant line (we need to record y every iteration) */
1265
1266 d= adx-ady, delta_d= - 2*ady, d_max= 2*adx;
1267 while ((adx-=1)>=0)
1268 {
1269 if (d<0) y+= 1, d+= d_max;
1270 if (dy>=0) *record++= y; else *--record= y;
1271 x+= dx, d+= delta_d;
1272 }
1273 }
1274 else
1275 {
1276 /* y-dominant line (we need to record y every time x changes) */
1277
1278 d= ady-adx, delta_d= - 2*adx, d_max= 2*ady;
1279 while ((ady-=1)>=0)
1280 {
1281 if (d<0) { x+= dx, d+= d_max, adx-= 1; if (dy>=0) *record++= y; else *--record= y; }
1282 y+= 1, d+= delta_d;
1283 }
1284 if (adx==1) if (dy>=0) *record++= y; else *--record= y; else fc_assert(!adx);
1285 }
1286 }
1287 else
1288 {
1289 /* can�t build a table for a negative dx */
1290 return NULL;
1291 }
1292
1293 return table;
1294 }
1295