www.pudn.com > fatmap2.zip > DRAW.CPP


 
/* 
 *      Drawing functions 
 * 
 *      This source is part of the fatmap2.txt document by 
 *      Mats Byggmastar, mri@penti.sit.fi 
 *      17.4.1997 Jakobstad, Finland 
 * 
 *      Companies with self respect are encouraged to contact me if 
 *      any of this code is to be used as part of a commercial product. 
 */ 
 
 
#include "misc.h" 
 
 
/* 
 *  Watcom float -> long conversion is very slow.      
 *  Therefore we do this with inline FPU assembler. 
 *  No fadd trick here though, just simple fistp. 
 */ 
 
static float Scale16 = 65536.0; 
 
// dst[0] = (long) (src[0] * 65536.0); 
// dst[1] = (long) (src[1] * 65536.0); 
 
void fist16two(long * dst, float * src); 
#pragma aux fist16two = \ 
    "   fld    dword [ebx]          "\ 
    "   fmul   dword [Scale16]      "\ 
    "   fld    dword [ebx+4]        "\ 
    "   fmul   dword [Scale16]      "\ 
    "   fxch   st(1)                "\ 
    "   fistp  dword [eax]          "\ 
    "   fistp  dword [eax+4]        "\ 
    parm [eax] [ebx] modify [8087] 
 
 
// *dst = (long) src; 
 
void fist(long * dst, double src); 
#pragma aux fist = \ 
    "   fistp  dword [eax]  "\ 
    parm [eax] [8087] modify [8087] 
 
 
inline int cliptest(vertexuvfloat * v) 
{ 
    int bits = 0; 
    if(v->y < TopClip)   bits |= TOP; 
    if(v->y > BotClip)   bits |= BOT; 
    if(v->x < LeftClip)  bits |= LEFT; 
    if(v->x > RightClip) bits |= RIGHT; 
    return bits; 
} 
 
void DrawFlatTriangle(vertexuvfloat * vtx, int color) 
{ 
    vertexuvfloat * v0 = vtx+0; 
    vertexuvfloat * v1 = vtx+1; 
    vertexuvfloat * v2 = vtx+2; 
 
    v0->visible = cliptest(v0); 
    v1->visible = cliptest(v1); 
    v2->visible = cliptest(v2); 
 
    int andbits = v0->visible & v1->visible & v2->visible; 
    if(andbits != 0) return;  
 
    int orbits  = v0->visible | v1->visible | v2->visible; 
 
    if((orbits & (TOP | BOT | LEFT | RIGHT)) == VISIBLE) { 
        static vertex v[3]; 
        fist16two(&v[0].x, &v0->x); 
        fist16two(&v[1].x, &v1->x); 
        fist16two(&v[2].x, &v2->x); 
        DrawFlatPoly(v, 3, color); 
    } 
    else { 
        static vertexclip vc[12], ** dst; 
        static vertex v[12]; 
        vc[0].x = v0->x; 
        vc[0].y = v0->y; 
        vc[2].u = 0.0;                      // We don't need u,v 
        vc[2].v = 0.0; 
        vc[0].visible = v0->visible; 
        vc[1].x = v1->x; 
        vc[1].y = v1->y; 
        vc[2].u = 0.0; 
        vc[2].v = 0.0; 
        vc[1].visible = v1->visible; 
        vc[2].x = v2->x; 
        vc[2].y = v2->y; 
        vc[2].u = 0.0; 
        vc[2].v = 0.0; 
        vc[2].visible = v2->visible; 
        int max = ClipUV(&dst, vc); 
        if(max < 3) return; 
 
        for(int n=0; nx); 
        } 
        DrawFlatPoly(v, max, color); 
    } 
} 
 
