home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwdos / danimate.c < prev    next >
C/C++ Source or Header  |  1995-02-15  |  14KB  |  540 lines

  1. /**********************************************************************
  2.  *
  3.  * Header files.
  4.  *
  5.  **********************************************************************/
  6.  
  7. #define INCLUDE_SHELLAPI_H
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13.  
  14. #include "rwlib.h"
  15.  
  16. #include "danimate.h"
  17. #include "dknight.h"
  18.  
  19. typedef float TyMatrix[12];
  20.  
  21. typedef struct {
  22.     int     tag;
  23.     TyMatrix m;
  24. } TyTokTransform;
  25.  
  26. typedef enum {
  27.     TK_NULL,
  28.     TK_FRAME,
  29.     TK_TRANSFORM,
  30. } EnToken;
  31.  
  32. typedef struct {
  33.   union {
  34.     int         frame;
  35.     TyTokTransform transform;
  36.   } u;
  37. } TyToken;
  38.  
  39. TyToken tok;
  40. long FrameCount = 0;
  41.  
  42. /*********************************************************************/
  43. int
  44. ReadInt(FILE * stream, int *val)
  45. {
  46.     char buffer[256];
  47.  
  48.     for(;;)
  49.     {
  50.         if (fscanf(stream, "%250s", buffer) == 1)
  51.         {
  52.             if (buffer[0] == '#')
  53.             {
  54.                 fgets(buffer, sizeof(buffer), stream);
  55.             }
  56.             else
  57.             {
  58.                 return(sscanf(buffer, "%d", val));
  59.             }
  60.         }
  61.         else
  62.         {
  63.             return(0);
  64.         }
  65.     }
  66. }
  67.  
  68. /*********************************************************************/
  69. int
  70. ReadFloat(FILE *stream, float *val)
  71. {
  72.     char buffer[256];
  73.  
  74.     for(;;)
  75.     {
  76.         if (fscanf(stream, "%250s", buffer) == 1)
  77.         {
  78.             if (buffer[0] == '#')
  79.             {
  80.                 fgets(buffer, sizeof(buffer), stream);
  81.             }
  82.             else
  83.             {
  84.                 if (sscanf(buffer, "%f", val))
  85.                 {
  86.                     return(1);
  87.                 }
  88.             }
  89.         }
  90.         else
  91.         {
  92.             return(0);
  93.         }
  94.     }
  95. }
  96.  
  97. /**********************************************************************/
  98. EnToken ReadToken(FILE *stream)
  99. {
  100.     int c;
  101.     int i;
  102.     char *s;
  103.     char string[128];    
  104.  
  105.     /* skip whitespace */
  106.     do
  107.     {
  108.         c = fgetc(stream);
  109.     }
  110.     while (isspace(c));
  111.  
  112.     i = 0;
  113.     s = string;
  114.     while ((c != EOF) && (!isspace(c)))
  115.     {
  116.         /* 
  117.          * Only append the characters read if there is room in the
  118.          * output string (this will truncate the string read).
  119.          */
  120.             if (i < 127)
  121.             {
  122.                 *s++ = (char)c;
  123.                 i++;
  124.             }
  125.             c = fgetc(stream);
  126.     }
  127.     /* 
  128.      * Put the terminating character back.
  129.      */
  130.     ungetc(c, stream);
  131.     *s = '\0';
  132.  
  133.     strlwr(string);
  134.     if (!strcmp(string, "frame"))
  135.     {
  136.         if (ReadInt(stream, &tok.u.frame))
  137.             return(TK_FRAME);
  138.     }
  139.     else if (!strcmp(string, "transform"))
  140.     {
  141.         if (ReadInt(stream, &tok.u.transform.tag) &&
  142.             ReadFloat(stream, &tok.u.transform.m[0]) &&
  143.             ReadFloat(stream, &tok.u.transform.m[1]) &&
  144.             ReadFloat(stream, &tok.u.transform.m[2]) &&
  145.             ReadFloat(stream, &tok.u.transform.m[3]) &&
  146.             ReadFloat(stream, &tok.u.transform.m[4]) &&
  147.             ReadFloat(stream, &tok.u.transform.m[5]) &&
  148.             ReadFloat(stream, &tok.u.transform.m[6]) &&
  149.             ReadFloat(stream, &tok.u.transform.m[7]) &&
  150.             ReadFloat(stream, &tok.u.transform.m[8]) &&
  151.             ReadFloat(stream, &tok.u.transform.m[9]) &&
  152.             ReadFloat(stream, &tok.u.transform.m[10]) &&
  153.             ReadFloat(stream, &tok.u.transform.m[11]))
  154.             return(TK_TRANSFORM);
  155.     }
  156.     return (TK_NULL);
  157. }
  158.  
  159. void DestroyFrame(TyFrameData *fd)
  160. {
  161.     int i;
  162.     if (fd->frames)
  163.     {
  164.         for (i=0; i < fd->frames; i++)
  165.             RwDestroyMatrix(fd->frame[i]);        
  166.                         
  167.         free(fd->frame);
  168.     }
  169.     fd->frames = 0;
  170.     fd->frame = NULL;
  171.     free(fd);
  172. }
  173.  
  174. TyFrameData *CreateFrame(void)
  175. {
  176.     TyFrameData *fd;
  177.     RwMatrix4d **frame;
  178.  
  179.     fd = malloc(sizeof(TyFrameData));
  180.     if (fd)
  181.     {        
  182.         frame = malloc(sizeof(RwMatrix4d *));
  183.         if (frame)
  184.         {
  185.             *frame = RwCreateMatrix();
  186.             if (*frame)
  187.             {
  188.                 fd->frames = 1;
  189.                 fd->frame = frame;
  190.                 return fd;
  191.             }
  192.             free(frame);        
  193.         }
  194.         free(fd);        
  195.     }
  196.     return NULL;        
  197. }
  198.  
  199. int AddFrame(TyFrameData *fd)
  200. {
  201.     RwMatrix4d **new_frame;
  202.  
  203.     new_frame = realloc(fd->frame, sizeof(RwMatrix4d *) * (fd->frames +1));
  204.     if (new_frame)
  205.     {
  206.         fd->frame = new_frame;
  207.         fd->frame[fd->frames] = RwCreateMatrix();
  208.         if (fd->frame[fd->frames])
  209.         {
  210.             fd->frames++;
  211.             return TRUE;
  212.         }  
  213.     }
  214.     DestroyFrame(fd);
  215.     return FALSE;
  216. }
  217. void DestroyAnimation(TyAnimationData *ad)
  218. {
  219.     if (ad->animations)
  220.     {
  221.         free(ad->animation);
  222.     }
  223.     free(ad);
  224. }
  225.  
  226. TyAnimationData *CreateAnimation(void)
  227. {
  228.     TyAnimationData *ad;
  229.     TyAnimation *new;
  230.     ad = malloc(sizeof(TyAnimationData));
  231.     if (ad)
  232.     {
  233.         new = malloc(sizeof(TyAnimation));
  234.         if (new)
  235.         {
  236.             ad->current_frame = 0;
  237.             ad->current_animation = NULL;
  238.             ad->next_animation = NULL;
  239.             ad->animations = 1;
  240.             ad->animation = new;
  241.             ad->state = A_ON;
  242.             ad->opacity = CREAL(1.0);
  243.             return ad;
  244.         }
  245.         free(ad);
  246.     }
  247.     return NULL;        
  248. }
  249.  
  250. TyAnimationData *AddAnimation(TyAnimationData *ad, char *name, int start, int end, int react)
  251. {
  252.     TyAnimation *new;
  253.  
  254.     if (ad)
  255.     {
  256.         new = realloc(ad->animation, sizeof(TyAnimation) * (ad->animations +1));
  257.         if (!new)
  258.         {
  259.             DestroyAnimation(ad);
  260.             return NULL;
  261.         }
  262.         ad->animation = new;
  263.         ad->animations++;        
  264.     }
  265.     else
  266.     {
  267.         ad = CreateAnimation();
  268.         if (!ad)
  269.         {
  270.             return NULL;
  271.         }
  272.     }
  273.     ad->animation[ad->animations-1].start = start;
  274.     ad->animation[ad->animations-1].end = end;
  275.     ad->animation[ad->animations-1].react = react;
  276.     strncpy(ad->animation[ad->animations-1].name, name, 15);
  277.     ad->animation[ad->animations-1].name[15] = 0;        
  278.     return ad;        
  279. }
  280.  
  281. TyAnimation *FindAnimation(TyAnimationData *ad, char *name)
  282. {
  283.     int i;
  284.  
  285.     for (i = 0; i < ad->animations; i++)
  286.     {
  287.         if (!strncmp(ad->animation[i].name, name,15))
  288.         {
  289.             return (&ad->animation[i]);
  290.         }        
  291.     }
  292.     return(NULL);
  293. }
  294.  
  295. void SetAnimationState(RwClump *clump, EnAnimation state)
  296. {
  297.     TyAnimationData *ad;
  298.  
  299.     ad = RwGetClumpData(clump);
  300.     if (ad)
  301.     {
  302.         ad->state = state;        
  303.     }
  304. }
  305.  
  306. EnAnimation GetAnimationState(RwClump *clump)
  307. {
  308.     TyAnimationData *ad;
  309.  
  310.     ad = RwGetClumpData(clump);
  311.     if (ad)
  312.     {
  313.         return (ad->state);
  314.     }
  315.     return (A_OFF);
  316. }
  317.  
  318. /**********************************************************************/
  319. int LoadAnimation(RwClump *clump, char *filename)
  320. {
  321.     int current_frame = 0;
  322.     RwClump *active_clump;
  323.     TyFrameData *fd;
  324.     FILE *fp;
  325.  
  326.     fp = fopen(filename, "r");
  327.     if (!fp)
  328.         return FALSE;
  329.     
  330.     for(;;)
  331.     {
  332.         switch (ReadToken(fp))
  333.         {
  334.             case TK_FRAME:
  335.                 current_frame = tok.u.frame;
  336.                 break;
  337.             case TK_TRANSFORM:
  338.                 active_clump = RwFindTaggedClump(clump, (RwInt32)tok.u.transform.tag);
  339.                 if (active_clump)
  340.                 {
  341.                     fd = RwGetClumpData(active_clump);
  342.                     if (!fd)
  343.                     {
  344.                         fd = CreateFrame();
  345.                         if (!fd)
  346.                             return FALSE;        
  347.                         RwSetClumpData(active_clump, fd);
  348.                     }        
  349.                     else
  350.                     {        
  351.                         if (!AddFrame(fd))
  352.                         {
  353.                             RwSetClumpData(active_clump, NULL);
  354.                             return FALSE;
  355.                         }
  356.                     }
  357.                     if (current_frame != fd->frames -1)
  358.                     {
  359.                         DestroyFrame(fd);
  360.                         RwSetClumpData(active_clump, NULL);
  361.                         return(FALSE);
  362.                     }        
  363.                     RwSetMatrixElement(fd->frame[current_frame], 0, 0, FL2REAL(tok.u.transform.m[0]));
  364.                     RwSetMatrixElement(fd->frame[current_frame], 0, 1, FL2REAL(tok.u.transform.m[1]));
  365.                     RwSetMatrixElement(fd->frame[current_frame], 0, 2, FL2REAL(tok.u.transform.m[2]));
  366.                     RwSetMatrixElement(fd->frame[current_frame], 0, 3, CREAL(0.0));
  367.                     RwSetMatrixElement(fd->frame[current_frame], 1, 0, FL2REAL(tok.u.transform.m[3]));
  368.                     RwSetMatrixElement(fd->frame[current_frame], 1, 1, FL2REAL(tok.u.transform.m[4]));
  369.                     RwSetMatrixElement(fd->frame[current_frame], 1, 2, FL2REAL(tok.u.transform.m[5]));
  370.                     RwSetMatrixElement(fd->frame[current_frame], 1, 3, CREAL(0.0));
  371.                     RwSetMatrixElement(fd->frame[current_frame], 2, 0, FL2REAL(tok.u.transform.m[6]));
  372.                     RwSetMatrixElement(fd->frame[current_frame], 2, 1, FL2REAL(tok.u.transform.m[7]));
  373.                     RwSetMatrixElement(fd->frame[current_frame], 2, 2, FL2REAL(tok.u.transform.m[8]));
  374.                     RwSetMatrixElement(fd->frame[current_frame], 2, 3, CREAL(0.0));
  375.                     RwSetMatrixElement(fd->frame[current_frame], 3, 0, FL2REAL(tok.u.transform.m[9]));
  376.                     RwSetMatrixElement(fd->frame[current_frame], 3, 1, FL2REAL(tok.u.transform.m[10]));
  377.                     RwSetMatrixElement(fd->frame[current_frame], 3, 2, FL2REAL(tok.u.transform.m[11]));
  378.                     RwSetMatrixElement(fd->frame[current_frame], 3, 3, CREAL(1.0));
  379.                 }
  380.                 break;
  381.             default:
  382.                 fclose(fp);
  383.                 return TRUE;
  384.          }
  385.     }
  386. }
  387.  
  388. void DefineAnimation(RwClump *clump, char *name, int start, int end, int react)
  389. {
  390.   TyAnimationData *ad;
  391.  
  392.   ad = RwGetClumpData(clump);
  393.   RwSetClumpData(clump, AddAnimation(ad, name, start, end, react));
  394. }
  395.  
  396. void StartAnimation(RwClump *clump, char *name)
  397. {
  398.   TyAnimationData *ad;
  399.  
  400.   ad = RwGetClumpData(clump);
  401.  
  402.   if (ad)
  403.   {
  404.      if (!ad->current_animation)
  405.      {
  406.         ad->current_animation = FindAnimation(ad, name);
  407.         if (ad->current_animation)
  408.             ad->current_frame = ad->current_animation->start;        
  409.      }
  410.      else
  411.      {
  412.         ad->next_animation = FindAnimation(ad, name);
  413.      }
  414.   }        
  415. }
  416.  
  417. RwClump *SetClumpFrame(RwClump *c, RwInt32 frame)
  418. {
  419.   TyFrameData *fd;
  420.  
  421.   if (RwGetClumpParent(c))
  422.   {        
  423.       fd = RwGetClumpData(c);
  424.       if (fd)
  425.       {
  426.          if (frame < fd->frames)
  427.          {
  428.             RwTransformClump(c, fd->frame[frame], rwREPLACE);        
  429.          }        
  430.       }
  431.   }    
  432.   return c;
  433. }
  434.  
  435. RwClump *SetClumpOpacity(RwClump *clump, RwReal opacity)
  436. {
  437.     return (RwForAllPolygonsInClumpReal(clump, RwSetPolygonOpacity, opacity));
  438. }
  439.  
  440. int ResolveClump(RwClump *clump)
  441. {
  442.     TyAnimationData *ad;
  443.  
  444.     ad = RwGetClumpData(clump);
  445.     if (ad)
  446.     {
  447.         ad->opacity = RAdd(ad->opacity, CREAL(0.05));
  448.         if (ad->opacity > CREAL(1.0))
  449.            ad->opacity = CREAL(1.0);
  450.         RwForAllClumpsInHierarchyReal(clump, SetClumpOpacity, ad->opacity);
  451.         if (ad->opacity < CREAL(1.0))
  452.             return(FALSE);
  453.     }       
  454.     return (TRUE);        
  455. }
  456.  
  457. int DissolveClump(RwClump *clump)
  458. {
  459.     TyAnimationData *ad;
  460.  
  461.     ad = RwGetClumpData(clump);
  462.     if (ad)
  463.     {
  464.         ad->opacity = RSub(ad->opacity, CREAL(0.05));
  465.         if (ad->opacity < CREAL(0.0))
  466.            ad->opacity = CREAL(0.0);
  467.         RwForAllClumpsInHierarchyReal(clump, SetClumpOpacity, ad->opacity);
  468.         if (ad->opacity > CREAL(0.0))
  469.             return(FALSE);
  470.     } 
  471.     return (TRUE);        
  472. }
  473.  
  474. RwClump *AnimateClump(RwClump *clump)
  475. {
  476.     TyAnimationData *ad;        
  477.  
  478.     if (RwGetClumpParent(clump))        /* only animate root clumps */        
  479.        return(clump);
  480.  
  481.     ad = RwGetClumpData(clump);
  482.  
  483.     if (ad)
  484.     {        
  485.        switch (ad->state)
  486.        {
  487.        case A_DISSOLVE:
  488.            if (DissolveClump(clump))
  489.            {
  490.                StartAnimation(clump, RandomKnight(clump));
  491.                RwForAllClumpsInHierarchyInt(clump, SetClumpFrame, (RwInt32)ad->current_frame);
  492.                SetAnimationState(clump, A_RESOLVE);      
  493.            }
  494.            break;
  495.        case A_RESOLVE:
  496.           if (ResolveClump(clump))
  497.           {
  498.               SetAnimationState(clump, A_ON);
  499.           }
  500.           break;
  501.        case A_ON:
  502.            if (ad->current_animation)
  503.            {
  504.                if (ad->current_animation->start < ad->current_animation->end)
  505.                    ad->current_frame++;
  506.                else 
  507.                    ad->current_frame--;
  508.     
  509.                if (ad->current_frame == ad->current_animation->react)
  510.                    ReactKnight(clump, ad->current_animation);
  511.                                 
  512.                if (ad->current_frame >= ad->current_animation->end)
  513.                {
  514.                    if (ad->next_animation)
  515.                    {
  516.                        ad->current_animation = ad->next_animation;
  517.                        ad->current_frame = ad->current_animation->start;
  518.                        ad->next_animation = NULL;
  519.                    }
  520.                    else
  521.                    {
  522.                        ad->current_animation = NULL;
  523.                        StartAnimation(clump, RandomKnight(clump));
  524.                        return(clump);
  525.                    }
  526.                }
  527.                RwForAllClumpsInHierarchyInt(clump, SetClumpFrame, (RwInt32)ad->current_frame);
  528.            }        
  529.            break;        
  530.         }
  531.     }
  532.     return(clump);
  533. }
  534.  
  535. void AnimateScene(void) 
  536. {
  537.     AnimateClump(Knight1);
  538.     AnimateClump(Knight2);
  539. }
  540.