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 >
Wrap
C/C++ Source or Header
|
1995-02-15
|
14KB
|
540 lines
/**********************************************************************
*
* Header files.
*
**********************************************************************/
#define INCLUDE_SHELLAPI_H
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "rwlib.h"
#include "danimate.h"
#include "dknight.h"
typedef float TyMatrix[12];
typedef struct {
int tag;
TyMatrix m;
} TyTokTransform;
typedef enum {
TK_NULL,
TK_FRAME,
TK_TRANSFORM,
} EnToken;
typedef struct {
union {
int frame;
TyTokTransform transform;
} u;
} TyToken;
TyToken tok;
long FrameCount = 0;
/*********************************************************************/
int
ReadInt(FILE * stream, int *val)
{
char buffer[256];
for(;;)
{
if (fscanf(stream, "%250s", buffer) == 1)
{
if (buffer[0] == '#')
{
fgets(buffer, sizeof(buffer), stream);
}
else
{
return(sscanf(buffer, "%d", val));
}
}
else
{
return(0);
}
}
}
/*********************************************************************/
int
ReadFloat(FILE *stream, float *val)
{
char buffer[256];
for(;;)
{
if (fscanf(stream, "%250s", buffer) == 1)
{
if (buffer[0] == '#')
{
fgets(buffer, sizeof(buffer), stream);
}
else
{
if (sscanf(buffer, "%f", val))
{
return(1);
}
}
}
else
{
return(0);
}
}
}
/**********************************************************************/
EnToken ReadToken(FILE *stream)
{
int c;
int i;
char *s;
char string[128];
/* skip whitespace */
do
{
c = fgetc(stream);
}
while (isspace(c));
i = 0;
s = string;
while ((c != EOF) && (!isspace(c)))
{
/*
* Only append the characters read if there is room in the
* output string (this will truncate the string read).
*/
if (i < 127)
{
*s++ = (char)c;
i++;
}
c = fgetc(stream);
}
/*
* Put the terminating character back.
*/
ungetc(c, stream);
*s = '\0';
strlwr(string);
if (!strcmp(string, "frame"))
{
if (ReadInt(stream, &tok.u.frame))
return(TK_FRAME);
}
else if (!strcmp(string, "transform"))
{
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);
}
return (TK_NULL);
}
void DestroyFrame(TyFrameData *fd)
{
int i;
if (fd->frames)
{
for (i=0; i < fd->frames; i++)
RwDestroyMatrix(fd->frame[i]);
free(fd->frame);
}
fd->frames = 0;
fd->frame = NULL;
free(fd);
}
TyFrameData *CreateFrame(void)
{
TyFrameData *fd;
RwMatrix4d **frame;
fd = malloc(sizeof(TyFrameData));
if (fd)
{
frame = malloc(sizeof(RwMatrix4d *));
if (frame)
{
*frame = RwCreateMatrix();
if (*frame)
{
fd->frames = 1;
fd->frame = frame;
return fd;
}
free(frame);
}
free(fd);
}
return NULL;
}
int AddFrame(TyFrameData *fd)
{
RwMatrix4d **new_frame;
new_frame = realloc(fd->frame, sizeof(RwMatrix4d *) * (fd->frames +1));
if (new_frame)
{
fd->frame = new_frame;
fd->frame[fd->frames] = RwCreateMatrix();
if (fd->frame[fd->frames])
{
fd->frames++;
return TRUE;
}
}
DestroyFrame(fd);
return FALSE;
}
void DestroyAnimation(TyAnimationData *ad)
{
if (ad->animations)
{
free(ad->animation);
}
free(ad);
}
TyAnimationData *CreateAnimation(void)
{
TyAnimationData *ad;
TyAnimation *new;
ad = malloc(sizeof(TyAnimationData));
if (ad)
{
new = malloc(sizeof(TyAnimation));
if (new)
{
ad->current_frame = 0;
ad->current_animation = NULL;
ad->next_animation = NULL;
ad->animations = 1;
ad->animation = new;
ad->state = A_ON;
ad->opacity = CREAL(1.0);
return ad;
}
free(ad);
}
return NULL;
}
TyAnimationData *AddAnimation(TyAnimationData *ad, char *name, int start, int end, int react)
{
TyAnimation *new;
if (ad)
{
new = realloc(ad->animation, sizeof(TyAnimation) * (ad->animations +1));
if (!new)
{
DestroyAnimation(ad);
return NULL;
}
ad->animation = new;
ad->animations++;
}
else
{
ad = CreateAnimation();
if (!ad)
{
return NULL;
}
}
ad->animation[ad->animations-1].start = start;
ad->animation[ad->animations-1].end = end;
ad->animation[ad->animations-1].react = react;
strncpy(ad->animation[ad->animations-1].name, name, 15);
ad->animation[ad->animations-1].name[15] = 0;
return ad;
}
TyAnimation *FindAnimation(TyAnimationData *ad, char *name)
{
int i;
for (i = 0; i < ad->animations; i++)
{
if (!strncmp(ad->animation[i].name, name,15))
{
return (&ad->animation[i]);
}
}
return(NULL);
}
void SetAnimationState(RwClump *clump, EnAnimation state)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
ad->state = state;
}
}
EnAnimation GetAnimationState(RwClump *clump)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
return (ad->state);
}
return (A_OFF);
}
/**********************************************************************/
int LoadAnimation(RwClump *clump, char *filename)
{
int current_frame = 0;
RwClump *active_clump;
TyFrameData *fd;
FILE *fp;
fp = fopen(filename, "r");
if (!fp)
return FALSE;
for(;;)
{
switch (ReadToken(fp))
{
case TK_FRAME:
current_frame = tok.u.frame;
break;
case TK_TRANSFORM:
active_clump = RwFindTaggedClump(clump, (RwInt32)tok.u.transform.tag);
if (active_clump)
{
fd = RwGetClumpData(active_clump);
if (!fd)
{
fd = CreateFrame();
if (!fd)
return FALSE;
RwSetClumpData(active_clump, fd);
}
else
{
if (!AddFrame(fd))
{
RwSetClumpData(active_clump, NULL);
return FALSE;
}
}
if (current_frame != fd->frames -1)
{
DestroyFrame(fd);
RwSetClumpData(active_clump, NULL);
return(FALSE);
}
RwSetMatrixElement(fd->frame[current_frame], 0, 0, FL2REAL(tok.u.transform.m[0]));
RwSetMatrixElement(fd->frame[current_frame], 0, 1, FL2REAL(tok.u.transform.m[1]));
RwSetMatrixElement(fd->frame[current_frame], 0, 2, FL2REAL(tok.u.transform.m[2]));
RwSetMatrixElement(fd->frame[current_frame], 0, 3, CREAL(0.0));
RwSetMatrixElement(fd->frame[current_frame], 1, 0, FL2REAL(tok.u.transform.m[3]));
RwSetMatrixElement(fd->frame[current_frame], 1, 1, FL2REAL(tok.u.transform.m[4]));
RwSetMatrixElement(fd->frame[current_frame], 1, 2, FL2REAL(tok.u.transform.m[5]));
RwSetMatrixElement(fd->frame[current_frame], 1, 3, CREAL(0.0));
RwSetMatrixElement(fd->frame[current_frame], 2, 0, FL2REAL(tok.u.transform.m[6]));
RwSetMatrixElement(fd->frame[current_frame], 2, 1, FL2REAL(tok.u.transform.m[7]));
RwSetMatrixElement(fd->frame[current_frame], 2, 2, FL2REAL(tok.u.transform.m[8]));
RwSetMatrixElement(fd->frame[current_frame], 2, 3, CREAL(0.0));
RwSetMatrixElement(fd->frame[current_frame], 3, 0, FL2REAL(tok.u.transform.m[9]));
RwSetMatrixElement(fd->frame[current_frame], 3, 1, FL2REAL(tok.u.transform.m[10]));
RwSetMatrixElement(fd->frame[current_frame], 3, 2, FL2REAL(tok.u.transform.m[11]));
RwSetMatrixElement(fd->frame[current_frame], 3, 3, CREAL(1.0));
}
break;
default:
fclose(fp);
return TRUE;
}
}
}
void DefineAnimation(RwClump *clump, char *name, int start, int end, int react)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
RwSetClumpData(clump, AddAnimation(ad, name, start, end, react));
}
void StartAnimation(RwClump *clump, char *name)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
if (!ad->current_animation)
{
ad->current_animation = FindAnimation(ad, name);
if (ad->current_animation)
ad->current_frame = ad->current_animation->start;
}
else
{
ad->next_animation = FindAnimation(ad, name);
}
}
}
RwClump *SetClumpFrame(RwClump *c, RwInt32 frame)
{
TyFrameData *fd;
if (RwGetClumpParent(c))
{
fd = RwGetClumpData(c);
if (fd)
{
if (frame < fd->frames)
{
RwTransformClump(c, fd->frame[frame], rwREPLACE);
}
}
}
return c;
}
RwClump *SetClumpOpacity(RwClump *clump, RwReal opacity)
{
return (RwForAllPolygonsInClumpReal(clump, RwSetPolygonOpacity, opacity));
}
int ResolveClump(RwClump *clump)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
ad->opacity = RAdd(ad->opacity, CREAL(0.05));
if (ad->opacity > CREAL(1.0))
ad->opacity = CREAL(1.0);
RwForAllClumpsInHierarchyReal(clump, SetClumpOpacity, ad->opacity);
if (ad->opacity < CREAL(1.0))
return(FALSE);
}
return (TRUE);
}
int DissolveClump(RwClump *clump)
{
TyAnimationData *ad;
ad = RwGetClumpData(clump);
if (ad)
{
ad->opacity = RSub(ad->opacity, CREAL(0.05));
if (ad->opacity < CREAL(0.0))
ad->opacity = CREAL(0.0);
RwForAllClumpsInHierarchyReal(clump, SetClumpOpacity, ad->opacity);
if (ad->opacity > CREAL(0.0))
return(FALSE);
}
return (TRUE);
}
RwClump *AnimateClump(RwClump *clump)
{
TyAnimationData *ad;
if (RwGetClumpParent(clump)) /* only animate root clumps */
return(clump);
ad = RwGetClumpData(clump);
if (ad)
{
switch (ad->state)
{
case A_DISSOLVE:
if (DissolveClump(clump))
{
StartAnimation(clump, RandomKnight(clump));
RwForAllClumpsInHierarchyInt(clump, SetClumpFrame, (RwInt32)ad->current_frame);
SetAnimationState(clump, A_RESOLVE);
}
break;
case A_RESOLVE:
if (ResolveClump(clump))
{
SetAnimationState(clump, A_ON);
}
break;
case A_ON:
if (ad->current_animation)
{
if (ad->current_animation->start < ad->current_animation->end)
ad->current_frame++;
else
ad->current_frame--;
if (ad->current_frame == ad->current_animation->react)
ReactKnight(clump, ad->current_animation);
if (ad->current_frame >= ad->current_animation->end)
{
if (ad->next_animation)
{
ad->current_animation = ad->next_animation;
ad->current_frame = ad->current_animation->start;
ad->next_animation = NULL;
}
else
{
ad->current_animation = NULL;
StartAnimation(clump, RandomKnight(clump));
return(clump);
}
}
RwForAllClumpsInHierarchyInt(clump, SetClumpFrame, (RwInt32)ad->current_frame);
}
break;
}
}
return(clump);
}
void AnimateScene(void)
{
AnimateClump(Knight1);
AnimateClump(Knight2);
}