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