Annotation of researchv9/jerq/src/lib/jj/3d.c, revision 1.1

1.1     ! root        1: /*% 3cc -c %
        !             2:  * Fixed-point 3d coordinate transform routines for machines with
        !             3:  * 16 bit shorts and 32 bit longs.
        !             4:  */
        !             5: #include       <jerq.h>
        !             6: #include       <3d.h>
        !             7: #include       <font.h>
        !             8: static Hcoordl cur;
        !             9: static Point cen;
        !            10: static int wid;
        !            11: /*
        !            12:  * angles are scaled so that PI=>32768
        !            13:  * Since unsigned shorts are 16 bits, 2*PI overflows and yields
        !            14:  * 0, which seems appropriate.
        !            15:  */
        !            16: angle cvtangle[361]={
        !            17: 0,     182,    364,    546,    728,    910,    1092,   1274,
        !            18: 1456,  1638,   1820,   2002,   2184,   2366,   2548,   2730,
        !            19: 2912,  3094,   3276,   3458,   3640,   3822,   4004,   4187,
        !            20: 4369,  4551,   4733,   4915,   5097,   5279,   5461,   5643,
        !            21: 5825,  6007,   6189,   6371,   6553,   6735,   6917,   7099,
        !            22: 7281,  7463,   7645,   7827,   8009,   8192,   8374,   8556,
        !            23: 8738,  8920,   9102,   9284,   9466,   9648,   9830,   10012,
        !            24: 10194, 10376,  10558,  10740,  10922,  11104,  11286,  11468,
        !            25: 11650, 11832,  12014,  12196,  12379,  12561,  12743,  12925,
        !            26: 13107, 13289,  13471,  13653,  13835,  14017,  14199,  14381,
        !            27: 14563, 14745,  14927,  15109,  15291,  15473,  15655,  15837,
        !            28: 16019, 16201,  16384,  16566,  16748,  16930,  17112,  17294,
        !            29: 17476, 17658,  17840,  18022,  18204,  18386,  18568,  18750,
        !            30: 18932, 19114,  19296,  19478,  19660,  19842,  20024,  20206,
        !            31: 20388, 20571,  20753,  20935,  21117,  21299,  21481,  21663,
        !            32: 21845, 22027,  22209,  22391,  22573,  22755,  22937,  23119,
        !            33: 23301, 23483,  23665,  23847,  24029,  24211,  24393,  24576,
        !            34: 24758, 24940,  25122,  25304,  25486,  25668,  25850,  26032,
        !            35: 26214, 26396,  26578,  26760,  26942,  27124,  27306,  27488,
        !            36: 27670, 27852,  28034,  28216,  28398,  28580,  28763,  28945,
        !            37: 29127, 29309,  29491,  29673,  29855,  30037,  30219,  30401,
        !            38: 30583, 30765,  30947,  31129,  31311,  31493,  31675,  31857,
        !            39: 32039, 32221,  32403,  32585,  32768,  32950,  33132,  33314,
        !            40: 33496, 33678,  33860,  34042,  34224,  34406,  34588,  34770,
        !            41: 34952, 35134,  35316,  35498,  35680,  35862,  36044,  36226,
        !            42: 36408, 36590,  36772,  36955,  37137,  37319,  37501,  37683,
        !            43: 37865, 38047,  38229,  38411,  38593,  38775,  38957,  39139,
        !            44: 39321, 39503,  39685,  39867,  40049,  40231,  40413,  40595,
        !            45: 40777, 40960,  41142,  41324,  41506,  41688,  41870,  42052,
        !            46: 42234, 42416,  42598,  42780,  42962,  43144,  43326,  43508,
        !            47: 43690, 43872,  44054,  44236,  44418,  44600,  44782,  44964,
        !            48: 45147, 45329,  45511,  45693,  45875,  46057,  46239,  46421,
        !            49: 46603, 46785,  46967,  47149,  47331,  47513,  47695,  47877,
        !            50: 48059, 48241,  48423,  48605,  48787,  48969,  49152,  49334,
        !            51: 49516, 49698,  49880,  50062,  50244,  50426,  50608,  50790,
        !            52: 50972, 51154,  51336,  51518,  51700,  51882,  52064,  52246,
        !            53: 52428, 52610,  52792,  52974,  53156,  53339,  53521,  53703,
        !            54: 53885, 54067,  54249,  54431,  54613,  54795,  54977,  55159,
        !            55: 55341, 55523,  55705,  55887,  56069,  56251,  56433,  56615,
        !            56: 56797, 56979,  57161,  57344,  57526,  57708,  57890,  58072,
        !            57: 58254, 58436,  58618,  58800,  58982,  59164,  59346,  59528,
        !            58: 59710, 59892,  60074,  60256,  60438,  60620,  60802,  60984,
        !            59: 61166, 61348,  61531,  61713,  61895,  62077,  62259,  62441,
        !            60: 62623, 62805,  62987,  63169,  63351,  63533,  63715,  63897,
        !            61: 64079, 64261,  64443,  64625,  64807,  64989,  65171,  65353,
        !            62: 65536, 
        !            63: };
        !            64: static fract sintab[128+2]={
        !            65: 0,     201,    402,    603,    803,    1004,   1205,   1405,
        !            66: 1605,  1805,   2005,   2204,   2404,   2602,   2801,   2998,
        !            67: 3196,  3393,   3589,   3785,   3980,   4175,   4369,   4563,
        !            68: 4756,  4948,   5139,   5329,   5519,   5708,   5896,   6083,
        !            69: 6269,  6455,   6639,   6822,   7005,   7186,   7366,   7545,
        !            70: 7723,  7900,   8075,   8249,   8423,   8594,   8765,   8934,
        !            71: 9102,  9268,   9434,   9597,   9759,   9920,   10079,  10237,
        !            72: 10393, 10548,  10701,  10853,  11002,  11150,  11297,  11442,
        !            73: 11585, 11726,  11866,  12003,  12139,  12273,  12406,  12536,
        !            74: 12665, 12791,  12916,  13038,  13159,  13278,  13395,  13510,
        !            75: 13622, 13733,  13842,  13948,  14053,  14155,  14255,  14353,
        !            76: 14449, 14543,  14634,  14723,  14810,  14895,  14978,  15058,
        !            77: 15136, 15212,  15286,  15357,  15426,  15492,  15557,  15618,
        !            78: 15678, 15735,  15790,  15842,  15892,  15940,  15985,  16028,
        !            79: 16069, 16107,  16142,  16175,  16206,  16234,  16260,  16284,
        !            80: 16305, 16323,  16339,  16353,  16364,  16372,  16379,  16382,
        !            81: 16384, 16382,  
        !            82: };
        !            83: fract isin(x)
        !            84: register angle x;
        !            85: {
        !            86:        register fract a, b;
        !            87:        register i, f=0;
        !            88:        if(x>=PI){
        !            89:                x-=PI;
        !            90:                f=1;
        !            91:        }
        !            92:        if(x>PI/2)
        !            93:                x=PI-x;
        !            94:        i=x>>7;
        !            95:        a=sintab[i];
        !            96:        b=sintab[i+1]-a;
        !            97:        i=x&0177;
        !            98:        a+=(b*i+64)/128;
        !            99:        return(f?-a:a);
        !           100: }
        !           101: fract icos(x)
        !           102: register angle x;
        !           103: {
        !           104:        return(isin(x+PI/2));
        !           105: }
        !           106: long isqrt(a)
        !           107: register long a;
        !           108: {
        !           109:        register long x, y;
        !           110:        if(a<=0)return(0);
        !           111:        for(y=a,x=1;y!=0;y>>=2,x<<=1);
        !           112:        while((y=(a/x+x)>>1)<x)x=y;
        !           113:        return(x);
        !           114: }
        !           115: #define        NSTACK  32
        !           116: Hcoord hcoord(x, y, z, w)
        !           117: fract x, y, z, w;
        !           118: {
        !           119:        Hcoord r;
        !           120:        r.x=x;
        !           121:        r.y=y;
        !           122:        r.z=z;
        !           123:        r.w=w;
        !           124:        return(r);
        !           125: }
        !           126: matrix stack3[NSTACK]={
        !           127:        ONE,0,0,0,
        !           128:        0,ONE,0,0,
        !           129:        0,0,ONE,0,
        !           130:        0,0,0,ONE,
        !           131: };
        !           132: matrix *sp3=stack3;            /* matrix stack pointer */
        !           133: /*
        !           134:  * Initialize the matrix stack.
        !           135:  * v is the viewport into which to map the image.  (d/s) is the distance to the
        !           136:  * screen, whose half-width is 1. (equivalently, d is the distance to a screen of
        !           137:  * half-size s.)
        !           138:  */
        !           139: Bitmap *viewport;
        !           140: init3(v, d, s)
        !           141: Bitmap *v;
        !           142: {
        !           143:        sp3=stack3;
        !           144:        ident(*sp3);
        !           145:        (*sp3)[0][0]=(*sp3)[2][2]=d;
        !           146:        (*sp3)[1][1]=s;
        !           147:        (*sp3)[3][3]=s;
        !           148:        viewport=v;
        !           149:        cen=div(add(v->rect.origin, v->rect.corner), 2);
        !           150:        wid=min(v->rect.corner.x-v->rect.origin.x,
        !           151:                v->rect.corner.y-v->rect.origin.y)/2;
        !           152: }
        !           153: /*
        !           154:  * Push a copy of the top of the matrix stack onto the stack
        !           155:  */
        !           156: push3(){
        !           157:        register i, j;
        !           158:        ;if(sp3==stack3+NSTACK-1)
        !           159:                return(-1);
        !           160:        for(i=0;i!=4;i++) for(j=0;j!=4;j++)
        !           161:                sp3[1][i][j]=sp3[0][i][j];
        !           162:        sp3++;
        !           163:        return(0);
        !           164: }
        !           165: /*
        !           166:  * pop the top matrix off the stack
        !           167:  */
        !           168: pop3(){
        !           169:        if(sp3==stack3)
        !           170:                return(-1);
        !           171:        --sp3;
        !           172:        return(0);
        !           173: }
        !           174: /*
        !           175:  * Multiply the top matrix on the stack by rotation of angle theta about
        !           176:  * the given axis.
        !           177:  */
        !           178: rot3(theta, axis)
        !           179: angle theta;
        !           180: {
        !           181:        rotsc3(isin(theta), icos(theta), axis);
        !           182: }
        !           183: /*
        !           184:  * rotate, given the sin and cosine of the rotation angle.
        !           185:  */
        !           186: rotsc3(s, c, axis)
        !           187: short s, c;
        !           188: {
        !           189:        matrix m;
        !           190:        register i=(axis+1)%3, j=(axis+2)%3;
        !           191:        ident(m);
        !           192:        m[i][i] = c;
        !           193:        m[i][j] = -s;
        !           194:        m[j][i] = s;
        !           195:        m[j][j] = c;
        !           196:        xform3(m);
        !           197: }
        !           198: /*
        !           199:  * Scale by a factor of [xyz]/w about axis [xyz]
        !           200:  */
        !           201: scale3(p)
        !           202: Hcoord p;
        !           203: {
        !           204:        matrix m;
        !           205:        ident(m);
        !           206:        m[0][0]=p.x;
        !           207:        m[1][1]=p.y;
        !           208:        m[2][2]=p.z;
        !           209:        m[3][3]=p.w;
        !           210:        xform3(m);
        !           211: }
        !           212: /*
        !           213:  * translate by (dx/dw, dy/dw, dz/dw)
        !           214:  */
        !           215: tran3(p)
        !           216: Hcoord p;
        !           217: {
        !           218:        matrix m;
        !           219:        ident(m);
        !           220:        m[0][0]=p.w;
        !           221:        m[1][1]=p.w;
        !           222:        m[2][2]=p.w;
        !           223:        m[3][3]=p.w;
        !           224:        m[0][3]=p.x;
        !           225:        m[1][3]=p.y;
        !           226:        m[2][3]=p.z;
        !           227:        xform3(m);
        !           228: }
        !           229: /*
        !           230:  * Store an identity matrix in m
        !           231:  */
        !           232: ident(m)
        !           233: matrix m;
        !           234: {
        !           235:        register fract *s = &m[0][0];
        !           236:        *s++=ONE;*s++=0;*s++=0;*s++=0;
        !           237:        *s++=0;*s++=ONE;*s++=0;*s++=0;
        !           238:        *s++=0;*s++=0;*s++=ONE;*s++=0;
        !           239:        *s++=0;*s++=0;*s++=0;*s++=ONE;
        !           240: }
        !           241: /*
        !           242:  * Multiply the top of the matrix stack by m
        !           243:  */
        !           244: xform3(m)
        !           245: matrix m;
        !           246: {
        !           247:        register i, j, k;
        !           248:        long sum, max=0;
        !           249:        long tmp[4][4];
        !           250:        char buf[128];
        !           251: 
        !           252:        for(i=0;i!=4;i++) for(j=0;j!=4;j++){
        !           253:                sum=0;
        !           254:                for(k=0;k!=4;k++)
        !           255:                        sum+=(long)(*sp3)[i][k]*m[k][j];
        !           256:                tmp[i][j]=sum;
        !           257:                if(sum<0)
        !           258:                        sum = -sum;
        !           259:                if(sum>max)
        !           260:                        max=sum;
        !           261:        }
        !           262:        if((k = max/(ONE-1)) == 0) k = 1;
        !           263:        for(i=0;i!=4;i++) for(j=0;j!=4;j++)
        !           264:                (*sp3)[i][j]=tmp[i][j]/k;
        !           265: }
        !           266: long dot(a, b)
        !           267: Hcoord a, b;
        !           268: {
        !           269:        return((long)a.x*b.x+(long)a.y*b.y+(long)a.z*b.z);
        !           270: }
        !           271: Hcoord unitize(a)
        !           272: Hcoord a;
        !           273: {
        !           274:        short l=isqrt(dot(a, a));
        !           275:        Hcoord v;
        !           276:        if(l==0){
        !           277:                v=a;
        !           278:                v.w=0;
        !           279:        }
        !           280:        else{
        !           281:                if(a.w<0) l = -l;
        !           282:                v.x=muldiv(a.x, ONE, l);
        !           283:                v.y=muldiv(a.y, ONE, l);
        !           284:                v.z=muldiv(a.z, ONE, l);
        !           285:                v.w=ONE;
        !           286:        }
        !           287:        return(v);
        !           288: }
        !           289: Hcoord cross(a, b)
        !           290: Hcoord a, b;
        !           291: {
        !           292:        Hcoord r;
        !           293:        r.x=((long)a.y*b.z-(long)a.z*b.y)/ONE;
        !           294:        r.y=((long)a.z*b.x-(long)a.x*b.z)/ONE;
        !           295:        r.z=((long)a.x*b.y-(long)a.y*b.x)/ONE;
        !           296:        r.w=ONE;
        !           297:        return(r);
        !           298: }
        !           299: /*
        !           300:  * multiply the top of the maxrix stack by a view-pointing transformation
        !           301:  * with the eyepoint at e, looking in direction (lx, ly, lz),
        !           302:  * with up direction (ux, uy, uz)
        !           303:  */
        !           304: look3(e, l, u)
        !           305: Hcoord e, l, u;
        !           306: {
        !           307:        matrix m;
        !           308:        fract len;
        !           309:        Hcoord r;
        !           310: 
        !           311:        /*printf("look3(e=(%d,%d,%d,%d), l=(%d,%d,%d,%d), u=(%d,%d,%d,%d))\n",
        !           312:                e.x,e.y,e.z,e.w,l.x,l.y,l.z,l.w,u.x,u.y,u.z,u.w);*/
        !           313:        l=unitize(l);
        !           314:        if(l.w==0){
        !           315:                l.y=ONE;
        !           316:                l.w=ONE;
        !           317:        }
        !           318:        /* Adjust u to be perpendicular to l */
        !           319:        u=unitize(u);
        !           320:        len=dot(u, l)/ONE;
        !           321:        u.x-=muldiv(len, l.x, ONE);
        !           322:        u.y-=muldiv(len, l.y, ONE);
        !           323:        u.z-=muldiv(len, l.z, ONE);
        !           324:        u=unitize(u);
        !           325:        if(u.w==0){
        !           326:                u.z=ONE;
        !           327:                u.w=ONE;
        !           328:        }
        !           329:        r=cross(l, u);
        !           330:        /*printf("r=(%d,%d,%d,%d), l=(%d,%d,%d,%d), u=(%d,%d,%d,%d))\n",
        !           331:                r.x,r.y,r.z,r.w,l.x,l.y,l.z,l.w,u.x,u.y,u.z,u.w);*/
        !           332:        /* make the matrix to transform from (rlu) space to (xyz) space */
        !           333:        ident(m);
        !           334:        m[0][0]=r.x; m[0][1]=r.y; m[0][2]=r.z;
        !           335:        m[1][0]=l.x; m[1][1]=l.y; m[1][2]=l.z;
        !           336:        m[2][0]=u.x; m[2][1]=u.y; m[2][2]=u.z;
        !           337:        xform3(m);
        !           338:        tran3(hcoord(e.x, e.y, e.z, -e.w));
        !           339: }
        !           340: Hcoordl xformp(p)
        !           341: Hcoord p;
        !           342: {
        !           343:        Hcoordl r;
        !           344:        r.x=(long)(*sp3)[0][0]*p.x+(long)(*sp3)[0][1]*p.y
        !           345:                +(long)(*sp3)[0][2]*p.z+(long)(*sp3)[0][3]*p.w;
        !           346:        r.y=(long)(*sp3)[1][0]*p.x+(long)(*sp3)[1][1]*p.y
        !           347:                +(long)(*sp3)[1][2]*p.z+(long)(*sp3)[1][3]*p.w;
        !           348:        r.z=(long)(*sp3)[2][0]*p.x+(long)(*sp3)[2][1]*p.y
        !           349:                +(long)(*sp3)[2][2]*p.z+(long)(*sp3)[2][3]*p.w;
        !           350:        r.w=(long)(*sp3)[3][0]*p.x+(long)(*sp3)[3][1]*p.y
        !           351:                +(long)(*sp3)[3][2]*p.z+(long)(*sp3)[3][3]*p.w;
        !           352:        return(r);
        !           353: }
        !           354: move3(p)
        !           355: Hcoord p;
        !           356: {
        !           357:        cur=xformp(p);
        !           358:        /*printf("move3(%d,%d,%d,%d)\n", p.x, p.y, p.z, p.w);*/
        !           359: }
        !           360: line3(p)
        !           361: Hcoord p;
        !           362: {
        !           363:        Hcoordl new;
        !           364:        /*printf("line3(%d,%d,%d,%d)\n", p.x, p.y, p.z, p.w);*/
        !           365:        new=xformp(p);
        !           366:        clipanddraw(cur, new);
        !           367:        cur=new;
        !           368: }
        !           369: /*
        !           370:  * clip points to the viewing volume, then do perspective division
        !           371:  * and mapping to screen coordinates and draw lines.  We only clip against the
        !           372:  * eye plane, trusting segment to clip in x and z.  There probably should
        !           373:  * be some overflow precaution taken in the multiplication by n/d.
        !           374:  */
        !           375: int clip3scale = 0;
        !           376: 
        !           377: static clipanddraw(a, b)
        !           378: Hcoordl a, b;
        !           379: {
        !           380:        Point A, B;
        !           381:        Hcoordl t;
        !           382:        int clip=0;
        !           383:        long n, d;
        !           384:        long m;
        !           385:        long as, bs;
        !           386: #define                OV      (32767)         /* 2**(15.5) */
        !           387:        /*
        !           388:         * we clip against the plane p=(0,1,0,-1)  [this corresponds
        !           389:         * to the euclidean plane y=1.  This is picked rather than y=0
        !           390:         * to avoid a divide check in the perspective divide]
        !           391:         * First we check to see if one endpoint is on each side of the plane.
        !           392:         * and if necessary switch them so that a is behind and b is in front.
        !           393:         * then we replace a by a+(b-a)*n/d, where p.(a+(b-a)*n/d)=0
        !           394:         * i.e. a.y+(b.y-a.y)*n/d-a.w-(b.w-a.w)*n/d=0
        !           395:         *      (b.y-a.y-b.w+a.w)*n/d=a.w-a.y
        !           396:         *      n/d=(a.w-a.y)/(b.y-a.y-b.w+a.w)
        !           397:         */
        !           398:        /*printf("clipanddraw(a=(%d,%d,%d,%d), b=(%d,%d,%d,%d)\n",
        !           399:                a.x,a.y,a.z,a.w,b.x,b.y,b.z,b.w);*/
        !           400:        if(a.w>0?a.y<a.w:a.y>a.w)       /* eqv. a.y/a.w<1, but avoids divide */
        !           401:                clip++;
        !           402:        if(b.w>0?b.y<b.w:b.y>b.w){
        !           403:                if(clip)                /* both points behind y=1 plane */
        !           404:                {
        !           405:                        /*printf("clipped out of existence\n");*/
        !           406:                        return;
        !           407:                }
        !           408:                t=a;
        !           409:                a=b;
        !           410:                b=t;
        !           411:                clip++;
        !           412:        }
        !           413:        /* check for overflow */
        !           414:        m = max(max(abs(a.x), abs(a.y)), max(abs(a.z), abs(b.x)));
        !           415:        m = max(m, max(max(abs(b.y), abs(b.z)), max(abs(a.w), abs(b.w))));
        !           416:        if(m > OV)
        !           417:        {
        !           418:                m = (m+OV-1)/OV;
        !           419:                a.x /= m;
        !           420:                a.y /= m;
        !           421:                a.z /= m;
        !           422:                a.w /= m;
        !           423:                b.x /= m;
        !           424:                b.y /= m;
        !           425:                b.z /= m;
        !           426:                b.w /= m;
        !           427:        }
        !           428:        if(clip){
        !           429:                n=a.w-a.y;
        !           430:                d=b.y-a.y-b.w+a.w;
        !           431:                if(d==0)                        /* never happens? */
        !           432:                        return;
        !           433:                a.x+=(b.x-a.x)*n/d;
        !           434:                a.y+=(b.y-a.y)*n/d;
        !           435:                a.z+=(b.z-a.z)*n/d;
        !           436:                a.w+=(b.w-a.w)*n/d;     /* don't use w below */
        !           437:                /*printf("clipped to a=(%d,%d,%d,%d), b=(%d,%d,%d,%d)\n",
        !           438:                        a.x,a.y,a.z,a.w,b.x,b.y,b.z,b.w);*/
        !           439:        }
        !           440:        if(clip3scale)
        !           441:        {
        !           442:                as = a.w*clip3scale;
        !           443:                bs = b.w*clip3scale;
        !           444:        }
        !           445:        else
        !           446:        {
        !           447:                as = a.y;
        !           448:                bs = b.y;
        !           449:        }
        !           450:        A=add(Pt((short)muldiv(a.x, wid, as), (short)muldiv(-a.z, wid, as)), cen);
        !           451:        B=add(Pt((short)muldiv(b.x, wid, bs), (short)muldiv(-b.z, wid, bs)), cen);
        !           452:        segment(viewport, A, B, F_OR);
        !           453:        /*printf("---->drew points (%d,%d) - (%d,%d)\n", A.x, A.y, B.x, B.y);*/
        !           454: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.