[gameprogrammer] Re: Scaling Object By Z axis in 2D

  • From: Gato <gato@xxxxxxxxxxxx>
  • To: gameprogrammer@xxxxxxxxxxxxx
  • Date: Sat, 21 May 2011 13:46:00 -0500

The easiest way to accomplish what I think you want to do would be to use, say, OpenGL, and let it do the scaling, occlusion and clipping. Not to mention it would be faster than a software implementation.


But, if you still want to go the software way or just for curiosity, using a 2D api in which you want to simulate a 3D positioning of sprites, and lacking a z-buffer, first you would need to sort the sprites according to their depth, and process them farthest to closest.

Actually you can use something as simple as bubble sort, because usually objects don't change depth so much with respect to each other from frame to frame, so bubble sort works really well.

Once you have the sprites sorted, you blit them starting from the one furthest away and proceeding form there. This is what is called the painter's algorithm: closer objects being painted on top of further objects.

Next, you need to determine the size of an object considering the distance from the camera. The apparent size varies proportionally to the inverse of the distance. That is:

scaling = (distance of projection plane from camera) / (distance of object from camera)

If you normalize and set the distance of the projection plane to 1, and put that as numerator, then whenever your sprites have a z=1 they will have their original size. for z>1 they would shrink and for z<1 they wold be larger. ie. scaling = 1/z

Finally you need to perform the actual blitting. I don't know what platform you'd use. If you can just tell it to scale your sprite to any size you specify, you're done. Otherwise you'll need to scale the sprite yourself:

Here I'll assume "source" and "dest" are bidimensional arrays which have the original sprite and the surface onto which you will blit (the screen, for example), respectively. Also, source_width and source_height are the dimensions of the source array. dest_width, and dest_height are the dimensions of the destination array. new_width and new_height are the dimensions of the (scaled) blitted rectangle. pos_x and pos_y are the point on the dest surface where you want the center of the blitted sprite.

What you want here is to fill the area on the screen corresponding to the scaled sprite with pixels taken from the original sprite. It would be something like:

// compute some values
scale = 1.0 / z;
new_height = source_height * scale;
new_width = source_width * scale;
inv_scale = inv_scale = 1.0 / scale;

// center the sprite about pos_x and pos_y
corner_x = int(pos_x - new_width * 0.5);
corner_y = int(pos_y - new_height * 0.5);

// blit
for (y = 0; y< new height; y++) {
    for (x = 0; x < new_width; x++) {
dest[y + corner_y][x + corner_x] = source[int(y * inv_scale)][int(x * inv_scale)];
    }
}

But that would be inefficient. For every pixel you're doing two float-to-int conversions plus 4 multiplications per pixel: the two explicit ones, plus one in each array access.

A better implementation would be, and assuming now your source and dest arrays are linear arrays -which is usually the case-:

...
s_stride = inv_scale;
for (y = 0; y< new height; y++) {
    d_idx = corner_x + (y + corner_y) * dest_width;
    s_idx = floor(y * inv_y_scale) * source_width;

    for (x = 0; x < new_width; x++) {
        dest[d_idx++] = source[int(s_idx)];
        s_idx += s_stride;
    }
}

I'm assuming here your pixels are one word size each (byte, int, whatever the word size of dest and source).

There are many issues that I didn't even touch, like clipping against the bounds of the dest array, or sub-pixel acurancy, or taking in consideration a padding sprites may have at the end of each line when stored in memory.

One more thing, a few years ago, I'd use fixed point math instead of floats, specially in the inner loop. Now I just use OpenGL and forget about it.


-Gato









On 05/21/2011 09:29 AM, Agha Usman Ahmed wrote:
Hi,


I am working on a 2D image where I have X and Y axis now I want to simulate Z axis by scaling the size of objects in image. but I am stuck with the calculation. I don't know how to scale the objects based on Z-Axis. I red this http://en.wikipedia.org/wiki/Transformation_matrix link but didn't proof very helpful.

Can anyone of you forward me to the right direction. I think I have successfully put my question on this email but if there is some thing missing please let me know .







Regards,

*Agha Usman Ahmed*
Sr . Software Engineer
Personal Blog <http://www.aghausman.net> | Official Blog <http://weblogs.asp.net/aghausman/default.aspx>



Other related posts: