home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * File : animate.c
- *
- * Abstract : Animation handler. This module is a general animation handler
- * that parses the .rwv files produced by the 3DS convertor
- * and attaches the frame data to the user data field of the
- * required clump(s).
- *
- **********************************************************************
- *
- * This file is a product of Criterion Software Ltd.
- *
- * This file is provided as is with no warranties of any kind and is
- * provided without any obligation on Criterion Software Ltd. or
- * Canon Inc. to assist in its use or modification.
- *
- * Criterion Software Ltd. will not, under any
- * circumstances, be liable for any lost revenue or other damages arising
- * from the use of this file.
- *
- * Copyright (c) 1995 Criterion Software Ltd.
- * All Rights Reserved.
- *
- * RenderWare is a trademark of Canon Inc.
- *
- ************************************************************************/
-
- /*--- Include Files ---*/
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
-
- #include "rwlib.h"
- #include "animate.h"
-
- /*--- Type Definitions ---*/
-
- /* TyFrame: This structure is attached to the user data field of each clump
- * that is being animated. It contains an RwMatrix4d for each frame of the
- * animation.
- */
-
- typedef struct {
- int frames; /* Total number of frames of animation */
- int current; /* Current frame being animated */
- RwMatrix4d **frame; /* Array of matrices representing the frames */
- } TyFrame;
-
-
- /* The .rwv file contains 2 different tokens:
- * 1. Frame <n> - defines the frame number for all subsequent tokens
- * 2. Transform <tag> <float[12]> - defines the matrix representing the frame
- * and the clump that it will be attached to.
- */
-
- /* EnToken: Enumerated type defining the available token types */
-
- typedef enum {
- TK_NULL,
- TK_FRAME,
- TK_TRANSFORM,
- } EnToken;
-
- /* TyTokTransform: contains the data for a Transform token */
-
- typedef struct {
- RwInt32 tag;
- float m[12];
- } TyTokTransform;
-
- /* TyToken: A single global variable of this type is declared and
- * used when parsing the .rwv file.
- */
- typedef struct {
- union {
- RwInt32 frame;
- TyTokTransform transform;
- } u;
- } TyToken;
-
- static TyToken tok;
-
- /************************************************************************
- *
- * Function: ReadInt()
- *
- * Description: Read an integer value from the input stream
- *
- * Parameters: stream - inupt file stream
- * val - location to store the value read
- *
- * Return Value: 0 on failure, any other value for success
- *
- ************************************************************************/
- static int
- ReadInt(FILE * stream, RwInt32 *val)
- {
- char buffer[256];
-
- /* Read a single string from the input stream */
- while (fscanf(stream, "%250s", buffer) == 1)
- {
- if (buffer[0] == '#')
- {
- /* Its a comment. Read to the end of line and ignore */
- fgets(buffer, sizeof(buffer), stream);
- }
- else
- {
- /* Convert the string into an int value */
- return(sscanf(buffer, "%d", val));
- }
- }
- /* Error reading stream */
- return(0);
- }
- /************************************************************************
- *
- * Function: ReadFloat()
- *
- * Description: Read a floating point value from the input stream
- *
- * Parameters: stream - inupt file stream
- * val - location to store the value read
- *
- * Return Value: 0 on failure, any other value for success
- *
- ************************************************************************/
- static int
- ReadFloat(FILE *stream, float *val)
- {
- char buffer[256];
-
- /* Read a single string from the input stream */
- while (fscanf(stream, "%250s", buffer) == 1)
- {
- if (buffer[0] == '#')
- {
- /* Its a comment. Read to the end of line and ignore */
- fgets(buffer, sizeof(buffer), stream);
- }
- else
- {
- /* Convert the string into a float value */
- return(sscanf(buffer, "%f", val));
- }
- }
- /* Error reading stream */
- return(0);
- }
- /************************************************************************
- *
- * Function: ReadString()
- *
- * Description: Read a string from the input stream
- *
- * Parameters: stream - inupt file stream
- * string - location to store the value read
- *
- * Return Value: 0 on failure, any other value for success
- *
- ************************************************************************/
- static int
- ReadString(FILE * stream, char *string)
- {
- char buffer[256];
-
- /* Read a single string from the input stream */
- while (fscanf(stream, "%250s", buffer) == 1)
- {
- if (buffer[0] == '#')
- {
- /* Its a comment. Read to the end of line and ignore */
- fgets(buffer, sizeof(buffer), stream);
- }
- else
- {
- /* copy the string into the variable supplied */
- strcpy(string, buffer);
- return(1);
- }
- }
- return(0);
- }
-
- /************************************************************************
- *
- * Function: ReadToken()
- *
- * Description: Read a token from the input stream
- *
- * Parameters: stream - inupt file stream
- *
- * Return Value: returns the token type read. The global variable
- * tok contains the token data
- *
- ************************************************************************/
- static EnToken
- ReadToken(FILE *stream)
- {
- char string[128];
-
- /* Read the next string from the input stream */
- ReadString(stream, string);
-
- strlwr(string);
-
- /* Is it a frame keyword */
- if (!strcmp(string, "frame"))
- {
- /* Yes. Read the frame number */
- if (ReadInt(stream, &tok.u.frame))
- return(TK_FRAME);
- }
-
- /* Is it a transform keyword */
- else if (!strcmp(string, "transform"))
- {
- /* Yes. Read the clump tag and the transform data */
- if (ReadInt(stream, &tok.u.transform.tag) &&
- ReadFloat(stream, &tok.u.transform.m[0]) &&
- ReadFloat(stream, &tok.u.transform.m[1]) &&
- ReadFloat(stream, &tok.u.transform.m[2]) &&
- ReadFloat(stream, &tok.u.transform.m[3]) &&
- ReadFloat(stream, &tok.u.transform.m[4]) &&
- ReadFloat(stream, &tok.u.transform.m[5]) &&
- ReadFloat(stream, &tok.u.transform.m[6]) &&
- ReadFloat(stream, &tok.u.transform.m[7]) &&
- ReadFloat(stream, &tok.u.transform.m[8]) &&
- ReadFloat(stream, &tok.u.transform.m[9]) &&
- ReadFloat(stream, &tok.u.transform.m[10]) &&
- ReadFloat(stream, &tok.u.transform.m[11]))
- return(TK_TRANSFORM);
- }
-
- /* Couldn't read a valid toke so return error */
- return (TK_NULL);
- }
-
- /************************************************************************
- *
- * Function: LoadAnimation()
- *
- * Description: Load the animation from the specified .rwv file
- * and attach it to the clump.
- *
- * Parameters: clump - the clump to attach the animation to. This
- * will usually be the parent clump of a hierarchical
- * model.
- * filename - the name of the .rwv file to parse
- *
- * Return Value: returns TRUE on success otherwise FALSE
- *
- ************************************************************************/
- int
- LoadAnimation(RwClump *clump, char *filename)
- {
- int current_frame;
- RwClump *active_clump;
- TyFrame *frame;
- FILE *fp;
-
- fp = fopen(filename, "r");
- if (!fp)
- {
- /* Can't open file - error */
- return FALSE;
- }
-
- /* Keep on reading until an error occurs or we reach the end of the file */
-
- for(;;)
- {
- /* Read a token fro the file */
- switch (ReadToken(fp))
- {
- case TK_FRAME:
- /* Its a frame so define the current frame of animation */
- current_frame = (int)tok.u.frame;
- break;
- case TK_TRANSFORM:
- /* It's a transform. Find the clump to attach the transform to */
- active_clump = RwFindTaggedClump(clump, tok.u.transform.tag);
- if (active_clump)
- {
- /* Clump found. Allocate space for the frame */
- frame = RwGetClumpData(active_clump);
- if (!frame)
- {
- frame = malloc(sizeof(TyFrame));
- frame->frames = 1;
- frame->current = 0;
- frame->frame = malloc(sizeof(RwMatrix4d *));
- RwSetClumpData(active_clump, frame);
- }
- else
- {
- frame->frames = current_frame + 1;
- frame->frame = realloc(frame->frame, sizeof(RwMatrix4d *) * (current_frame + 1));
- }
- /* Create a RenderWare matrix and initialise it with the transform values */
- frame->frame[current_frame] = RwCreateMatrix();
- RwSetMatrixElement(frame->frame[current_frame], 0, 0, FL2REAL(tok.u.transform.m[0]));
- RwSetMatrixElement(frame->frame[current_frame], 0, 1, FL2REAL(tok.u.transform.m[1]));
- RwSetMatrixElement(frame->frame[current_frame], 0, 2, FL2REAL(tok.u.transform.m[2]));
- RwSetMatrixElement(frame->frame[current_frame], 0, 3, CREAL(0.0));
- RwSetMatrixElement(frame->frame[current_frame], 1, 0, FL2REAL(tok.u.transform.m[3]));
- RwSetMatrixElement(frame->frame[current_frame], 1, 1, FL2REAL(tok.u.transform.m[4]));
- RwSetMatrixElement(frame->frame[current_frame], 1, 2, FL2REAL(tok.u.transform.m[5]));
- RwSetMatrixElement(frame->frame[current_frame], 1, 3, CREAL(0.0));
- RwSetMatrixElement(frame->frame[current_frame], 2, 0, FL2REAL(tok.u.transform.m[6]));
- RwSetMatrixElement(frame->frame[current_frame], 2, 1, FL2REAL(tok.u.transform.m[7]));
- RwSetMatrixElement(frame->frame[current_frame], 2, 2, FL2REAL(tok.u.transform.m[8]));
- RwSetMatrixElement(frame->frame[current_frame], 2, 3, CREAL(0.0));
- RwSetMatrixElement(frame->frame[current_frame], 3, 0, FL2REAL(tok.u.transform.m[9]));
- RwSetMatrixElement(frame->frame[current_frame], 3, 1, FL2REAL(tok.u.transform.m[10]));
- RwSetMatrixElement(frame->frame[current_frame], 3, 2, FL2REAL(tok.u.transform.m[11]));
- RwSetMatrixElement(frame->frame[current_frame], 3, 3, CREAL(1.0));
- }
- break;
- default:
- /* Not a valid token. Its probably the end of the file so just
- shutup and return success */
- fclose(fp);
- return TRUE;
- }
- }
- }
-
- /************************************************************************
- *
- * Function: DestroyCallback()
- *
- * Description: Function called for each clump in the hierarchy to
- * return all frame data back to the system.
- *
- * Parameters: clump - The clump to remove the frame data from.
- *
- * Return Value: returns the clump passed in
- * (required for RwForAllClumps...)
- *
- ************************************************************************/
- RwClump *DestroyCallback(RwClump *clump)
- {
- TyFrame *frame;
- int i;
-
- /* Retrieve the frame data for the clump and free it up if it exists */
- frame = RwGetClumpData(clump);
- if (frame)
- {
- if (frame->frame)
- {
- for (i = 0; i < frame->frames; i++)
- {
- /* Destroy the RenderWare matrix objects */
- RwDestroyMatrix(frame->frame[i]);
- }
- free(frame->frame);
- }
- free(frame);
- }
- return(clump);
- }
-
- /************************************************************************
- *
- * Function: DestroyAnimation()
- *
- * Description: Detach the animation data from a clump and
- * return all allocated memory back to the system
- *
- * Parameters: clump - The clump to remove the frame data from.
- *
- * Return Value: None
- *
- ************************************************************************/
- void DestroyAnimation(RwClump *clump)
- {
- RwForAllClumpsInHierarchy(clump, DestroyCallback);
- }
-
- /************************************************************************
- *
- * Function: AnimateClump()
- *
- * Description: Animate the clump. For this example we just advance
- * to the next frame of animation and cycle back to the
- * start once we reach the end.
- *
- * Parameters: clump - The clump to advance.
- *
- * Return Value: the clump passed in. This allows the function to be
- * called by RwForAllClumps... functions
- *
- ************************************************************************/
- RwClump *AnimateClump(RwClump *clump)
- {
- TyFrame *clump_frame;
- int current_frame;
-
- /* Get the frame data */
- clump_frame = (TyFrame *)RwGetClumpData(clump);
-
- if (clump_frame)
- {
- /* We've got the frame data so advance the clump to the next frame */
- current_frame = clump_frame->current % clump_frame->frames;
-
- /* And apply the transform to the clump */
- RwTransformClump(clump, clump_frame->frame[current_frame], rwREPLACE);
- clump_frame->current++;
- }
- return(clump);
- }
-
-