Changeset 3987 for libcaca/trunk/caca
 Timestamp:
 Nov 21, 2009, 11:28:58 AM (10 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

libcaca/trunk/caca/triangle.c
r3926 r3987 1 /* 1 /* 2 2 * libcaca Colour ASCIIArt library 3 3 * Copyright (c) 20022006 Sam Hocevar <sam@zoy.org> … … 13 13 */ 14 14 15 /* 15 /* 16 16 * This file contains triangle drawing functions, both filled and outline. 17 17 */ … … 40 40 * \return This function always returns 0. 41 41 */ 42 int caca_draw_triangle(caca_canvas_t * cv, int x1, int y1, int x2, int y2,43 42 int caca_draw_triangle(caca_canvas_t * cv, int x1, int y1, int x2, int y2, 43 int x3, int y3, uint32_t ch) 44 44 { 45 45 caca_draw_line(cv, x1, y1, x2, y2, ch); … … 63 63 * \return This function always returns 0. 64 64 */ 65 int caca_draw_thin_triangle(caca_canvas_t * cv, int x1, int y1,66 65 int caca_draw_thin_triangle(caca_canvas_t * cv, int x1, int y1, 66 int x2, int y2, int x3, int y3) 67 67 { 68 68 caca_draw_thin_line(cv, x1, y1, x2, y2); … … 87 87 * \return This function always returns 0. 88 88 */ 89 int caca_fill_triangle(caca_canvas_t * cv, int x1, int y1, int x2, int y2,90 89 int caca_fill_triangle(caca_canvas_t * cv, int x1, int y1, int x2, int y2, 90 int x3, int y3, uint32_t ch) 91 91 { 92 92 int x, y, xmin, xmax, ymin, ymax; … … 94 94 95 95 /* Bubblesort y1 <= y2 <= y3 */ 96 if (y1 > y2)96 if (y1 > y2) 97 97 return caca_fill_triangle(cv, x2, y2, x1, y1, x3, y3, ch); 98 98 99 if (y2 > y3)99 if (y2 > y3) 100 100 return caca_fill_triangle(cv, x1, y1, x3, y3, x2, y2, ch); 101 101 … … 112 112 ymax = y3 + 1 < cv>height ? y3 + 1 : cv>height; 113 113 114 if (ymin < y2)114 if (ymin < y2) 115 115 { 116 116 xa = x1 + sl21 * (ymin  y1); 117 117 xb = x1 + sl31 * (ymin  y1); 118 118 } 119 else if (ymin == y2)119 else if (ymin == y2) 120 120 { 121 121 xa = x2; 122 122 xb = (y1 == y3) ? x3 : x1 + sl31 * (ymin  y1); 123 123 } 124 else /* (ymin > y2) */124 else /* (ymin > y2) */ 125 125 { 126 126 xa = x3 + sl32 * (ymin  y3); … … 129 129 130 130 /* Rasterize our triangle */ 131 for (y = ymin; y < ymax; y++)131 for (y = ymin; y < ymax; y++) 132 132 { 133 133 /* Rescale xa and xb, recentering the division */ 134 if (xa < xb)134 if (xa < xb) 135 135 { 136 136 xx1 = (xa + 0x800) / 0x10000; … … 146 146 xmax = xx2 + 1 < cv>width ? xx2 + 1 : cv>width; 147 147 148 for (x = xmin; x < xmax; x++)148 for (x = xmin; x < xmax; x++) 149 149 caca_put_char(cv, x, y, ch); 150 150 … … 156 156 } 157 157 158 /* This function actually renders the triangle, 159 * but is not exported due to sam's pedantic will. */ 160 static int caca_fill_triangle_textured_l(caca_canvas_t *cv, 161 int x1, int y1, 162 int x2, int y2, 163 int x3, int y3, 164 caca_canvas_t *tex, 165 float u1, float v1, 166 float u2, float v2, 167 float u3, float v3) 168 158 /* This function actually renders the triangle, but is not exported due to 159 sam's pedantic will. */ 160 static int caca_fill_triangle_textured_l(caca_canvas_t * cv, 161 int x1, int y1, 162 int x2, int y2, 163 int x3, int y3, 164 caca_canvas_t * tex, 165 float u1, float v1, 166 float u2, float v2, 167 float u3, float v3) 169 168 { 170 169 uint32_t savedattr; 171 170 172 #define SWAP_F(a, b) {float c = a; a = b; b = c; } 173 174 /* (very) Naive and 175 * (very) floatbased affine and 176 * (very) nonclipped and 177 * (very) noncorrected triangle mapper 178 * 179 * Accepts arbitrary texture sizes 180 * Coordinates clamped to [0.0  1.0] (no repeat) 181 */ 182 if(!cv  !tex) return 1; 171 #define SWAP_F(a, b) {float c = a; a = b; b = c; } 172 173 /* (very) Naive and (very) floatbased affine and (very) nonclipped and 174 (very) noncorrected triangle mapper Accepts arbitrary texture sizes 175 Coordinates clamped to [0.0  1.0] (no repeat) */ 176 if (!cv  !tex) 177 return 1; 183 178 184 179 /* Bubblesort y1 <= y2 <= y3 */ 185 if (y1 > y2)186 return caca_fill_triangle_textured_l(cv, 180 if (y1 > y2) 181 return caca_fill_triangle_textured_l(cv, 187 182 x2, y2, x1, y1, x3, y3, 188 tex, 189 u2, v2, u1, v1, u3, v3); 190 if(y2 > y3) 191 return caca_fill_triangle_textured_l(cv, 183 tex, u2, v2, u1, v1, u3, v3); 184 if (y2 > y3) 185 return caca_fill_triangle_textured_l(cv, 192 186 x1, y1, x3, y3, x2, y2, 193 tex, 194 u1, v1, u3, v3, u2, v2); 187 tex, u1, v1, u3, v3, u2, v2); 195 188 196 189 savedattr = caca_get_attr(cv, 1, 1); 197 190 198 191 /* Clip texture coordinates */ 199 if(u1<0.0f) u1 = 0.0f; if(v1<0.0f) v1 = 0.0f; 200 if(u2<0.0f) u2 = 0.0f; if(v2<0.0f) v2 = 0.0f; 201 if(u3<0.0f) u3 = 0.0f; if(v3<0.0f) v3 = 0.0f; 202 if(u1>1.0f) u1 = 1.0f; if(v1>1.0f) v1 = 1.0f; 203 if(u2>1.0f) u2 = 1.0f; if(v2>1.0f) v2 = 1.0f; 204 if(u3>1.0f) u3 = 1.0f; if(v3>1.0f) v3 = 1.0f; 205 192 if (u1 < 0.0f) 193 u1 = 0.0f; 194 if (v1 < 0.0f) 195 v1 = 0.0f; 196 if (u2 < 0.0f) 197 u2 = 0.0f; 198 if (v2 < 0.0f) 199 v2 = 0.0f; 200 if (u3 < 0.0f) 201 u3 = 0.0f; 202 if (v3 < 0.0f) 203 v3 = 0.0f; 204 if (u1 > 1.0f) 205 u1 = 1.0f; 206 if (v1 > 1.0f) 207 v1 = 1.0f; 208 if (u2 > 1.0f) 209 u2 = 1.0f; 210 if (v2 > 1.0f) 211 v2 = 1.0f; 212 if (u3 > 1.0f) 213 u3 = 1.0f; 214 if (v3 > 1.0f) 215 v3 = 1.0f; 216 206 217 /* Convert relative tex coordinates to absolute */ 207 218 int tw = caca_get_canvas_width(tex); 208 219 int th = caca_get_canvas_height(tex); 209 210 u1*=(float)tw; u2*=(float)tw; u3*=(float)tw; 211 v1*=(float)th; v2*=(float)th; v3*=(float)th; 212 220 221 u1 *= (float)tw; 222 u2 *= (float)tw; 223 u3 *= (float)tw; 224 v1 *= (float)th; 225 v2 *= (float)th; 226 v3 *= (float)th; 227 213 228 int x, y; 214 float y2y1 = y2 y1;215 float y3y1 = y3 y1;216 float y3y2 = y3 y2;217 229 float y2y1 = y2  y1; 230 float y3y1 = y3  y1; 231 float y3y2 = y3  y2; 232 218 233 /* Compute slopes, making sure we don't divide by zero */ 219 234 /* (in this case, we don't need the value anyway) */ 220 235 /* FIXME : only compute needed slopes */ 221 float sl12 = ((float)x2  x1) / (y2y1 ==0?1:y2y1);222 float sl13 = ((float)x3  x1) / (y3y1 ==0?1:y3y1);223 float sl23 = ((float)x3  x2) / (y3y2 ==0?1:y3y2);224 225 float usl12 = (u2  u1) / (y2y1 ==0?1:y2y1);226 float usl13 = (u3  u1) / (y3y1 ==0?1:y3y1);227 float usl23 = (u3  u2) / (y3y2 ==0?1:y3y2);228 float vsl12 = (v2  v1) / (y2y1 ==0?1:y2y1);229 float vsl13 = (v3  v1) / (y3y1 ==0?1:y3y1);230 float vsl23 = (v3  v2) / (y3y2 ==0?1:y3y2);231 232 float xa = (float) x1, xb = (float)x1;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; 233 248 float ua = u1, ub = u1; 234 249 float va = v1, vb = v1; 235 250 float u, v; 236 251 237 252 int s = 0; 238 253 239 254 /* Top */ 240 for(y = y1 ; y < y2; y++) 241 { 242 243 if(xb < xa) { 244 SWAP_F(xb, xa); 255 for (y = y1; y < y2; y++) 256 { 257 258 if (xb < xa) 259 { 260 SWAP_F(xb, xa); 245 261 SWAP_F(sl13, sl12); 246 262 SWAP_F(ua, ub); 247 SWAP_F(va, vb); 263 SWAP_F(va, vb); 248 264 SWAP_F(usl13, usl12); 249 265 SWAP_F(vsl13, vsl12); 250 s =1;251 } 252 266 s = 1; 267 } 268 253 269 float tus = (ub  ua) / (xb  xa); 254 270 float tvs = (vb  va) / (xb  xa); 255 v = va; u = ua; 256 271 v = va; 272 u = ua; 273 257 274 /* scanline */ 258 for (x = xa; x < xb; x++)259 { 260 u +=tus;261 v +=tvs;262 /* FIXME: use caca_get_canvas_attrs / caca_get_canvas_chars 275 for (x = xa; x < xb; x++) 276 { 277 u += tus; 278 v += tvs; 279 /* FIXME: use caca_get_canvas_attrs / caca_get_canvas_chars */ 263 280 uint32_t attr = caca_get_attr(tex, u, v); 264 uint32_t c 281 uint32_t c = caca_get_char(tex, u, v); 265 282 caca_set_attr(cv, attr); 266 283 caca_put_char(cv, x, y, c); 267 284 } 268 269 xa+=sl13; 270 xb+=sl12; 271 272 ua+=usl13; va+=vsl13; 273 ub+=usl12; vb+=vsl12; 274 } 275 276 if(s) 285 286 xa += sl13; 287 xb += sl12; 288 289 ua += usl13; 290 va += vsl13; 291 ub += usl12; 292 vb += vsl12; 293 } 294 295 if (s) 277 296 { 278 297 SWAP_F(xb, xa); … … 283 302 SWAP_F(vsl13, vsl12); 284 303 } 285 286 304 305 287 306 /* Bottom */ 288 xb = (float) 289 290 /* These variables are set by 'top' routine 291 * and are in an incorrect state if we only draw the bottom part292 */293 if(y1 == y2){307 xb = (float)x2; 308 309 /* These variables are set by 'top' routine and are in an incorrect state 310 if we only draw the bottom part */ 311 if (y1 == y2) 312 { 294 313 ua = u1; 295 314 ub = u2; … … 297 316 vb = v2; 298 317 } 299 300 for (y = y2; y < y3; y++)301 { 302 if (xb <= xa)318 319 for (y = y2; y < y3; y++) 320 { 321 if (xb <= xa) 303 322 { 304 323 SWAP_F(xb, xa); … … 308 327 SWAP_F(usl13, usl23); 309 328 SWAP_F(vsl13, vsl23); 310 } 311 329 } 330 312 331 float tus = (ub  ua) / ((float)xb  xa); 313 332 float tvs = (vb  va) / ((float)xb  xa); 314 u = ua; v = va; 315 333 u = ua; 334 v = va; 335 316 336 /* scanline */ 317 for (x = xa; x < xb; x++)318 { 319 u +=tus;320 v +=tvs;321 /* FIXME, can be heavily optimised 337 for (x = xa; x < xb; x++) 338 { 339 u += tus; 340 v += tvs; 341 /* FIXME, can be heavily optimised */ 322 342 uint32_t attr = caca_get_attr(tex, u, v); 323 uint32_t c 343 uint32_t c = caca_get_char(tex, u, v); 324 344 caca_set_attr(cv, attr); 325 345 caca_put_char(cv, x, y, c); 326 346 } 327 347 328 xa+=sl13; 329 xb+=sl23; 330 331 ua+=usl13; va+=vsl13; 332 ub+=usl23; vb+=vsl23; 348 xa += sl13; 349 xb += sl23; 350 351 ua += usl13; 352 va += vsl13; 353 ub += usl23; 354 vb += vsl23; 333 355 } 334 356 … … 348 370 * \return This function return 0 if ok, 1 if canvas or texture are missing. 349 371 */ 350 int caca_fill_triangle_textured(caca_canvas_t * cv,372 int caca_fill_triangle_textured(caca_canvas_t * cv, 351 373 int coords[6], 352 caca_canvas_t * tex,353 float uv[6]){354 374 caca_canvas_t * tex, float uv[6]) 375 { 376 355 377 return caca_fill_triangle_textured_l(cv, 356 378 coords[0], coords[1], … … 358 380 coords[4], coords[5], 359 381 tex, 360 uv[0], uv[1], 361 uv[2], uv[3], 362 uv[4], uv[5]); 363 } 364 365 366 367 /* 382 uv[0], uv[1], 383 uv[2], uv[3], uv[4], uv[5]); 384 } 385 386 387 388 /* 368 389 * XXX: The following functions are aliases. 369 390 */ 370 391 371 392 int cucul_draw_triangle(cucul_canvas_t *, int, int, int, int, int, 372 int, uint32_t) CACA_ALIAS(caca_draw_triangle);373 int cucul_draw_thin_triangle(cucul_canvas_t *, int, int, int, int,374 int, int) CACA_ALIAS(caca_draw_thin_triangle);375 int cucul_fill_triangle(cucul_canvas_t *, int, int, int, int, int, 376 int, uint32_t) CACA_ALIAS(caca_fill_triangle);377 393 int, uint32_t) CACA_ALIAS(caca_draw_triangle); 394 int cucul_draw_thin_triangle(cucul_canvas_t *, int, int, int, int, 395 int, 396 int) CACA_ALIAS(caca_draw_thin_triangle); 397 int cucul_fill_triangle(cucul_canvas_t *, int, int, int, int, int, int, 398 uint32_t) CACA_ALIAS(caca_fill_triangle);
Note: See TracChangeset
for help on using the changeset viewer.