cvs: gd /playground/gdimageshadedtriangle shadedtriangle.c

[email protected] ("Pierre-Alain Joye")
Newsgroups php.gd.cvs
Message-ID <cvspajoye1170857899@cvsserver>
pajoye		Wed Feb  7 14:18:19 2007 UTC

  Added files:                 
    /gd/playground/gdimageshadedtriangle	shadedtriangle.c 
  Log:
  - initial import
  
  

http://cvs.php.net/viewvc.cgi/gd/playground/gdimageshadedtriangle/shadedtriangle.c?view=markup&rev=1.1
Index: gd/playground/gdimageshadedtriangle/shadedtriangle.c
+++ gd/playground/gdimageshadedtriangle/shadedtriangle.c
/*
   Shaded Triangle for GD

	Implementation based on the 3DICA3 tutorial
	http://tfpsly.free.fr/Docs/3dIca/3dica3.htm
	License New BSD (See gd CVS for a copy of the license)
	(c) 2007 Pierre-Alain Joye
*/


#include <gd.h>
#include <stdio.h>
#include <string.h>

/* That will end in fast ops anyway (at least vc and gcc :) */
#define SWAP(a, b) do {\
  char c[sizeof(a)]; \
  memcpy((void *)&c, (void *)&a, sizeof(c)); \
  memcpy((void *)&a, (void *)&b, sizeof(a)); \
  memcpy((void *)&b, (void *)&c, sizeof(b)); \
} while (0)

#define GD_SHADED_FP 16

void _gdImageShadedHLine_FP(gdImagePtr im, int x1, int x2, int y,
	int c1_r, int c1_g, int c1_b,
	int c2_r, int c2_g, int c2_b)
{
	long d_r, d_g, d_b;
	long c_r, c_g, c_b;
#define RETAIN_SPATIAL_PRECISION 1
#if RETAIN_SPATIAL_PRECISION
    long dval;
#endif
    long x1_cast, x2_cast;
	int i;

	if(x1==x2) {
		 return;
	}

	if(x1>x2) {
		SWAP(x1, x2);
		SWAP(c1_r, c2_r);
		SWAP(c1_g, c2_g);
		SWAP(c1_b, c2_b);
	}

#if RETAIN_SPATIAL_PRECISION
    /* Compute color at rounded values */
    x1_cast = ((x1 + (1<<(GD_SHADED_FP-1))) >> GD_SHADED_FP) << GD_SHADED_FP;
    x2_cast = ((x2 + (1<<(GD_SHADED_FP-1))) >> GD_SHADED_FP) << GD_SHADED_FP;
    dval = (c2_r - c1_r);
    c1_r = dval * (x1_cast - x1) / (x2 - x1) + c1_r;
    c2_r = dval * (x2_cast - x2) / (x2 - x1) + c2_r;
    dval = (c2_g - c1_g);
    c1_g = dval * (x1_cast - x1) / (x2 - x1) + c1_g;
    c2_g = dval * (x2_cast - x2) / (x2 - x1) + c2_g;
    dval = (c2_b - c1_b);
    c1_b = dval * (x1_cast - x1) / (x2 - x1) + c1_b;
    c2_b = dval * (x2_cast - x2) / (x2 - x1) + c2_b;
#endif

	d_r = (c2_r - c1_r) / ((x2-x1) >> GD_SHADED_FP);
	d_g = (c2_g - c1_g) / ((x2-x1) >> GD_SHADED_FP);
	d_b = (c2_b - c1_b) / ((x2-x1) >> GD_SHADED_FP);

	c_r = c1_r;
	c_g = c1_g;
	c_b = c1_b;

    x1 = (x1 + (1<<(GD_SHADED_FP-1))) >> GD_SHADED_FP;
    x2 = (x2 + (1<<(GD_SHADED_FP-1))) >> GD_SHADED_FP;

	i=0;
	while((i++) < (x2 - x1)) {
#if RETAIN_SPATIAL_PRECISION
		gdImageSetPixel(im, x1 + i, y,
		gdTrueColorAlpha((c_r<0?0:c_r >> GD_SHADED_FP)&0xFF,
		(c_g<0?0:c_g >> GD_SHADED_FP)&0xFF,
		(c_b<0?0:c_b >> GD_SHADED_FP)&0xFF,0));
#else
		gdImageSetPixel(im, x1 + i, y,
		gdTrueColorAlpha((c_r >> GD_SHADED_FP)&0xFF,
		(c_g >> GD_SHADED_FP)&0xFF,
		(c_b >> GD_SHADED_FP)&0xFF,0));
#endif
		c_r += d_r;
		c_g += d_g;
		c_b += d_b;
	}
}

