home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / prog-asm / talincod.lha / talincode.lha / patch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-06  |  11.5 KB  |  503 lines

  1. /* test program for catmull-rom bicubic splines. */
  2.  
  3. #include "exec/types.h"
  4. #include "intuition/intuition.h"
  5. #include <macros.h>
  6.  
  7. struct Library *IntuitionBase=NULL, *GfxBase=NULL;
  8. void *OpenLibrary();
  9.  
  10. struct Window *Window=NULL, *OpenWindow();
  11. struct Screen *Screen=NULL, *OpenScreen();
  12. struct RastPort *rp;                            /* rast port */
  13.  
  14. struct TmpRas TmpRas;
  15. struct AreaInfo AreaInfo;
  16. PLANEPTR TRBuf;
  17. UWORD AIBuf[20];
  18.  
  19. USHORT colors[32] = {
  20.     0x000,0xFFF,0x000,0x111,0x222,0x333,0x444,0x555,
  21.     0x666,0x777,0x888,0x999,0xAAA,0xBBB,0xCCC,0xDDD,
  22.     0xEEE,0xFFF,0xB86,0x963,0x740,0x400,0xD80,0x666,
  23.     0xDB8,0xABF,0xDB8,0xC96,0xB86,0xBA8,0xA00,0xC08
  24. };
  25.  
  26. struct NewScreen NewScreen = { 0,0,320,200, 5, 0,1, NULL, CUSTOMSCREEN, };
  27.  
  28. struct NewWindow back_ground =
  29. {    0,0,320,200, 0,1,
  30.     MENUPICK | MOUSEMOVE,
  31.     NOCAREREFRESH | ACTIVATE | SMART_REFRESH | BORDERLESS | REPORTMOUSE,
  32.     NULL,NULL,NULL,NULL,NULL,320,200,320,200,CUSTOMSCREEN
  33. };
  34.  
  35. #define DF3    ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ
  36.  
  37. struct IntuiText quit_tx = { 5,1,JAM2,4,1,NULL,(UBYTE *)"Exit" };
  38. struct MenuItem quit_mi = { NULL,0,20,190,10,DF3,0,(APTR)&quit_tx,0,'X' };
  39. struct Menu menu1 = { NULL, 1,0,56,10, MENUENABLED | MIDRAWN, "File", &quit_mi };
  40.  
  41. #define SCAT    goto exit_pgm;
  42.  
  43. struct Point {
  44.     WORD    x,y;
  45. };
  46.  
  47. typedef struct {
  48.     float        x,y,z;
  49. } Point3;
  50.  
  51. typedef struct {                            /* varying point                    */
  52.     Point3        p,du,dv;
  53. } Point3V;
  54.  
  55. Point3 control_hull[10][10];
  56. float m[4][4];                            /* spline basis weighting factors */
  57.  
  58. struct Point coord2[4];
  59.  
  60. extern UWORD misc_grid_data[4][8];
  61.  
  62. long color_x;
  63. short color = 30;
  64.  
  65. transform(Point3 *p, Point *s)
  66. {    s->x = 160 + (WORD)((p->x - p->y) * 60.0);
  67.     s->y = 260 - (WORD)((p->x + p->y + p->z*2.5) * 25.0);
  68. }
  69.  
  70. struct BitMap *bm_draw;
  71.  
  72. WORD    ustep = 1, vstep = 1;
  73.  
  74. calc_cardinal(float tension)
  75. {
  76.     m[0][0] = -tension;
  77.     m[0][1] = 2.0 - tension;
  78.     m[0][2] = tension - 2.0;
  79.     m[0][3] = tension;
  80.  
  81.     m[1][0] = 2*tension;
  82.     m[1][1] = tension - 3.0;
  83.     m[1][2] = 3.0 - 2.0*tension;
  84.     m[1][3] = -tension;
  85.  
  86.     m[2][0] = -tension;
  87.     m[2][1] = 0.0;
  88.     m[2][2] = tension;
  89.     m[2][3] = 0.0;
  90.  
  91.     m[3][0] = 0.0;
  92.     m[3][1] = 1.0;
  93.     m[3][2] = 0.0;
  94.     m[3][3] = 0.0;
  95. }
  96.  
  97. main()
  98. {    int i,j,k;
  99.  
  100.     if ((IntuitionBase = OpenLibrary("intuition.library",0)) == NULL) SCAT;
  101.     if ((GfxBase = OpenLibrary("graphics.library",0)) == NULL) SCAT;
  102.     if ((Screen = OpenScreen(&NewScreen)) == NULL) SCAT;
  103.     LoadRGB4(&(Screen->ViewPort),colors,32);
  104.  
  105.     back_ground.Screen = Screen;
  106.     if ((Window = OpenWindow(&back_ground)) == NULL) SCAT;
  107.     rp = Window->RPort;
  108.  
  109.     TRBuf = (void *)AllocRaster(320,200);
  110.     if (!TRBuf) SCAT;
  111.     InitTmpRas(&TmpRas,TRBuf,RASSIZE(320,200));
  112.     rp->TmpRas = &TmpRas;
  113.     InitArea(&AreaInfo,AIBuf,5);
  114.     rp->AreaInfo = &AreaInfo;
  115.  
  116.     SetMenuStrip(Window,&menu1);
  117.  
  118.     SetAPen(rp,1); SetRast(rp,0);
  119.     bm_draw = rp->BitMap;
  120.  
  121.     WaitBlit();
  122.  
  123.     calc_cardinal(0.5);
  124.  
  125.         /* initialize control points */
  126.  
  127.     for (i=0; i<8; i++)
  128.     {    for (j=0; j<8; j++)
  129.         {    control_hull[i][j].x = (float)i;
  130.             control_hull[i][j].y = (float)j;
  131.             control_hull[i][j].z = 0.0;
  132.         }
  133.     }
  134.  
  135.     control_hull[2][2].z = 0.9;
  136.     control_hull[2][3].z = 1.5;
  137.     control_hull[3][3].z = 0.5;
  138.     control_hull[3][4].z = -0.5;
  139.     control_hull[4][2].z = 0.7;
  140.  
  141.     for (i=3; i>=0; i--)
  142.     {    for (j=3; j>=0; j--) do_patch(i,j);
  143.     }
  144.  
  145.     for (;;)
  146.     {    struct IntuiMessage *message, *GetMsg();
  147.  
  148.         Wait(1 << Window->UserPort->mp_SigBit);
  149.  
  150.         while (message = GetMsg(Window->UserPort))
  151.         {    ULONG class; USHORT code;
  152.             class = message->Class;
  153.             code = message->Code;
  154.             ReplyMsg(message);
  155.  
  156.             if (class == MENUPICK && code != MENUNULL) SCAT;
  157.         }
  158.     }
  159. exit_pgm:
  160.     if (TRBuf) { FreeRaster(TRBuf,320,200); rp->TmpRas = NULL; rp->AreaInfo = NULL; }
  161.     if (Window){ ClearMenuStrip(Window); CloseWindow(Window); }
  162.     if (Screen) CloseScreen(Screen); 
  163.     if (GfxBase) CloseLibrary(GfxBase);
  164.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  165. }
  166.  
  167. typedef Point3        SplineBasis[4][4];
  168.  
  169. interpolate_points(i,j,u,v,p) WORD i,j; float u,v; Point3 *p;
  170. {    float uv0, uv1, uv2, uv3;
  171.  
  172.     uv0 = u * v;
  173.     uv1 = (1.0 - u) * v;
  174.     uv2 = (1.0 - u) * (1.0 - v);
  175.     uv3 = u * (1.0 - v);
  176.  
  177.         /* first point */
  178.  
  179.     p->x =  control_hull[i  ][j  ].x * uv0 + 
  180.             control_hull[i+1][j  ].x * uv1 + 
  181.             control_hull[i+1][j+1].x * uv2 + 
  182.             control_hull[i  ][j+1].x * uv3;
  183.  
  184.     p->y =  control_hull[i  ][j  ].y * uv0 + 
  185.             control_hull[i+1][j  ].y * uv1 + 
  186.             control_hull[i+1][j+1].y * uv2 + 
  187.             control_hull[i  ][j+1].y * uv3;
  188.  
  189.     p->z =  control_hull[i  ][j  ].z * uv0 + 
  190.             control_hull[i+1][j  ].z * uv1 + 
  191.             control_hull[i+1][j+1].z * uv2 + 
  192.             control_hull[i  ][j+1].z * uv3;
  193. }
  194.  
  195.     /* evaluate a spline at a particular (u,v) values. This function expects
  196.  
  197.         A SplineBasis array, which is a pre-computed combination of the
  198.         16 control points combined with the 4x4 Basis Function.
  199.  
  200.         This function returns the point, and the derivatives of that point
  201.             (one with respect to u, the other with respect to v), for the
  202.             given parameters.
  203.     */
  204.  
  205. spline_eval(SplineBasis *b,float u,float v,Point3 *p,WORD dflag)
  206. {    WORD    j;
  207.     float    u2 = u*u,                        /* u squared                        */
  208.             u3 = u2*u,                        /* u cubed                            */
  209.             v2 = v*v,                        /* v squared                        */
  210.             v3 = v2*v,                        /* v cubed                            */
  211.             du2 = u * 2.0,                    /* derivative of u squared            */
  212.             du3 = u*u*3.0,                    /* derivative of u cubed            */
  213.             dv2 = v * 2.0,                    /* derivative of v squared            */
  214.             dv3 = v*v*3.0;                    /* derivative of v cubed            */
  215.     Point3    *du = p + 1,                    /* derivatives                        */
  216.             *dv = p + 2;
  217.  
  218.     p->x = p->y = p->z = 0.0;                /* set point to zero                */
  219.     *du = *p;                                /* set derivatives to zero            */
  220.     *dv = *p;
  221.  
  222.     for (j=0; j<4; j++)                        /* iterate through Y control points */
  223.     {    Point3            sum,
  224.                         dsum;
  225.         Point3            *cpoint;
  226.         float            basis;
  227.  
  228.             /* calculate each of the four u-splines */
  229.             /* also calculate the derivative with respect to u */
  230.  
  231.         cpoint = &(*b)[j][3];                /* first row * u^0                    */
  232.  
  233.         sum.x = cpoint->x;
  234.         sum.y = cpoint->y;
  235.         sum.z = cpoint->z;
  236.  
  237.         cpoint = &(*b)[j][2];                /* second row * u^1                    */
  238.  
  239.         sum.x += u * cpoint->x;
  240.         sum.y += u * cpoint->y;
  241.         sum.z += u * cpoint->z;
  242.  
  243.         dsum.x = cpoint->x;
  244.         dsum.y = cpoint->y;
  245.         dsum.z = cpoint->z;
  246.  
  247.         cpoint = &(*b)[j][1];                /* third row * u^2                    */
  248.  
  249.         sum.x += u2 * cpoint->x;
  250.         sum.y += u2 * cpoint->y;
  251.         sum.z += u2 * cpoint->z;
  252.  
  253.         dsum.x += du2 * cpoint->x;
  254.         dsum.y += du2 * cpoint->y;
  255.         dsum.z += du2 * cpoint->z;
  256.  
  257.         cpoint = &(*b)[j][0];                /* fourth row * u^3                    */
  258.  
  259.         sum.x += u3 * cpoint->x;
  260.         sum.y += u3 * cpoint->y;
  261.         sum.z += u3 * cpoint->z;
  262.  
  263.         dsum.x += du3 * cpoint->x;
  264.         dsum.y += du3 * cpoint->y;
  265.         dsum.z += du3 * cpoint->z;
  266.  
  267. #if 0
  268.         cpoint = &(*b)[j][2];                /* second row * du/du (1.0)            */
  269.         cpoint = &(*b)[j][1];                /* third row * du^2/d2 (2u)            */
  270.         cpoint = &(*b)[j][0];                /* fourth row * du^3/du                */
  271. #endif
  272.             /* calculate a single vspline that runs across the four u-splines */
  273.  
  274.         basis = (m[3][j])  +
  275.                 (m[2][j] * v) +
  276.                 (m[1][j] * v2) +
  277.                 (m[0][j] * v3);
  278.  
  279.         p->x += basis * sum.x;
  280.         p->y += basis * sum.y;
  281.         p->z += basis * sum.z;
  282.  
  283.         if (dflag)
  284.         {    du->x += basis * dsum.x;
  285.             du->y += basis * dsum.y;
  286.             du->z += basis * dsum.z;
  287.  
  288.                 /* calculate the derivative with respect to v, similarly */
  289.  
  290.             basis = (m[2][j]) +
  291.                     (m[1][j] * dv2) +
  292.                     (m[0][j] * dv3);
  293.  
  294.             dv->x += basis * sum.x;
  295.             dv->y += basis * sum.y;
  296.             dv->z += basis * sum.z;
  297.         }
  298.     }
  299. }
  300.  
  301. void cross (Point3 *a, Point3 *b, Point3 *c)
  302. {    c->x = a->y * b->z - b->y * a->z;
  303.     c->y = a->z * b->x - b->z * a->x;
  304.     c->z = a->x * b->y - b->x * a->y;
  305. }
  306.  
  307. void vsubtract (Point3 *a, Point3 *b, Point3 *c)
  308. {    c->x = a->x - b->x;
  309.     c->y = a->y - b->y;
  310.     c->z = a->z - b->z;
  311. }
  312.  
  313. float length(Point3 *v)
  314. {    float l;
  315.     l = v->x*v->x + v->y*v->y + v->z*v->z;
  316.     l = sqrt(l);
  317.     return l;
  318. }
  319.  
  320. void normalize(Point3 *v)
  321. {    float l = length(v);
  322.     v->x /= l;
  323.     v->y /= l;
  324.     v->z /= l;
  325. }
  326.  
  327. #if 0
  328. sub_patch(SplineBasis *b, float u1, float u2, float v1, float v2, WORD level)
  329. {    float    um,vm;
  330.  
  331.     um = (u1 + u2) / 2.0;
  332.     vm = (v1 + v2) / 2.0;
  333.  
  334.     if (level < 3)
  335.     {    level++;
  336.         sub_patch(b, u1,um,v1,vm,level);
  337.         sub_patch(b, u1,um,vm,v2,level);
  338.         sub_patch(b, um,u2,v1,vm,level);
  339.         sub_patch(b, um,u2,vm,v2,level);
  340.         level--;
  341.     }
  342.     else
  343.     {    Point        s0,s1,s2,s3;
  344.         WORD        icolor;
  345.         Point3        snormal, du, dv;
  346.         Point3V        p0,p1,p2,p3;
  347.  
  348.         spline_eval( b, u1, v1, &p0.p, TRUE );
  349.         spline_eval( b, u2, v1, &p1.p, TRUE );
  350.         spline_eval( b, u2, v2, &p2.p, TRUE );
  351.         spline_eval( b, u1, v2, &p3.p, TRUE );
  352.  
  353. /*        interpolate_points( i,j, u1,v1, &p0 );
  354.         interpolate_points( i,j, u2,v1, &p1 );
  355.         interpolate_points( i,j, u2,v2, &p2 );
  356.         interpolate_points( i,j, u1,v2, &p3 );
  357. */
  358.         transform( &p0.p, &s0 );
  359.         transform( &p1.p, &s1 );
  360.         transform( &p2.p, &s2 );
  361.         transform( &p3.p, &s3 );
  362.  
  363.         cross(&p3.du,&p3.dv,&snormal);
  364.         normalize(&snormal);
  365.  
  366.         icolor = (long)(8.0 - snormal.x * 8.0);
  367.  
  368.         icolor = clamp(2,icolor,15);
  369.         SetAPen(rp,icolor);
  370.  
  371.         AreaMove(rp,s0.x,s0.y);
  372.         AreaDraw(rp,s1.x,s1.y);
  373.         AreaDraw(rp,s2.x,s2.y);
  374.         AreaDraw(rp,s3.x,s3.y);
  375.         AreaEnd(rp);
  376.     }
  377. }
  378. #endif
  379.  
  380. sub_patch(SplineBasis *b,
  381.     float u1, float u2, float v1, float v2,
  382.     Point3V *p0, Point3V *p1, Point3V *p2, Point3V *p3,
  383.     WORD level)
  384. {    float    um,vm;
  385.  
  386.     um = (u1 + u2) / 2.0;
  387.     vm = (v1 + v2) / 2.0;
  388.  
  389.     if (level < 5)
  390.     {    Point3V        p01,p12,p23,p30,pm;
  391.  
  392.         spline_eval( b, um, v1, &p01.p, TRUE );
  393.         spline_eval( b, u2, vm, &p12.p, TRUE );
  394.         spline_eval( b, um, v2, &p23.p, TRUE );
  395.         spline_eval( b, u1, vm, &p30.p, TRUE );
  396.         spline_eval( b, um, vm, &pm.p,  TRUE );
  397.  
  398.         level++;
  399.         sub_patch(b, um,u2,vm,v2, &pm, &p12, p2, &p23, level);
  400.         sub_patch(b, um,u2,v1,vm, &p01, p1, &p12,&pm,  level);
  401.         sub_patch(b, u1,um,vm,v2, &p30,&pm, &p23, p3,  level);
  402.         sub_patch(b, u1,um,v1,vm,  p0, &p01,&pm, &p30, level);
  403.         level--;
  404.     }
  405.     else
  406.     {    Point        s0,s1,s2,s3;
  407.         WORD        icolor;
  408.         Point3        snormal, du, dv;
  409.  
  410. /*        Point3V        p0,p1,p2,p3;
  411.  
  412.         spline_eval( b, u1, v1, &p0.p, TRUE );
  413.         spline_eval( b, u2, v1, &p1.p, TRUE );
  414.         spline_eval( b, u2, v2, &p2.p, TRUE );
  415.         spline_eval( b, u1, v2, &p3.p, TRUE );
  416. */
  417.  
  418. /*        interpolate_points( i,j, u1,v1, &p0 );
  419.         interpolate_points( i,j, u2,v1, &p1 );
  420.         interpolate_points( i,j, u2,v2, &p2 );
  421.         interpolate_points( i,j, u1,v2, &p3 );
  422. */
  423.         transform( &p0->p, &s0 );
  424.         transform( &p1->p, &s1 );
  425.         transform( &p2->p, &s2 );
  426.         transform( &p3->p, &s3 );
  427.  
  428.         cross(&p3->du,&p3->dv,&snormal);
  429.         normalize(&snormal);
  430.  
  431.         icolor = (long)(8.0 - snormal.x * 8.0);
  432.  
  433.         icolor = clamp(2,icolor,15);
  434.         SetAPen(rp,icolor);
  435.  
  436.         AreaMove(rp,s0.x,s0.y);
  437.         AreaDraw(rp,s1.x,s1.y);
  438.         AreaDraw(rp,s2.x,s2.y);
  439.         AreaDraw(rp,s3.x,s3.y);
  440.         AreaEnd(rp);
  441.     }
  442. }
  443.  
  444. #define ITERATIONS 8.0
  445.  
  446. do_patch(ibase,jbase) WORD ibase,jbase;
  447. {    SplineBasis        PreCalc;
  448.     WORD            i,j,k;
  449.  
  450.     for (j=0; j<4; j++)                        /* iterate through Y control points */
  451.     {    Point3        sum;
  452.  
  453.         for (k=0; k<4; k++)                    /* iterate through X control points */
  454.         {
  455.             PreCalc[j][k].x = 0.0;
  456.             PreCalc[j][k].y = 0.0;
  457.             PreCalc[j][k].z = 0.0;
  458.  
  459.             for (i=0; i<4; i++)                /* iterate through powers of U        */
  460.             {    float basis;                /* weighting factor for averaging    */
  461.                 Point3    *cpoint;
  462.  
  463.                 basis = m[k][i];
  464.                 cpoint = &control_hull[i+ibase][j+jbase];
  465.  
  466.                 PreCalc[j][k].x += basis * cpoint->x;
  467.                 PreCalc[j][k].y += basis * cpoint->y;
  468.                 PreCalc[j][k].z += basis * cpoint->z;
  469.             }
  470.         }
  471.     }
  472.  
  473. #if 0
  474.     for (i=ITERATIONS; i>0; i--)
  475.     {    float u1,u2;
  476.  
  477.         u1 = (float)i / ITERATIONS;
  478.         u2 = (float)(i-1) / ITERATIONS;
  479.  
  480.         for (j=ITERATIONS; j>0; j--)
  481.         {    float        v1,v2;
  482.  
  483.             v1 = (float)j / ITERATIONS;
  484.             v2 = (float)(j-1) / ITERATIONS;
  485.  
  486.             sub_patch(&PreCalc, u1, u2, v1, v2, 5);
  487.         }
  488.     }
  489. #endif
  490.  
  491. /*    sub_patch(ibase,jbase, 0.0, 1.0, 0.0, 1.0, 0); */
  492. /*    sub_patch(&PreCalc, 0.0, 1.0, 0.0, 1.0, 0); */
  493.  
  494.     {    Point3V    p0,p1,p2,p3;
  495.  
  496.         spline_eval( &PreCalc, 0.0, 0.0, &p0.p, TRUE );
  497.         spline_eval( &PreCalc, 1.0, 0.0, &p1.p, TRUE );
  498.         spline_eval( &PreCalc, 1.0, 1.0, &p2.p, TRUE );
  499.         spline_eval( &PreCalc, 0.0, 1.0, &p3.p, TRUE );
  500.         sub_patch(&PreCalc, 0.0, 1.0, 0.0, 1.0, &p0,&p1,&p2,&p3, 0);
  501.     }
  502. }
  503.