polygon3d(3)

NAME
polygon3d, polygon3d_f

SYNOPSIS
#include <allegro.h>

void polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[]); void polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[]);

DESCRIPTION
Draw 3d polygons onto the specified bitmap, using the specified rendering mode. Unlike the regular polygon() function, these routines don't support concave or self-intersecting shapes, and they can't draw onto mode-X screen bitmaps (if you want to write 3d code in mode-X, draw onto a memory bitmap and then blit to the screen). The width and height of the texture bitmap must be powers of two, but can be different, eg. a 64x16 texture is fine, but a 17x3 one is not. The vertex count parameter (vc) should be followed by an array containing the appropriate number of pointers to vertex structures: polygon3d() uses the fixed point V3D structure, while polygon3d_f() uses the floating point V3D_f structure. These are defined as:
   typedef struct V3D
   {
      fixed x, y, z;       - position
      fixed u, v;          - texture map coordinates
      int c;               - color
   } V3D;

   typedef struct V3D_f
   {
      float x, y, z;       - position
      float u, v;          - texture map coordinates
      int c;               - color
   } V3D_f;

How the vertex data is used depends on the rendering mode: The x and y values specify the position of the vertex in 2d screen coordinates. The z value is only required when doing perspective correct texture mapping, and specifies the depth of the point in 3d world coordinates. The u and v coordinates are only required when doing texture mapping, and specify a point on the texture plane to be mapped on to this vertex. The texture plane is an infinite plane with the texture bitmap tiled across it. Each vertex in the polygon has a corresponding vertex on the texture plane, and the image of the resulting polygon in the texture plane will be mapped on to the polygon on the screen. We refer to pixels in the texture plane as texels. Each texel is a block, not just a point, and whole numbers for u and v refer to the top-left corner of a texel. This has a few implications. If you want to draw a rectangular polygon and map a texture sized 32x32 on to it, you would use the texture coordinates (0,0), (0,32), (32,32) and (32,0), assuming the vertices are specified in anticlockwise order. The texture will then be mapped perfectly on to the polygon. However, note that when we set u=32, the last column of texels seen on the screen is the one at u=31, and the same goes for v. This is because the coordinates refer to the top-left corner of the texels. In effect, texture coordinates at the right and bottom on the texture plane are exclusive. There is another interesting point here. If you have two polygons side by side sharing two vertices (like the two parts of folded piece of cardboard), and you want to map a texture across them seamlessly, the values of u and v on the vertices at the join will be the same for both polygons. For example, if they are both rectangular, one polygon may use (0,0), (0,32), (32,32) and (32,0), and the other may use (32,0), (32,32), (64,32), (64,0). This would create a seamless join. Of course you can specify fractional numbers for u and v to indicate a point part-way across a texel. In addition, since the texture plane is infinite, you can specify larger values than the size of the texture. This can be used to tile the texture several times across the polygon. The c value specifies the vertex color, and is interpreted differently by various rendering modes. The type parameter specifies the polygon rendering mode, and can be any of the values: POLYTYPE_FLAT: A simple flat shaded polygon, taking the color from the c value of the first vertex. This polygon type is affected by the drawing_mode() function, so it can be used to render XOR or translucent polygons. POLYTYPE_GCOL: A single-color gouraud shaded polygon. The colors for each vertex are taken from the c value, and interpolated across the polygon. This is very fast, but will only work in 256-color modes if your palette contains a smooth gradient between the colors. In truecolor modes it interprets the color as a packed, display-format value as produced by the makecol() function. POLYTYPE_GRGB: A gouraud shaded polygon which interpolates RGB triplets rather than a single color. In 256-color modes this uses the global rgb_map table to convert the result to an 8-bit paletted color, so it must only be used after you have set up the RGB mapping table! The colors for each vertex are taken from the c value, which is interpreted as a 24-bit RGB triplet (0xFF0000 is red, 0x00FF00 is green, and 0x0000FF is blue). POLYTYPE_ATEX: An affine texture mapped polygon. This stretches the texture across the polygon with a simple 2d linear interpolation, which is fast but not mathematically correct. It can look ok if the polygon is fairly small or flat-on to the camera, but because it doesn't deal with perspective foreshortening, it can produce strange warping artifacts. To see what I mean, run test.exe and see what happens to the polygon3d() test when you zoom in very close to the cube. POLYTYPE_PTEX: A perspective-correct texture mapped polygon. This uses the z value from the vertex structure as well as the u/v coordinates, so textures are displayed correctly regardless of the angle they are viewed from. Because it involves division calculations in the inner texture mapping loop, this mode is a lot slower than POLYTYPE_ATEX, and it uses floating point so it will be very slow on anything less than a Pentium (even with an FPU, a 486 can't overlap floating point division with other integer operations like the Pentium can). POLYTYPE_ATEX_MASK: POLYTYPE_PTEX_MASK: Like POLYTYPE_ATEX and POLYTYPE_PTEX, but zero texture map pixels are skipped, allowing parts of the texture map to be transparent. POLYTYPE_ATEX_LIT: POLYTYPE_PTEX_LIT: Like POLYTYPE_ATEX and POLYTYPE_PTEX, but the global color_map table (for 256-color modes) or blender function (for non-MMX truecolor modes) is used to blend the texture with a light level taken from the c value in the vertex structure. This must only be used after you have set up the color mapping table or blender functions! POLYTYPE_ATEX_MASK_LIT: POLYTYPE_PTEX_MASK_LIT: Like POLYTYPE_ATEX_LIT and POLYTYPE_PTEX_LIT, but zero texture map pixels are skipped, allowing parts of the texture map to be transparent. POLYTYPE_ATEX_TRANS: POLYTYPE_PTEX_TRANS: Render translucent textures. All the general rules for drawing translucent things apply. However, these modes have a major limitation: they only work with memory bitmaps or linear frame buffers (not with banked frame buffers). Don't even try, they do not check and your program will die horribly (or at least draw wrong things). POLYTYPE_ATEX_MASK_TRANS: POLYTYPE_PTEX_MASK_TRANS: Like POLYTYPE_ATEX_TRANS and POLYTYPE_PTEX_TRANS, but zero texture map pixels are skipped. If the CPU_MMX flag of the cpu_capabilities global variable is set, the GRGB and truecolor *LIT routines will be optimised using MMX instructions. If the CPU_3DNOW flag is set, the truecolor PTEX*LIT routines will take advantage of the 3DNow! CPU extensions. Using MMX for *LIT routines has a side effect: normally (without MMX), these routines use the blender functions used also for other lighting functions, set with set_trans_blender() or set_blender_mode(). The MMX versions only use the RGB value passed to set_trans_blender() and do the linear interpolation themselves. Therefore a new set of blender functions passed to set_blender_mode() is ignored.

SEE ALSO
triangle3d(3), quad3d(3), polygon(3), clip3d(3), cpu_capabilities(3), excamera(3)