3d coding question

hi all,

i’m in the process of developing a simple 3d game engine and at the moment
i’m using SDL to do the drawing. my question is: is SDL a good choice for
doing the drawing (not just straight blits)? for example, i’m sure there’s a
better way to implement a putpixel function than to draw a rectangle 1x1
pixel in size? what do you guys do for low-level drawing functions?

thanks in advance,
-Luke

Luke Bond wrote:

hi all,

i’m in the process of developing a simple 3d game engine and at the moment
i’m using SDL to do the drawing. my question is: is SDL a good choice for
doing the drawing (not just straight blits)? for example, i’m sure there’s a
better way to implement a putpixel function than to draw a rectangle 1x1
pixel in size? what do you guys do for low-level drawing functions?

You can lock a surface and gain direct access to its pixels with the
’pixels’ field. Look at the SDL docs; there is an example.
It’s generally a good idea to pick one or two common pixel formats to
support (16-bit 565, for instance) and let SDL sort the rest out with
its format emulation.

Here’s a simple linear texturemapper I wrote a while back. It’s
completely unoptimized (there’s no excuse for that multiplication in the
inner loop), but it’s an example of direct surface access. It only
supports 16-bit pixels, which is fairly reasonable these days.
You’d want to call SDL_LockSurface on target and texture before using
this function, and SDL_UnlockSurface on them afterwards.