void DrawGouraudTriangle(vertexuvfloat * vtx) 
{ 
    vertexuvfloat * v0 = vtx+0; 
    vertexuvfloat * v1 = vtx+1; 
    vertexuvfloat * v2 = vtx+2; 
 
    v0->visible = cliptest(v0); 
    v1->visible = cliptest(v1); 
    v2->visible = cliptest(v2); 
 
    int andbits = v0->visible & v1->visible & v2->visible; 
    if(andbits != 0) return;  
 
    // We use u to hold the color intensity 
 
    double denom = (v0->x - v2->x) * (v1->y - v2->y) - 
                   (v1->x - v2->x) * (v0->y - v2->y); 
    if(denom == 0.0) return; 
    long didx; 
    fist(&didx, ((v0->u - v2->u) * (v1->y - v2->y) - 
                 (v1->u - v2->u) * (v0->y - v2->y)) / denom * 65536.0); 
 
    int orbits  = v0->visible | v1->visible | v2->visible; 
 
    if((orbits & (TOP | BOT | LEFT | RIGHT)) == VISIBLE) { 
        static vertexi v[3]; 
        fist16two(&v[0].x, &v0->x); 
        fist(&v[0].i, v0->u*65536.0); 
        fist16two(&v[1].x, &v1->x); 
        fist(&v[1].i, v1->u*65536.0); 
        fist16two(&v[2].x, &v2->x); 
        fist(&v[2].i, v2->u*65536.0); 
        DrawGouraudPoly(v, 3, didx); 
    } 
    else { 
        static vertexclip vc[12], ** dst; 
        static vertexi v[12]; 
        vc[0].x = v0->x; 
        vc[0].y = v0->y; 
        vc[0].u = v0->u; 
        vc[0].v = 0.0;                      // We don't need v 
        vc[0].visible = v0->visible; 
        vc[1].x = v1->x; 
        vc[1].y = v1->y; 
        vc[1].u = v1->u; 
        vc[1].v = 0.0; 
        vc[1].visible = v1->visible; 
        vc[2].x = v2->x; 
        vc[2].y = v2->y; 
        vc[2].u = v2->u; 
        vc[2].v = 0.0; 
        vc[2].visible = v2->visible; 
        int max = ClipUV(&dst, vc); 
        if(max < 3) return; 
 
        for(int n=0; nx); 
            fist(&v[n].i, dst[n]->u*65536.0); 
        } 
        DrawGouraudPoly(v, max, didx); 
    } 
} 
 
 
void DrawTextureTriangle(vertexuvfloat * vtx, char * bitmap) 
{ 
    vertexuvfloat * v0 = vtx+0; 
    vertexuvfloat * v1 = vtx+1; 
    vertexuvfloat * v2 = vtx+2; 
 
    v0->visible = cliptest(v0); 
    v1->visible = cliptest(v1); 
    v2->visible = cliptest(v2); 
 
    int andbits = v0->visible & v1->visible & v2->visible; 
    if(andbits != 0) return;  
 
    double denom = (v0->x - v2->x) * (v1->y - v2->y) - 
                   (v1->x - v2->x) * (v0->y - v2->y); 
    if(denom == 0.0) return; 
    double id = 1.0/denom * 65536.0; 
    long dudx, dvdx; 
    fist(&dudx, ((v0->u - v2->u) * (v1->y - v2->y) - 
                 (v1->u - v2->u) * (v0->y - v2->y)) * id); 
    fist(&dvdx, ((v0->v - v2->v) * (v1->y - v2->y) - 
                 (v1->v - v2->v) * (v0->y - v2->y)) * id); 
 
    int orbits  = v0->visible | v1->visible | v2->visible; 
 
    if((orbits & (TOP | BOT | LEFT | RIGHT)) == VISIBLE) { 
        static vertexuv v[3]; 
        fist16two(&v[0].x, &v0->x); 
        fist16two(&v[0].u, &v0->u); 
        fist16two(&v[1].x, &v1->x); 
        fist16two(&v[1].u, &v1->u); 
        fist16two(&v[2].x, &v2->x); 
        fist16two(&v[2].u, &v2->u); 
        DrawTexturePoly(v, 3, bitmap, dudx, dvdx); 
    } 
    else { 
        static vertexclip vc[12], ** dst; 
        static vertexuv v[12]; 
        vc[0].x = v0->x; 
        vc[0].y = v0->y; 
        vc[0].u = v0->u; 
        vc[0].v = v0->v; 
        vc[0].visible = v0->visible; 
        vc[1].x = v1->x; 
        vc[1].y = v1->y; 
        vc[1].u = v1->u; 
        vc[1].v = v1->v; 
        vc[1].visible = v1->visible; 
        vc[2].x = v2->x; 
        vc[2].y = v2->y; 
        vc[2].u = v2->u; 
        vc[2].v = v2->v; 
        vc[2].visible = v2->visible; 
        int max = ClipUV(&dst, vc); 
        if(max < 3) return; 
 
        for(int n=0; nx); 
            fist16two(&v[n].u, &dst[n]->u); 
        } 
        DrawTexturePoly(v, max, bitmap, dudx, dvdx); 
    } 
} 
 
