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