void gdImageShadedTriangle(gdImagePtr im, gdPoint v[3], int c[3])
{
	int x1, y1, x2, y2, x3, y3;
	int c1, c2, c3;

	/*
	 sl == scanline dc == delta color dx == delta x
	 */
	long dx12,dx13,dx23,sl_x1,sl_x2;
	long dc12_r, dc13_r, dc23_r, sl_c1_r, sl_c2_r;
	long dc12_g, dc13_g, dc23_g, sl_c1_g, sl_c2_g;
	long dc12_b, dc13_b, dc23_b, sl_c1_b, sl_c2_b;
	int i;

	x1 = v[0].x; y1 = v[0].y;
	x2 = v[1].x; y2 = v[1].y;
	x3 = v[2].x; y3 = v[2].y;
	c1 = c[0]; c2 = c[1]; c3 = c[2];

	/* Sort the vertices */
	if(y1 > y2) {
		SWAP(y1, y2);
		SWAP(x1, x2);
		SWAP(c1, c2);
	}

	if(y2 > y3) {
		SWAP(y2, y3);
		SWAP(x2, x3);
		SWAP(c2, c3);
	}

	if(y1 > y2) {
		SWAP(y2, y1);
		SWAP(x2, x1);
		SWAP(c2, c1);
	}

	if((i= y2 - y1) != 0) {
		dx12 = ((x2 - x1) << GD_SHADED_FP) / i;
		dc12_r = ((gdImageRed(im, c2) - gdImageRed(im, c1)) << GD_SHADED_FP) / i;
		dc12_g = ((gdImageGreen(im, c2) - gdImageGreen(im, c1)) << GD_SHADED_FP) / i;
		dc12_b = ((gdImageBlue(im, c2) - gdImageBlue(im, c1)) << GD_SHADED_FP) / i;
	} else {
		dx12 = 0;
		dc12_r = 0;
		dc12_g = 0;
		dc12_b = 0;
	}

	if((i = y3 - y1) != 0) {
		dx13 = ((x3-x1) << GD_SHADED_FP) / i;
		dc13_r = ((gdImageRed(im, c3) - gdImageRed(im, c1)) << GD_SHADED_FP) / i;
		dc13_g = ((gdImageGreen(im, c3) - gdImageGreen(im, c1)) << GD_SHADED_FP) / i;
		dc13_b = ((gdImageBlue(im, c3) - gdImageBlue(im, c1)) << GD_SHADED_FP) / i;
	} else {
		dx13 = 0;
		dc13_r = 0;
		dc13_g = 0;
		dc13_b = 0;
	}

	if((i = y3 - y2) != 0) {
		dx23 = ((x3-x2) << GD_SHADED_FP) / i;
		dc23_r = ((gdImageRed(im, c3) - gdImageRed(im, c2)) << GD_SHADED_FP) / i;
		dc23_g = ((gdImageGreen(im, c3) - gdImageGreen(im, c2)) << GD_SHADED_FP) / i;
		dc23_b = ((gdImageBlue(im, c3) - gdImageBlue(im, c2)) << GD_SHADED_FP) / i;
	} else {
		dx23 = 0;
		dc23_r = 0;
		dc23_g = 0;
		dc23_b = 0;
	}

	sl_x1 = sl_x2 = x1 << GD_SHADED_FP;
	sl_c1_r = sl_c2_r = gdImageRed(im, c1) << GD_SHADED_FP;
	sl_c1_g = sl_c2_g = gdImageGreen(im, c1) << GD_SHADED_FP;
	sl_c1_b = sl_c2_b = gdImageBlue(im, c1) << GD_SHADED_FP;

	for(i = y1; i < y2; i++) {
		_gdImageShadedHLine_FP(im,
			sl_x1, sl_x2, i,
			sl_c1_r, sl_c1_g, sl_c1_b,
			sl_c2_r, sl_c2_g, sl_c2_b
		);

		sl_x1 += dx13;
		sl_x2 += dx12;

		sl_c1_r += dc13_r;
		sl_c1_g += dc13_g;
		sl_c1_b += dc13_b;
		sl_c2_r += dc12_r;
		sl_c2_g += dc12_g;
		sl_c2_b += dc12_b;
	}

	sl_x2 = x2 << GD_SHADED_FP;
	sl_c2_r = gdImageRed(im, c2) << GD_SHADED_FP;
	sl_c2_g = gdImageGreen(im, c2) << GD_SHADED_FP;
	sl_c2_b = gdImageBlue(im, c2) << GD_SHADED_FP;

	for(i = y2; i < y3; i++) {
		_gdImageShadedHLine_FP(im,
		sl_x1, sl_x2, i,
		sl_c1_r, sl_c1_g, sl_c1_b,
		sl_c2_r, sl_c2_g, sl_c2_b
		);

		sl_x1+=dx13;
		sl_x2+=dx23;
		sl_c1_r += dc13_r;
		sl_c1_g += dc13_g;
		sl_c1_b += dc13_b;
		sl_c2_r += dc23_r;
		sl_c2_g += dc23_g;
		sl_c2_b += dc23_b;
	}
}

int main()
{
	gdImagePtr im;
	int error = 0;
	FILE *fp;

	gdPoint v[3];
	int c[3];

	v[0].x = 10;
	v[0].y = 10;
	c[0] = gdTrueColorAlpha(255, 0, 0, 0);

	v[1].x = 310;
	v[1].y = 10;
	c[1] = gdTrueColorAlpha(0, 255, 0, 0);

	v[2].x = 160;
	v[2].y = 270;
	c[2] = gdTrueColorAlpha(0, 0, 255, 0);

	im = gdImageCreateTrueColor(320, 280);

	gdImageShadedTriangle(im, v, c);


	fp = fopen("gouraud5.png", "wb");
 	gdImagePng(im,fp);
	fclose(fp);

 	gdImageDestroy(im);
	return error;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.