SBSPSS/Utils/MkAnim3d/MkAnim3d.cpp
2001-01-30 17:39:20 +00:00

347 lines
8.5 KiB
C++

/**********************************/
/*** SpongeBob 3d Anim Creator ***/
/**********************************/
#include "stdio.h"
#include <misc.hpp>
#include <GFName.hpp>
#include <conio.h>
#include <iostream.h>
#include <vector>
#include <PsxLib.h>
#include <FaceStore.h>
#include "MkAnim3d.h"
using namespace std;
int QuatCount=0;
/*
buttbounceend.gin buttbouncestart.gin deathbackwards.gin deathdry.gin deathfall.gin deathforwards.gin deathspin.gin deathtar.gin electricshock.gin electricshockend.gin electricshockstart.gin faceback.gin facefront.gin fall.gin getup.gin getuprun.gin hitground.gin hover.gin hoverend.gin hoverstart.gin idlebreathe.gin idlehoola.gin idlelook.gin idlewigglearm.gin jumpend.gin karate.gin knockback.gin knockforward.gin run.gin runjumpend.gin runjumpstart.gin runstart.gin runstop.gin soakup.gin talk01.gin talk02.gin talk03.gin talk04.gin teeterback.gin teeterfront.gin
*/
/* duff anims
deathfall.gin
runjumpend.gin
runjumpstart.gin
*/
//***************************************************************************
char * CycleCommands(char *String,int Num)
{
//char Text[256],*TextPtr;
//int Count;
if (String[0]=='-' || String[0]=='/')
{
GString TpStr;
switch (String[1])
{
// Switches
case 'o':
OutStr = CheckFileString(String);
break;
case 'd':
DebugOn =true;
break;
case 's':
TpStr= CheckFileString(String);
Scale=atof(TpStr);
break;
case 'i':
IncludeFile= CheckFileString(String);
break;
default:
GObject::Error(ERR_FATAL,"Unknown switch %s",String);
break;
}
}
else
{
GString UpperName(String);
UpperName.Upper();
MyFiles.AddFile(UpperName);
}
return(String);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
void CMkAnim3d::Add(GString const &Filename)
{
CScene Scene;
int ThisBoneCount;
GFName Name=Filename;
printf("%s\t",Name.File());
Scene.Load(Filename);
// Process Anim
sAnim ThisAnim;
ThisAnim.Name=Name.File();
ThisAnim.Name.Upper();
ThisAnim.FrameCount=ProcessSkelMove(Scene,ThisAnim,1);
ProcessSkelAnim(Scene,ThisAnim,1);
AnimList.push_back(ThisAnim);
ThisBoneCount=ThisAnim.BoneAnim.size();
printf("\t(%i Bones, %i Frames)\n",ThisBoneCount,ThisAnim.FrameCount);
// Check Skeleton
if (BoneCount==-1)
{
BoneCount=ThisBoneCount;
}
else
{
if (BoneCount!=ThisBoneCount)
{
GObject::Error(ERR_FATAL,"Invalid skeleton\n");
}
}
}
//***************************************************************************
int CMkAnim3d::ProcessSkelMove(CScene &Scene,sAnim &ThisAnim,int Idx)
{
CNode &ThisNode=Scene.GetNode(Idx);
vector<sGinAnim> const &NodeAnim=ThisNode.GetAnim();
int FrameCount=NodeAnim.size();
vector<s32> &Move=ThisAnim.Move;
Move.resize(FrameCount);
for (int i=0; i<FrameCount; i++)
{
// Move[i].vx=round(NodeAnim[i].Pos.x*Scale);
Move[i]=-round(NodeAnim[i].Pos.y*Scale);
// Move[i].vz=round(NodeAnim[i].Pos.z*Scale);
}
return(FrameCount);
}
//***************************************************************************
void CMkAnim3d::ProcessSkelAnim(CScene &Scene,sAnim &ThisAnim,int Idx)
{
CNode &ThisNode=Scene.GetNode(Idx);
vector<sGinAnim> const &NodeAnim=ThisNode.GetAnim();
int FrameCount=NodeAnim.size();
// if (!ThisNode.Pts.size()) // Dont export Skin as bone
if (!ThisNode.GetTris().size()) // Dont export Skin as bone
{
sBoneAnim FrameList;
FrameList.Idx.resize(FrameCount);
for (int i=0; i<FrameCount; i++)
{
sGinAnim const &InFrame=NodeAnim[i];
sQuat ThisFrame;
Quaternion const &ThisQuat=InFrame.Ang;
ThisFrame.vx=round(ThisQuat.x*4096);
ThisFrame.vy=round(ThisQuat.y*4096);
ThisFrame.vz=round(ThisQuat.z*4096);
ThisFrame.vw=round(ThisQuat.w*4096);
FrameList.Idx[i]=QuatList.Add(ThisFrame);
QuatCount++;
}
ThisAnim.BoneAnim.push_back(FrameList);
}
int ChildCount=ThisNode.GetPruneChildCount();
for (int Loop=0;Loop<ChildCount;Loop++) ProcessSkelAnim(Scene,ThisAnim,ThisNode.PruneChildList[Loop]);
}
//***************************************************************************
void CMkAnim3d::Write(GString &Filename)
{
int Anim,AnimCount=AnimList.size();
sAnim3dFileHdr FileHdr;
sAnim3dHdr Hdr;
File=fopen(Filename,"wb");
// Write Dummy FileHdr
FileHdr.AnimCount=AnimCount;
FileHdr.BoneCount=BoneCount;
fwrite(&FileHdr,1,sizeof(sAnim3dFileHdr),File);
// Write Dummy AnimHdrs
for (Anim=0; Anim<AnimCount; Anim++)
{
fwrite(&Hdr,1,sizeof(sAnim3dHdr),File);
}
// Write QuatTable
FileHdr.QuatTable=(sQuat*)WriteQuatTable();
// Write Movements
for (Anim=0; Anim<AnimCount; Anim++)
{
AnimList[Anim].MoveOfs=WriteMove(AnimList[Anim]);
}
// Write Anims (u16 can cause address errors, so write last
for (Anim=0; Anim<AnimCount; Anim++)
{
AnimList[Anim].AnimOfs=WriteAnim(AnimList[Anim]);
}
// ReWrite FileHdr
fseek(File, 0, SEEK_SET);
fwrite(&FileHdr,1,sizeof(sAnim3dFileHdr),File);
// Rewrite Dummy AnimHdrs
for (Anim=0; Anim<AnimCount; Anim++)
{
Hdr.FrameCount=AnimList[Anim].FrameCount;
Hdr.Move=(s32*)AnimList[Anim].MoveOfs;
Hdr.Anim=(u16*)AnimList[Anim].AnimOfs;
fwrite(&Hdr,1,sizeof(sAnim3dHdr),File);
}
fclose(File);
}
//***************************************************************************
int CMkAnim3d::WriteMove(sAnim const &ThisAnim)
{
int Pos=ftell(File);
for (int Frame=0; Frame<ThisAnim.FrameCount; Frame++)
{
s32 ThisMove=ThisAnim.Move[Frame];
fwrite(&ThisMove,1,sizeof(s32),File);
// printf("%i %i %i\n",ThisMove.vx,ThisMove.vy,ThisMove.vz);
}
return(Pos);
}
//***************************************************************************
int CMkAnim3d::WriteAnim(sAnim const &ThisAnim)
{
int Pos=ftell(File);
for (int Frame=0; Frame<ThisAnim.FrameCount; Frame++)
{
for (int Bone=0; Bone<BoneCount; Bone++)
{
u16 ThisIdx=ThisAnim.BoneAnim[Bone].Idx[Frame];
fwrite(&ThisIdx,1,sizeof(u16),File);
}
}
return(Pos);
}
//***************************************************************************
int CMkAnim3d::WriteQuatTable()
{
int Pos=ftell(File);
int ListSize=QuatList.size();
for (int i=0; i<ListSize; i++)
{
sQuat &ThisQuat=QuatList[i];
fwrite(&ThisQuat,1,sizeof(sQuat),File);
}
//------------
printf("%i Anims\n",AnimList.size());
printf("QuatCount=%i\t=%i\n",QuatCount,QuatCount*sizeof(sQuat));
printf("ListSize=%i\t=%i\n",ListSize,(ListSize*sizeof(sQuat))+(QuatCount*sizeof(u16)));
return(Pos);
}
//***************************************************************************
void CMkAnim3d::WriteInclude(GString const &Filename)
{
GString Upper=Filename;
Upper.Upper();
GFName Name=Upper;
File=fopen(Filename,"wt");
fprintf(File,"// %s Header\n",Name.File());
fprintf(File,"\n");
fprintf(File,"#ifndef\t__ANIM_%s_HEADER__\n",Name.File());
fprintf(File,"#define\t__ANIM_%s_HEADER__\n",Name.File());
fprintf(File,"\n");
fprintf(File,"\n");
fprintf(File,"enum\tANIM_%s_LIST\n",Name.File());
fprintf(File,"{\n");
int ListSize=AnimList.size();
for (int i=0; i<ListSize; i++)
{
sAnim &ThisAnim=AnimList[i];
fprintf(File,"\tANIM_%s_%s",Name.File(),ThisAnim.Name);
if (i==0)
{
fprintf(File,"=0");
}
fprintf(File,",\n");
}
fprintf(File,"};\n");
fprintf(File,"\n");
fprintf(File,"#endif\n");
fclose(File);
}
//***************************************************************************
//***************************************************************************
//***************************************************************************
void Usage(char *ErrStr)
{
printf("\nMkAnim3d: by Dave\n");
printf("Usage: MkAnim3d <file> [ <file>.. ] [ switches.. ]\n");
printf("Switches:\n");
printf(" -o:[FILE] Set output File\n");
printf(" -d: Enable Debug output\n");
printf(" -s: Set Scale\n");
GObject::Error(ERR_FATAL,ErrStr);
}
//***************************************************************************
int main (int argc, char *argv[])
{
CMkAnim3d AnimBank;
CommandLine(argc,argv,CycleCommands);
if (OutStr.Empty()) Usage("No Output File Set\n");
vector<GString> const &Files = MyFiles.GetFileInfoVector();
for (int Loop=0; Loop<Files.size(); Loop++)
{
AnimBank.Add(Files[Loop]);
}
AnimBank.Write(OutStr);
if (!IncludeFile.Empty())
{
AnimBank.WriteInclude(IncludeFile);
}
return 0;
}