Changeset 3909 for libcaca/trunk/caca/triangle.c
 Timestamp:
 Nov 16, 2009, 1:17:01 PM (10 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

libcaca/trunk/caca/triangle.c
r2826 r3909 156 156 } 157 157 158 /** \brief Fill a triangle on the canvas using an arbitrarysized texture. 159 * 160 * This function fails if one or both the canvas are missing 161 * 162 * \param cv The handle to the libcaca canvas. 163 * \param x1 X coordinate of the first point. 164 * \param y1 Y coordinate of the first point. 165 * \param x2 X coordinate of the second point. 166 * \param y2 Y coordinate of the second point. 167 * \param x3 X coordinate of the third point. 168 * \param y3 Y coordinate of the third point. 169 * \param u1 U texture coordinate of the first point. 170 * \param v1 V texture coordinate of the first point. 171 * \param u2 U texture coordinate of the second point. 172 * \param v2 V texture coordinate of the second point. 173 * \param u3 U texture coordinate of the third point. 174 * \param v3 V texture coordinate of the third point. 175 * \param tex The handle of the canvas texture. 176 * \return This function return 0 if ok, 1 if canvas or texture are missing. 177 */ 178 int caca_fill_triangle_textured(caca_canvas_t *cv, 179 int x1, int y1, 180 int x2, int y2, 181 int x3, int y3, 182 float u1, float v1, 183 float u2, float v2, 184 float u3, float v3, 185 caca_canvas_t *tex) 186 { 187 188 #define SWAP_F(a, b) {float c = a; a = b; b = c; } 189 190 /* (very) Naive and 191 * (very) floatbased affine and 192 * (very) nonclipped and 193 * (very) noncorrected triangle mapper 194 * 195 * Accepts arbitrary texture sizes 196 * Coordinates clamped to [0.0  1.0] (no repeat) 197 */ 198 if(!cv  !tex) return 1; 199 200 /* Bubblesort y1 <= y2 <= y3 */ 201 if(y1 > y2) 202 return caca_fill_triangle_textured(cv, 203 x2, y2, x1, y1, x3, y3, 204 u2, v2, u1, v1, u3, v3, 205 tex); 206 if(y2 > y3) 207 return caca_fill_triangle_textured(cv, 208 x1, y1, x3, y3, x2, y2, 209 u1, v1, u3, v3, u2, v2, 210 tex); 211 212 213 /* Clip texture coordinates */ 214 if(u1<0.0f) u1 = 0.0f; if(v1<0.0f) v1 = 0.0f; 215 if(u2<0.0f) u2 = 0.0f; if(v2<0.0f) v2 = 0.0f; 216 if(u3<0.0f) u3 = 0.0f; if(v3<0.0f) v3 = 0.0f; 217 if(u1>1.0f) u1 = 1.0f; if(v1>1.0f) v1 = 1.0f; 218 if(u2>1.0f) u2 = 1.0f; if(v2>1.0f) v2 = 1.0f; 219 if(u3>1.0f) u3 = 1.0f; if(v3>1.0f) v3 = 1.0f; 220 221 /* Convert relative tex coordinates to absolute */ 222 int tw = caca_get_canvas_width(tex); 223 int th = caca_get_canvas_height(tex); 224 225 u1*=(float)tw; u2*=(float)tw; u3*=(float)tw; 226 v1*=(float)th; v2*=(float)th; v3*=(float)th; 227 228 float x = (float) x1, y = (float) y1; 229 float y2y1 = y2y1; 230 float y3y1 = y3y1; 231 float y3y2 = y3y2; 232 233 /* Compute slopes, making sure we don't divide by zero */ 234 /* (in this case, we don't need the value anyway) */ 235 /* FIXME : only compute needed slopes */ 236 float sl12 = ((float)x2  x1) / (y2y1==0?1:y2y1); 237 float sl13 = ((float)x3  x1) / (y3y1==0?1:y3y1); 238 float sl23 = ((float)x3  x2) / (y3y2==0?1:y3y2); 239 240 float usl12 = (u2  u1) / (y2y1==0?1:y2y1); 241 float usl13 = (u3  u1) / (y3y1==0?1:y3y1); 242 float usl23 = (u3  u2) / (y3y2==0?1:y3y2); 243 float vsl12 = (v2  v1) / (y2y1==0?1:y2y1); 244 float vsl13 = (v3  v1) / (y3y1==0?1:y3y1); 245 float vsl23 = (v3  v2) / (y3y2==0?1:y3y2); 246 247 float xa = (float) x1, xb = (float) x1; 248 float ua = u1, ub = u1; 249 float va = v1, vb = v1; 250 float u, v; 251 252 int s = 0; 253 254 /* Top */ 255 for(y = y1 ; y < y2; y++) 256 { 257 258 if(xb < xa) { 259 SWAP_F(xb, xa); 260 SWAP_F(sl13, sl12); 261 SWAP_F(ua, ub); 262 SWAP_F(va, vb); 263 SWAP_F(usl13, usl12); 264 SWAP_F(vsl13, vsl12); 265 s=1; 266 } 267 268 float tus = (ub  ua) / (xb  xa); 269 float tvs = (vb  va) / (xb  xa); 270 v = va; u = ua; 271 272 /* scanline */ 273 for(x = xa ; x < xb; x++) 274 { 275 u+=tus; 276 v+=tvs; 277 /* FIXME: use caca_get_canvas_attrs / caca_get_canvas_chars */ 278 uint32_t attr = caca_get_attr(tex, u, v); 279 uint32_t c = caca_get_char(tex, u, v); 280 caca_set_attr(cv, attr); 281 caca_put_char(cv, x, y, c); 282 } 283 284 xa+=sl13; 285 xb+=sl12; 286 287 ua+=usl13; va+=vsl13; 288 ub+=usl12; vb+=vsl12; 289 } 290 291 if(s) 292 { 293 SWAP_F(xb, xa); 294 SWAP_F(sl13, sl12); 295 SWAP_F(ua, ub); 296 SWAP_F(va, vb); 297 SWAP_F(usl13, usl12); 298 SWAP_F(vsl13, vsl12); 299 } 300 301 302 /* Bottom */ 303 xb = (float) x2; 304 305 /* These variables are set by 'top' routine 306 * and are in an incorrect state if we only draw the bottom part 307 */ 308 if(y1 == y2) { 309 ua = u1; 310 ub = u2; 311 va = v1; 312 vb = v2; 313 } 314 315 for(y = y2 ; y < y3; y++) 316 { 317 if(xb <= xa) 318 { 319 SWAP_F(xb, xa); 320 SWAP_F(sl13, sl23); 321 SWAP_F(ua, ub); 322 SWAP_F(va, vb); 323 SWAP_F(usl13, usl23); 324 SWAP_F(vsl13, vsl23); 325 } 326 327 float tus = (ub  ua) / ((float)xb  xa); 328 float tvs = (vb  va) / ((float)xb  xa); 329 u = ua; v = va; 330 331 /* scanline */ 332 for(x = xa ; x < xb; x++) 333 { 334 u+=tus; 335 v+=tvs; 336 /* FIXME, can be heavily optimised */ 337 uint32_t attr = caca_get_attr(tex, u, v); 338 uint32_t c = caca_get_char(tex, u, v); 339 caca_set_attr(cv, attr); 340 caca_put_char(cv, x, y, c); 341 } 342 343 xa+=sl13; 344 xb+=sl23; 345 346 ua+=usl13; va+=vsl13; 347 ub+=usl23; vb+=vsl23; 348 } 349 350 return 0; 351 } 352 353 158 354 /* 159 355 * XXX: The following functions are aliases.
Note: See TracChangeset
for help on using the changeset viewer.