%ffp /* title: Convex polygon drawing date: 2001-11-09 author: Martijn W. van der Lee / VanDerLee date id change ---------- ------ ------------------------------------------------- 2001-12-14 MWVDL Added per-vertex RGB information. Added per-vertex Alpha information. Updated todo and general meta stuff. description ----------------------------------------------------------------- This example demonstrates how to create polygons with FM. It uses the put/get buffer to store the vertices and the Tn buffers during rendering to store this info. t(0) - Canvas; if PIXEL any line crossed the location. t(1) - Alpha; the interpolated Alpha value at location. t2(0) - Red; the interpolated R value at location. t2(1) - Green; the interpolated G value at location. t2(2) - Blue; the interpolated B value at location. To do ----------------------------------------------------------------- - Import polygons and RGBA info from file. - Store per-vertex Z information in T[1]. After 3d transformation, depth can be stored in a buffer similar to the color buffer process, this data can be mixed with a global depth-buffer to do propper polygon clipping. Please note that this rapidly depletes the supply of buffers. Ideally the Z and RGB buffers may be mixed for gourraud shading, this may be used in combination with flatshading, though. There's currently no space both the required Z channels to implement this. Either use memory functions (rather inconvenient due to only ever having to write 1 pixel at a time) or abuse the pget/pset buffers. - Optimize the filling algo by bounding x and y to min/max in the edge drawing algo? - Study the possibility of using v1, v2 and vscale buffers; v1 contains the index of vertex 1, v2 of vertex 2, vscale would contain the "influence" of v1 in a scale of [0,255]. This method would limit the use of buffers to 4 at most due to enabling look-up of actual values. If we assume the first vertex to have a node index of 1, we could further limit the number of buffers to just 3. Downside is the requirement of a list of vertices, causing a future file input to be cached. A Z-depth buffer would still need it's own bufferspace. - Replace scl() function by manual code which can scale with identical begin- and end-points in source range. */ ForEveryTile: { const int BFR_X = 0; const int BFR_Y = 100; const int BFR_R = 200; const int BFR_G = 300; const int BFR_B = 400; const int BFR_A = 500; const int EMPTY = 0; const int PIXEL = 1; const int CH_CANVAS = 0; const int CH_ALPHA = 1; // Clear pixel canvas for(x = 0; x < X; ++x) for(y = 0; y < Y; ++y) tset(x, y, CH_CANVAS, EMPTY); // Define N-point convex polygon. // Remember; triangles are always convex by concept. // Negative values yield undefined results. // This stuff could be loaded from a file (hint!). // XXX, nnn YYY, nnn RRR, nnn GGG, nnn BBB, nnn AAA, nnn put( 50, 1); put( 10, 101); put(255, 201); put( 0, 301); put( 0, 401); put( 0, 501); put( 10, 2); put( 30, 102); put(200, 202); put(200, 302); put( 0, 402); put( 0, 502); put( 40, 3); put( 90, 103); put( 0, 203); put( 0, 303); put(255, 403); put( 0, 503); put( 80, 4); put( 80, 104); put(127, 204); put(127, 304); put(255, 404); put( 0, 504); put( 90, 5); put( 50, 105); put(255, 205); put(255, 305); put(255, 405); put(255, 505); m = 5; // Number of points // Draw edges for(i1 = 1; i1 <= m; ++i1) { const int i2 = (i1 % m) + 1; const int X1 = get(BFR_X + i1) * X / 100; const int Y1 = get(BFR_Y + i1) * Y / 100; const int R1 = get(BFR_R + i1); const int G1 = get(BFR_G + i1); const int B1 = get(BFR_B + i1); const int A1 = get(BFR_A + i1); const int X2 = get(BFR_X + i2) * X / 100; const int Y2 = get(BFR_Y + i2) * Y / 100; const int R2 = get(BFR_R + i2); const int G2 = get(BFR_G + i2); const int B2 = get(BFR_B + i2); const int A2 = get(BFR_A + i2); // Draw a line from (X1, Y1) to (X2, Y2) for(y = min(Y1, Y2); y <= max(Y1, Y2); ++y) { const int xx = ((y - Y1) * (X2 - X1) / (Y2 - Y1)) + X1; tset(xx, y, CH_CANVAS, PIXEL); tset(xx, y, CH_ALPHA, scl(y, Y1, Y2, A1, A2)); t2set(xx, y, 0, scl(y, Y1, Y2, R1, R2)); t2set(xx, y, 1, scl(y, Y1, Y2, G1, G2)); t2set(xx, y, 2, scl(y, Y1, Y2, B1, B2)); } } // Outerbound fill convex polygon for(y = 0; y < Y; ++y) { int b, e; for(b = 0; b < X && tget(b, y, CH_CANVAS) == EMPTY; ++b); for(e = X; e > 0 && tget(e, y, CH_CANVAS) == EMPTY; --e); // Scanline the line at Y-pos y if(b == e) // Single pixel line? -> fix for scl(). for(z = 0; z < 3; ++z) tset(b, y, z, mix(src(b, y, z), t2get(b, y, z), CH_ALPHA, 255)); else { const int a1 = tget(b, y, CH_ALPHA); const int a2 = tget(e, y, CH_ALPHA); for(z = 0; z < 3; ++z) { const int c1 = t2get(b, y, z); const int c2 = t2get(e, y, z); for(x = b; x <= e; ++x) pset(x, y, z, mix(src(x, y, z), scl(x, b, e, c1, c2), scl(x, b, e, a1, a2), 255)); } } } return true; }