void drawTexturedPoly16(SDL_Surface *target, SDL_Surface *texture, int
num_vertices, point2d_p tgt_vertices[], point2d_p tex_vertices[])
{
int i;
int top_index = 0, bottom_index = 0;
int left_index, right_index;
int next_left_index, next_right_index;
int tgt_row, tgt_final_row;
Sint32 tgt_left_x, tgt_right_x;
Sint32 tgt_left_xstep, tgt_right_xstep;
Sint32 tgt_left_xspan, tgt_right_xspan;
Sint32 tgt_left_yspan, tgt_right_yspan;

Sint32 tex_left_x, tex_left_y;
Sint32 tex_right_x, tex_right_y;
Sint32 tex_left_xstep, tex_right_xstep;
Sint32 tex_left_ystep, tex_right_ystep;
	
int strip_width;

Sint32 u, v, ustep, vstep;

Uint16 *tgt_memory, *tex_memory;

for (i = 0; i < num_vertices; i++) {
	if (tgt_vertices[i]->y < tgt_vertices[top_index]->y)
		top_index = i;
	if (tgt_vertices[i]->y > tgt_vertices[bottom_index]->y)
		bottom_index = i;
};

left_index = top_index;
right_index = top_index;
next_left_index = (top_index - 1);if (next_left_index < 0)

next_left_index += num_vertices;
next_right_index = (top_index + 1); if (next_right_index >=
num_vertices) next_right_index -= num_vertices;

tgt_row = tgt_vertices[top_index]->y;
tgt_final_row = tgt_vertices[bottom_index]->y;

tgt_left_x = tgt_vertices[top_index]->x << 16;
tgt_right_x = (tgt_vertices[top_index]->x << 16) + 65535;

tgt_left_xspan = tgt_vertices[next_left_index]->x -

tgt_vertices[left_index]->x;
tgt_right_xspan = tgt_vertices[next_right_index]->x -
tgt_vertices[right_index]->x;
tgt_left_yspan = tgt_vertices[next_left_index]->y -
tgt_vertices[left_index]->y;
if (tgt_left_yspan == 0) tgt_left_yspan = 1;
tgt_right_yspan = tgt_vertices[next_right_index]->y -
tgt_vertices[right_index]->y;
if (tgt_right_yspan == 0) tgt_right_yspan = 1;
tgt_left_xstep = (tgt_left_xspan << 16) / tgt_left_yspan;
tgt_right_xstep = (tgt_right_xspan << 16) / tgt_right_yspan;

tex_left_x = tex_vertices[left_index]->x << 16;
tex_right_x = tex_vertices[right_index]->x << 16;
tex_left_y = tex_vertices[left_index]->y << 16;
tex_right_y = tex_vertices[right_index]->y << 16;
tex_left_xstep = ((tex_vertices[next_left_index]->x -

tex_vertices[left_index]->x) << 16) / tgt_left_yspan;
tex_left_ystep = ((tex_vertices[next_left_index]->y -
tex_vertices[left_index]->y) << 16) / tgt_left_yspan;
tex_right_xstep = ((tex_vertices[next_right_index]->x -
tex_vertices[right_index]->x) << 16) / tgt_right_yspan;
tex_right_ystep = ((tex_vertices[next_right_index]->y -
tex_vertices[right_index]->y) << 16) / tgt_right_yspan;

while (tgt_row <= tgt_final_row) {
	
	/* Progress to the next left edge if necessary. */
	while (tgt_row >= tgt_vertices[next_left_index]->y) {

		left_index--; if (left_index < 0) left_index += num_vertices;
		next_left_index--; if (next_left_index < 0) next_left_index +=

num_vertices;

		tgt_left_xspan = tgt_vertices[next_left_index]->x -

tgt_vertices[left_index]->x;
tgt_left_yspan = tgt_vertices[next_left_index]->y -
tgt_vertices[left_index]->y;
if (tgt_left_yspan == 0) tgt_left_yspan = 1;
tgt_left_xstep = (tgt_left_xspan << 16) / tgt_left_yspan;

		tex_left_xstep = ((tex_vertices[next_left_index]->x -

tex_vertices[left_index]->x) << 16) / tgt_left_yspan;
tex_left_ystep = ((tex_vertices[next_left_index]->y -
tex_vertices[left_index]->y) << 16) / tgt_left_yspan;

		tgt_left_x = tgt_vertices[left_index]->x << 16;
		tex_left_x = tex_vertices[left_index]->x << 16;
		tex_left_y = tex_vertices[left_index]->y << 16;
		
		if (tgt_row >= tgt_final_row) break;
	};
	
	/* Progress to the next right edge if necessary. */
	while (tgt_row >= tgt_vertices[next_right_index]->y) {

		right_index++; if (right_index >= num_vertices) right_index -=

num_vertices;
next_right_index++; if (next_right_index >= num_vertices)
next_right_index -= num_vertices;

		tgt_right_xspan = tgt_vertices[next_right_index]->x -

tgt_vertices[right_index]->x;
tgt_right_yspan = tgt_vertices[next_right_index]->y -
tgt_vertices[right_index]->y;
if (tgt_right_yspan == 0) tgt_right_yspan = 1;
tgt_right_xstep = (tgt_right_xspan << 16) / tgt_right_yspan;

		tex_right_xstep = ((tex_vertices[next_right_index]->x -

tex_vertices[right_index]->x) << 16) / tgt_right_yspan;
tex_right_ystep = ((tex_vertices[next_right_index]->y -
tex_vertices[right_index]->y) << 16) / tgt_right_yspan;

		tgt_right_x = tgt_vertices[right_index]->x << 16;
		tex_right_x = tex_vertices[right_index]->x << 16;
		tex_right_y = tex_vertices[right_index]->y << 16;

		if (tgt_row >= tgt_final_row) break;
	};

	/* Draw the current scanline. */
	if (tgt_row >= 0 && tgt_row < target->h) {
		u = tex_left_x + 65536/2;		/* these are shifted by 16 */
		v = tex_left_y + 65536/2;
	
		strip_width = (tgt_right_x - tgt_left_x) >> 16;
		if (strip_width > 0) {
	
			ustep = (tex_right_x - tex_left_x) / strip_width;
			vstep = (tex_right_y - tex_left_y) / strip_width;
			
			tgt_memory = (Uint16 *)target->pixels + target->w * tgt_row +

(tgt_left_x >> 16);
tex_memory = (Uint16 *)texture->pixels;

			for (i = 0; i + (tgt_left_x >> 16) < 0 && i < strip_width; i++) {
				tgt_memory++;
				u += ustep;
				v += vstep;
			};
			
			if ((tgt_right_x >> 16) >= target->w)
				strip_width -= ((tgt_right_x >> 16) - target->w + 1);

			tex_memory = (Uint16 *)texture->pixels;

			/* FIXME: get that multiplication out of the loop */
			for (; i < strip_width; i++) {
				*tgt_memory = tex_memory[(texture->w * (v >> 16)) + (u >> 16)];
				tgt_memory++;
				u += ustep;
				v += vstep;
			};

		};
	};

	/* Advance to the next row. */
	tgt_row++;

	/* Calculate the next edge coordinates. */
	tgt_left_x += tgt_left_xstep;
	tgt_right_x += tgt_right_xstep;
	tex_left_x += tex_left_xstep;
	tex_left_y += tex_left_ystep;
	tex_right_x += tex_right_xstep;
	tex_right_y += tex_right_ystep;

};

}

-John

Mensaje citado por: Luke Bond :

hi all,

i’m in the process of developing a simple 3d game engine and at the
moment
i’m using SDL to do the drawing. my question is: is SDL a good
choice for
doing the drawing (not just straight blits)? for example, i’m sure
there’s
a
better way to implement a putpixel function than to draw a rectangle
1x1
pixel in size? what do you guys do for low-level drawing functions?

thanks in advance,
-Luke

Take a look at SGE.
It is in the library page.

Miguel

Luke Bond wrote:

hi all,

i’m in the process of developing a simple 3d game engine and at the moment
i’m using SDL to do the drawing. my question is: is SDL a good choice for
doing the drawing (not just straight blits)? for example, i’m sure there’s a
better way to implement a putpixel function than to draw a rectangle 1x1
pixel in size? what do you guys do for low-level drawing functions?

Well, you could blast pixels straight into the buffer…just be sure you
know what it is you’re squeezing in…–
Rafael R. Sevilla <@Rafael_R_Sevilla> +63 (2) 4342217
ICSM-F Development Team +63 (917) 4458925
University of the Philippines Diliman