1 /*
2  * OpenBOR - http://www.LavaLit.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2011 OpenBOR Team
7  */
8 
9 ///////////////////////////////////////////////////////////////////////////
10 //         This file defines some commmon methods used by the gamelib
11 ////////////////////////////////////////////////////////////////////////////
12 
13 #include "globals.h"
14 #include "types.h"
15 
16 #define _swap(va, vb) {vsw=va;va=vb;vb=vsw;}
17 #define P unsigned char
18 
19 
20 extern void draw_pixel_gfx(s_screen* dest, gfx_entry* src, int dx, int dy, int sx, int sy);
21 extern void init_gfx_global_draw_stuff(s_screen*, gfx_entry*, s_drawmethod*);
22 
draw_triangle_list(vert2d * vertices,s_screen * dest,gfx_entry * src,s_drawmethod * drawmethod,int triangleCount)23 void draw_triangle_list(vert2d* vertices, s_screen *dest, gfx_entry *src, s_drawmethod* drawmethod, int triangleCount)
24 {
25 	vert2d *v1, *v2, *v3, *vsw = NULL;
26 
27 	int i, triangleHalf;
28 	float tmpDiv; // temporary division factor
29 	float spanLongest; // saves the spanLongest span
30 	int height; // saves height of triangle
31 	int targetY; // target pointer where to plot pixels
32 	int spanEnd; // saves end of spans
33 	float leftdeltaxf; // amount of pixels to increase on left side of triangle
34 	float rightdeltaxf; // amount of pixels to increase on right side of triangle
35 	int leftx, rightx, temp; // position where we are
36 	float leftxf, rightxf; // same as above, but as float values
37 	int span; // current span
38 	int	hSpanBegin, hSpanEnd; // pointer used when plotting pixels
39 	float leftTx, rightTx, leftTy, rightTy; // texture interpolating values
40 	float leftTxStep, rightTxStep, leftTyStep, rightTyStep; // texture interpolating values
41 	float spanTx, spanTy, spanTxStep, spanTyStep; // values of Texturecoords when drawing a span
42 	rect2d trect, vrect; //triangle rect
43 	unsigned char* shadow_buffer; // temporary fix to remove overlapping, relatively slow
44 
45 	init_gfx_global_draw_stuff(dest, src, drawmethod);
46 
47 	vrect.ulx = vrect.uly = 0;
48 	vrect.lrx = dest->width;
49 	vrect.lry = dest->height;
50 
51 	shadow_buffer = malloc(dest->width*dest->height);
52 
53 	if(!shadow_buffer) return;
54 
55 	memset(shadow_buffer, 0, dest->width*dest->height);
56 /*
57 	if(triangleCount==8 && src->type == gfx_sprite){
58 		printf("%ld\n", src->sprite);
59 	}
60 	*/
61 	for (i=0; i<triangleCount; ++i)
62 	{
63 		v1 = &vertices[i];
64 		v2 = &vertices[i+1];
65 		v3 = &vertices[i+2];
66 
67 		// sort in order of v1 <= v2 <= v3
68 		if (v1->x > v2->x)	_swap(v1, v2);
69 		if (v1->x > v3->x)	_swap(v1, v3);
70 		if (v2->x > v3->x)	_swap(v2, v3);
71 
72 		if ((v1->x - v3->x) == 0)
73 			continue;
74 
75 		trect.ulx = v1->x;
76 		trect.lrx = v3->x;
77 
78 		// sort in order of v1 <= v2 <= v3
79 		if (v1->y > v2->y)	_swap(v1, v2);
80 		if (v1->y > v3->y)	_swap(v1, v3);
81 		if (v2->y > v3->y)	_swap(v2, v3);
82 
83 		trect.uly = v1->y;
84 		trect.lry = v3->y;
85 
86 		if (trect.ulx>vrect.lrx || trect.uly>vrect.lry || trect.lrx<vrect.ulx || trect.lry<vrect.uly)
87 			continue;
88 
89 		// calculate height of triangle
90 		height = v3->y - v1->y;
91 		if (!height)
92 			continue;
93 
94 		spanLongest = (v2->y - v1->y) / (float)height * (v3->x - v1->x) + (v1->x - v2->x);
95 
96 		spanEnd = v2->y;
97 		span = v1->y;
98 		leftxf = (float)v1->x;
99 		rightxf = (float)v1->x;
100 
101 		leftTx = rightTx = v1->tx;
102 		leftTy = rightTy = v1->ty;
103 
104 		targetY = span;
105 
106 		if (spanLongest < 0.0f)
107 		{
108 			tmpDiv = 1.0f / (float)(v2->y - v1->y);
109 			rightdeltaxf = (v2->x - v1->x) * tmpDiv;
110 			rightTxStep = (v2->tx - rightTx) * tmpDiv;
111 			rightTyStep = (v2->ty - rightTy) * tmpDiv;
112 
113 			tmpDiv = 1.0f / (float)height;
114 			leftdeltaxf = (v3->x - v1->x) * tmpDiv;
115 			leftTxStep = (v3->tx - leftTx) * tmpDiv;
116 			leftTyStep = (v3->ty - leftTy) * tmpDiv;
117 		}
118 		else
119 		{
120 			tmpDiv = 1.0f / (float)height;
121 			rightdeltaxf = (v3->x - v1->x) * tmpDiv;
122 			rightTxStep = (v3->tx - rightTx) * tmpDiv;
123 			rightTyStep = (v3->ty - rightTy) * tmpDiv;
124 
125 			tmpDiv = 1.0f / (float)(v2->y - v1->y);
126 			leftdeltaxf = (v2->x - v1->x) * tmpDiv;
127 			leftTxStep = (v2->tx - leftTx) * tmpDiv;
128 			leftTyStep = (v2->ty - leftTy) * tmpDiv;
129 		}
130 
131 
132 		//draw upper and lower half of the triangle
133 		for (triangleHalf=0; triangleHalf<2; ++triangleHalf)
134 		{
135 			if (spanEnd > vrect.lry)
136 				spanEnd = vrect.lry;
137 
138 			// if the span <0, than we can skip these spans,
139 			// and proceed to the next spans which are really on the screen.
140 			if (span < vrect.uly)
141 			{
142 				if (spanEnd < vrect.uly)
143 				{
144 					temp = spanEnd - span;
145 					span = spanEnd;
146 				}
147 				else
148 				{
149 					temp = vrect.uly - span;
150 					span = vrect.uly;
151 				}
152 
153 				leftxf += leftdeltaxf*temp;
154 				rightxf += rightdeltaxf*temp;
155 				targetY += temp;
156 
157 				leftTx += leftTxStep*temp;
158 				leftTy += leftTyStep*temp;
159 				rightTx += rightTxStep*temp;
160 				rightTy += rightTyStep*temp;
161 			}
162 
163 
164 			// draw each line of the part
165 			while (span < spanEnd)
166 			{
167 				leftx = (int)(leftxf);
168 				rightx = (int)(rightxf + 0.5f);
169 
170 				// TODO: perform clipping before going for the pixels
171 				if (rightx - leftx != 0)
172 				{
173 					tmpDiv = 1.0f / (rightxf - leftxf); // important: use float version of the right and left values to avoid sawtooth left edge
174 
175 					hSpanBegin = leftx;
176 					hSpanEnd = rightx;
177 
178 					spanTx = (float)leftTx;
179 					spanTy = (float)leftTy;
180 					spanTxStep = (rightTx - leftTx) * tmpDiv;
181 					spanTyStep = (rightTy - leftTy) * tmpDiv;
182 
183 					while (hSpanBegin < hSpanEnd)
184 					{
185 						if(hSpanBegin>=vrect.ulx && hSpanBegin<vrect.lrx)
186 						{
187 							temp = hSpanBegin + targetY*dest->width;
188 							//*hSpanBegin = srcp[(int)spanTy * src->width + (int)spanTx];
189 							if(!shadow_buffer[temp])
190 							{
191 								draw_pixel_gfx(dest, src, hSpanBegin, targetY, (int)spanTx, (int)spanTy);
192 								shadow_buffer[temp] = 1;
193 							}
194 						}
195 
196 						spanTx += spanTxStep;
197 						spanTy += spanTyStep;
198 
199 						++hSpanBegin;
200 					}
201 				}
202 
203 				leftxf += leftdeltaxf;
204 				rightxf += rightdeltaxf;
205 				++span;
206 				++targetY;
207 
208 				leftTx += leftTxStep;
209 				leftTy += leftTyStep;
210 				rightTx += rightTxStep;
211 				rightTy += rightTyStep;
212 
213 				//printf("rightTyStep %d  leftTyStep %d\n", rightTyStep, leftTyStep);
214 			}
215 
216 			if (triangleHalf>0) // break, we've gout only two halves
217 				break;
218 
219 
220 			// setup variables for second half of the triangle.
221 
222 			if (spanLongest < 0.0f)
223 			{
224 				tmpDiv = 1.0f / (v3->y - v2->y);
225 
226 				rightdeltaxf = (v3->x - v2->x) * tmpDiv;
227 				rightxf = (float)v2->x;
228 
229 				rightTx = v2->tx;
230 				rightTy = v2->ty;
231 				rightTxStep = (v3->tx - rightTx) * tmpDiv;
232 				rightTyStep = (v3->ty - rightTy) * tmpDiv;
233 			}
234 			else
235 			{
236 				tmpDiv = 1.0f / (v3->y - v2->y);
237 
238 				leftdeltaxf = (v3->x - v2->x) * tmpDiv;
239 				leftxf = (float)v2->x;
240 
241 				leftTx = v2->tx;
242 				leftTy = v2->ty;
243 				leftTxStep = (v3->tx - leftTx) * tmpDiv;
244 				leftTyStep = (v3->ty - leftTy) * tmpDiv;
245 			}
246 
247 
248 			spanEnd = v3->y;
249 		}
250 
251 	}
252 	free(shadow_buffer);
253 	shadow_buffer = NULL;
254 }
255 #undef P
256 #undef _swap
257 ////////////////////////////////////////////////////////////////
258 
259 
260 
261