void DrawArbitraryTextureTriangle(vertexuvfloat * vtx, char * bitmap, 
                                  int bitmapwidth) 
{ 
    vertexuvfloat * v0 = vtx+0; 
    vertexuvfloat * v1 = vtx+1; 
    vertexuvfloat * v2 = vtx+2; 
 
    v0->visible = cliptest(v0); 
    v1->visible = cliptest(v1); 
    v2->visible = cliptest(v2); 
 
    int andbits = v0->visible & v1->visible & v2->visible; 
    if(andbits != 0) return;  
 
    double denom = (v0->x - v2->x) * (v1->y - v2->y) - 
                   (v1->x - v2->x) * (v0->y - v2->y); 
    if(denom == 0.0) return; 
    double id = 1.0/denom * 65536.0; 
    long dudx, dvdx; 
    fist(&dudx, ((v0->u - v2->u) * (v1->y - v2->y) - 
                 (v1->u - v2->u) * (v0->y - v2->y)) * id); 
    fist(&dvdx, ((v0->v - v2->v) * (v1->y - v2->y) - 
                 (v1->v - v2->v) * (v0->y - v2->y)) * id); 
 
    int orbits  = v0->visible | v1->visible | v2->visible; 
 
    if((orbits & (TOP | BOT | LEFT | RIGHT)) == VISIBLE) { 
        static vertexuv v[3]; 
        fist16two(&v[0].x, &v0->x); 
        fist16two(&v[0].u, &v0->u); 
        fist16two(&v[1].x, &v1->x); 
        fist16two(&v[1].u, &v1->u); 
        fist16two(&v[2].x, &v2->x); 
        fist16two(&v[2].u, &v2->u); 
        DrawArbitraryTexturePoly(v, 3, bitmap, bitmapwidth, dudx, dvdx); 
    } 
    else { 
        static vertexclip vc[12], ** dst; 
        static vertexuv v[12]; 
        vc[0].x = v0->x; 
        vc[0].y = v0->y; 
        vc[0].u = v0->u; 
        vc[0].v = v0->v; 
        vc[0].visible = v0->visible; 
        vc[1].x = v1->x; 
        vc[1].y = v1->y; 
        vc[1].u = v1->u; 
        vc[1].v = v1->v; 
        vc[1].visible = v1->visible; 
        vc[2].x = v2->x; 
        vc[2].y = v2->y; 
        vc[2].u = v2->u; 
        vc[2].v = v2->v; 
        vc[2].visible = v2->visible; 
        int max = ClipUV(&dst, vc); 
        if(max < 3) return; 
 
        for(int n=0; nx); 
            fist16two(&v[n].u, &dst[n]->u); 
        } 
        DrawArbitraryTexturePoly(v, max, bitmap, bitmapwidth, dudx, dvdx); 
    } 
} 
 
void DrawTiledTextureTriangle(vertexuvfloat * vtx, char * bitmap) 
{ 
    vertexuvfloat * v0 = vtx+0; 
    vertexuvfloat * v1 = vtx+1; 
    vertexuvfloat * v2 = vtx+2; 
 
    v0->visible = cliptest(v0); 
    v1->visible = cliptest(v1); 
    v2->visible = cliptest(v2); 
 
    int andbits = v0->visible & v1->visible & v2->visible; 
    if(andbits != 0) return;  
 
    double denom = (v0->x - v2->x) * (v1->y - v2->y) - 
                   (v1->x - v2->x) * (v0->y - v2->y); 
    if(denom == 0.0) return; 
    double id = 1.0/denom * 65536.0; 
    long dudx, dvdx; 
    fist(&dudx, ((v0->u - v2->u) * (v1->y - v2->y) - 
                 (v1->u - v2->u) * (v0->y - v2->y)) * id); 
    fist(&dvdx, ((v0->v - v2->v) * (v1->y - v2->y) - 
                 (v1->v - v2->v) * (v0->y - v2->y)) * id); 
 
    int orbits  = v0->visible | v1->visible | v2->visible; 
 
    if((orbits & (TOP | BOT | LEFT | RIGHT)) == VISIBLE) { 
        static vertexuv v[3]; 
        fist16two(&v[0].x, &v0->x); 
        fist16two(&v[0].u, &v0->u); 
        fist16two(&v[1].x, &v1->x); 
        fist16two(&v[1].u, &v1->u); 
        fist16two(&v[2].x, &v2->x); 
        fist16two(&v[2].u, &v2->u); 
        DrawTiledTexturePoly(v, 3, bitmap, dudx, dvdx); 
    } 
    else { 
        static vertexclip vc[12], ** dst; 
        static vertexuv v[12]; 
        vc[0].x = v0->x; 
        vc[0].y = v0->y; 
        vc[0].u = v0->u; 
        vc[0].v = v0->v; 
        vc[0].visible = v0->visible; 
        vc[1].x = v1->x; 
        vc[1].y = v1->y; 
        vc[1].u = v1->u; 
        vc[1].v = v1->v; 
        vc[1].visible = v1->visible; 
        vc[2].x = v2->x; 
        vc[2].y = v2->y; 
        vc[2].u = v2->u; 
        vc[2].v = v2->v; 
        vc[2].visible = v2->visible; 
        int max = ClipUV(&dst, vc); 
        if(max < 3) return; 
 
        for(int n=0; nx); 
            fist16two(&v[n].u, &dst[n]->u); 
        } 
        DrawTiledTexturePoly(v, max, bitmap, dudx, dvdx); 
    } 
}