home *** CD-ROM | disk | FTP | other *** search
/ Learn 3D Graphics Programming on the PC / Learn_3D_Graphics_Programming_on_the_PC_Ferraro.iso / rwwin / animate.c_ / animate.bin
Text File  |  1995-11-14  |  15KB  |  568 lines

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