added a triangle drawing function, with interpolated color
This commit is contained in:
@@ -358,3 +358,98 @@ tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
|||||||
|
|
||||||
return dest;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ PyObject *alpha_over_wrap(PyObject *self, PyObject *args);
|
|||||||
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
PyObject *tint_with_mask(PyObject *dest, unsigned char sr, unsigned char sg,
|
||||||
unsigned char sb, unsigned char sa,
|
unsigned char sb, unsigned char sa,
|
||||||
PyObject *mask, int dx, int dy, int xsize, int ysize);
|
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 */
|
/* forward declaration of RenderMode object */
|
||||||
typedef struct _RenderMode RenderMode;
|
typedef struct _RenderMode RenderMode;
|
||||||
|
|||||||
Reference in New Issue
Block a user