0

added a triangle drawing function, with interpolated color

This commit is contained in:
Aaron Griffith
2011-10-11 21:17:10 -04:00
parent 3a090f77f5
commit 80a3849a6c
2 changed files with 102 additions and 0 deletions

View File

@@ -358,3 +358,98 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
return dest;
}
/* draws a triangle on the destination image, multiplicatively!
* used for smooth lighting
* (excuse the ridiculous number of parameters!)
*
* Algorithm adapted from _Fundamentals_of_Computer_Graphics_
* by Peter Shirley, Michael Ashikhmin
* (or at least, the version poorly reproduced here:
* http://www.gidforums.com/t-20838.html )
*/
PyObject *
draw_triangle(PyObject *dest,
int x0, int y0,
unsigned char r0, unsigned char g0, unsigned char b0,
int x1, int y1,
unsigned char r1, unsigned char g1, unsigned char b1,
int x2, int y2,
unsigned char r2, unsigned char g2, unsigned char b2) {
/* destination image */
Imaging imDest;
/* ranges of pixels that are affected */
int xmin, xmax, ymin, ymax;
/* constant coefficients for alpha, beta, gamma */
int a12, a20, a01;
int b12, b20, b01;
int c12, c20, c01;
/* constant normalizers for alpha, beta, gamma */
float alpha_norm, beta_norm, gamma_norm;
/* temporary variables */
int tmp;
/* iteration variables */
int x, y;
imDest = imaging_python_to_c(dest);
if (!imDest)
return NULL;
/* check the various image modes, make sure they make sense */
if (strcmp(imDest->mode, "RGBA") != 0) {
PyErr_SetString(PyExc_ValueError,
"given destination image does not have mode \"RGBA\"");
return NULL;
}
/* set up draw ranges */
xmin = MIN(x0, MIN(x1, x2));
ymin = MIN(y0, MIN(y1, y2));
xmax = MAX(x0, MAX(x1, x2)) + 1;
ymax = MAX(y0, MAX(y1, y2)) + 1;
xmin = MAX(xmin, 0);
ymin = MAX(ymin, 0);
xmax = MIN(xmax, imDest->xsize);
ymax = MIN(ymax, imDest->ysize);
/* setup coefficients */
a12 = y1 - y2; b12 = x2 - x1; c12 = (x1 * y2) - (x2 * y1);
a20 = y2 - y0; b20 = x0 - x2; c20 = (x2 * y0) - (x0 * y2);
a01 = y0 - y1; b01 = x1 - x0; c01 = (x0 * y1) - (x1 * y0);
/* setup normalizers */
alpha_norm = 1.0f / ((a12 * x0) + (b12 * y0) + c12);
beta_norm = 1.0f / ((a20 * x1) + (b20 * y1) + c20);
gamma_norm = 1.0f / ((a01 * x2) + (b01 * y2) + c01);
/* iterate over the destination rect */
for (y = ymin; y < ymax; y++) {
UINT8 *out = (UINT8 *)imDest->image[y] + xmin * 4;
for (x = xmin; x < xmax; x++) {
float alpha, beta, gamma;
alpha = alpha_norm * ((a12 * x) + (b12 * y) + c12);
beta = beta_norm * ((a20 * x) + (b20 * y) + c20);
gamma = gamma_norm * ((a01 * x) + (b01 * y) + c01);
if (alpha >= 0 && beta >= 0 && gamma >= 0) {
unsigned int r = alpha * r0 + beta * r1 + gamma * r2;
unsigned int g = alpha * g0 + beta * g1 + gamma * g2;
unsigned int b = alpha * b0 + beta * b1 + gamma * b2;
*out = MULDIV255(*out, r, tmp); out++;
*out = MULDIV255(*out, g, tmp); out++;
*out = MULDIV255(*out, b, tmp); out++;
/* keep alpha the same */
out++;
} else {
/* skip */
out += 4;
}
}
}
return dest;
}

View File

@@ -51,6 +51,13 @@ PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
unsigned char sb, unsigned char sa,
PyObject *mask, int dx, int dy, int xsize, int ysize);
PyObject *draw_triangle(PyObject *dest,
int x0, int y0,
unsigned char r0, unsigned char g0, unsigned char b0,
int x1, int y1,
unsigned char r1, unsigned char g1, unsigned char b1,
int x2, int y2,
unsigned char r2, unsigned char g2, unsigned char b2);
/* forward declaration of RenderMode object */
typedef struct _RenderMode RenderMode;