- Added libraries from formats and libvitaboy
This commit is contained in:
Tony Bark 2024-04-28 05:33:13 -04:00
parent 66ce473514
commit 5efdb29315
101 changed files with 11711 additions and 10889 deletions

View file

@ -0,0 +1 @@
Fatbag <X-Fi6@phppoll.org>

View file

@ -0,0 +1,15 @@
libvitaboy 1.0.1 (2012-03-10) Fatbag
* Corrected the BlendVertices function; blend vertices tug real vertices, not the other way around
* Interleaved all vertex data (coords, texcoords, normals, blend weights) into the VertexData array
* Made reading floats cross-platform (on modern architectures that use IEEE floats) by using unions
libvitaboy 1.0.0 (2012-03-04) Fatbag
* First stable release
* Read support for ANIM, APR, BND, COL, HAG, MESH, OFT, PO, SKEL
* Working rendering and animation of characters in OpenGL
* Basic keyboard controls
* Support for environments: MinGW
* Support for platforms: i686, x86-64

View file

@ -0,0 +1,51 @@
cmake_minimum_required(VERSION 2.6)
project(libvitaboy)
set(LIBVITABOY_SERIES 0)
set(LIBVITABOY_MAJOR 0)
set(LIBVITABOY_MINOR 1)
set(LIBVITABOY_SOURCES
anim.cpp
apr.cpp
bnd.cpp
col.cpp
hag.cpp
libvitaboy.cpp
mesh.cpp
oft.cpp
po.cpp
skel.cpp
)
if(WIN32)
set(LIBVITABOY_SOURCES ${LIBVITABOY_SOURCES} resource.rc)
else()
add_definitions(-Dstricmp=strcasecmp)
endif()
include_directories(${LIBGLDEMO_INCLUDE} ${FILEHANDLER_INCLUDE})
#### Static library (uncomment to build)
#add_library(libvitaboy_static STATIC ${LIBVITABOY_SOURCES})
#set_target_properties(libvitaboy_static PROPERTIES
# OUTPUT_NAME "vitaboy"
# CLEAN_DIRECT_OUTPUT 1)
add_library(libvitaboy_shared SHARED ${LIBVITABOY_SOURCES})
if(WIN32)
set_target_properties(libvitaboy_shared PROPERTIES OUTPUT_NAME "vitaboy${LIBVITABOY_SERIES}")
else()
set_target_properties(libvitaboy_shared PROPERTIES OUTPUT_NAME "vitaboy")
endif()
set_target_properties(libvitaboy_shared PROPERTIES
COMPILE_FLAGS "-fvisibility=default"
VERSION ${LIBVITABOY_SERIES}.${LIBVITABOY_MAJOR}.${LIBVITABOY_MINOR}
PREFIX "lib"
IMPORT_PREFIX "lib"
CLEAN_DIRECT_OUTPUT 1)
add_executable(vbparse vbparse.cpp)
target_link_libraries(vbparse libvitaboy_shared FileHandler_shared)
add_executable(Renderer ${GLDEMO_EXE} Renderer.cpp)
target_link_libraries(Renderer libvitaboy_shared ${GLDEMO_LINK} FileHandler_shared m)

View file

@ -0,0 +1,15 @@
libvitaboy - Open source OpenGL TSO character animation library
Version 1.0.1
Copyright (c) 2012 Niotso Project <http://niotso.org/>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

67
library/libvitaboy/README Normal file
View file

@ -0,0 +1,67 @@
***************************************************************************
* ** libvitaboy - Open source OpenGL TSO character animation library ** *
* ** Copyright (c) 2012 Drew D'Addesio ("Fatbag", <X-Fi6@phppoll.org>) ** *
* *
* Use and distribution of all files in the "include" and "lib" folders *
* are governed under the ISC License, included with this source code in *
* "COPYING". *
* *
* All other files included but not aforementioned are not copyrighted, *
* and are distributed into the public domain. *
***************************************************************************
libvitaboy is a cross-platform C++ library for parsing the various character rendering formats used in The Sims Online and using
that information to render and animate the 3D characters of the game using OpenGL.
Formats include:
(*) ANIM (Animation)
(*) APR (Appearance)
(*) BND (Binding)
(*) COL (Collection)
(*) HAG (Hand Group)
(*) MESH (Mesh)
(*) OFT (Outfit)
(*) PO (Purchasable Outfit)
(*) SKEL (Skeleton)
1. What this library will do for you
You can use this library to render a character in a predetermined location.
2. Compiling
Compiling is straightforward. The Makefiles and project files should already be set up for you, and are easy to tweak.
Before compiling the library, make your changes to config.h to specify what's compiled in.
a. Compiling from a Makefile
Makefiles are listed in the top directory in the format Makefile.$(PLATFORM). Just copy the one applicable to your platform
to the destination file "Makefile" and run GNU make.
b. Compiling from a project file
Project files are held within their own directories. They can be opened up with the target IDE and be compiled by
invoking the compile action of that IDE.
c. Compiling using your own Makefile or project file
It's possible no such file exists for your platform. In this case, look at whichever Makefile is most relevant to your
platform, copy all source files down (.cpp, .hpp, ...), and add it your own Makefile or project. In theory,
it should work. :)
libvitaboy is intended to work with any C++ compiler. If not, and the compiler is not only modern and popular but also free
software (gratis, libre, open source software), please report it as a bug.
3. Useful links
libvitaboy is hosted by and maintained by the Niotso project.
Home page: <http://www.niotso.org/>
Don Hopkins documentation:
(*) http://www.donhopkins.com/drupal/node/20 [Sims Character Animation File Format]
(*) http://www.donhopkins.com/drupal/node/21 [Details on The Sims Character Animation File Format and Rendering]
(*) http://www.donhopkins.com/drupal/node/19 [Sims VitaBoy Character Animation Library Documentation]
(*) http://www.donhopkins.com/home/movies/ [Index of Archived Streaming QuickTime Movies]

View file

@ -0,0 +1,441 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
Renderer.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
Instructions:
You must have the following files in the same directory as the Renderer binary:
Skeleton:
* skeleton.skel ("adult.skel" in ./avatardata/skeletons/)
Meshes:
* body.mesh (pick one from ./avatardata/bodies/meshes/)
* head.mesh (pick one from ./avatardata/heads/meshes/)
* lhand.mesh (pick one from ./avatardata/hands/meshes/)
* rhand.mesh (pick one from ./avatardata/hands/meshes/)
Textures:
* body.jpg (pick one from ./avatardata/bodies/textures/)
* head.jpg (pick one from ./avatardata/heads/textures/)
* hand.jpg (pick one from ./avatardata/hands/textures/)
Animation:
* animation.anim (pick one from ./avatardata/animations/)
==== Controls ====
Arrow keys: Rotate the sim
i,j,k,l: Translate the sim around the screen
z,x: Rotate the sim like a clock
a,s: Zoom in, out
q: Toggle skeleton
n: Animate the character
F11: Enter/leave fullscreen
*/
#include <math.h>
#include <FileHandler.hpp>
#include <libgldemo.h>
#include "libvitaboy.hpp"
static float zoom = -10;
struct BasicVertex_t {
float x, y, z;
};
struct CharacterPlacement_t {
BasicVertex_t Translation;
BasicVertex_t Rotation;
};
static CharacterPlacement_t Character = {{0,-3,0}, {0,0,0}};
static Skeleton_t Skeleton;
static const unsigned TextureCount = 3;
static unsigned texture[3];
enum { Texture_Body, Texture_Head, Texture_Hand };
static const char* const TexturePaths[] = {"body.jpg", "head.jpg", "hand.jpg"};
static const unsigned MeshCount = 4;
static Mesh_t Meshes[4];
enum { Mesh_Body, Mesh_Head, Mesh_LHand, Mesh_RHand };
static const char* const MeshPaths[] = {"body.mesh", "head.mesh", "lhand.mesh", "rhand.mesh" };
static const unsigned Mesh_UseTexture[] = { Texture_Body, Texture_Head, Texture_Hand, Texture_Hand };
static const char* const MeshActivate[] = {NULL, "HEAD", "L_HAND", "R_HAND"};
static Animation_t Animation;
static float AnimationTime = 0;
static bool ShowMesh = true;
static bool ShowSkeleton = true;
static bool PressedQ = false;
static void DisplayFileError(const char * Filename){
const char * Message;
switch(File::Error){
case FERR_NOT_FOUND:
Message = "%s does not exist.";
break;
case FERR_OPEN:
Message = "%s could not be opened for reading.";
break;
case FERR_BLANK:
case FERR_UNRECOGNIZED:
case FERR_INVALIDDATA:
Message = "%s is corrupt or invalid.";
break;
case FERR_MEMORY:
Message = "Memory for %s could not be allocated.";
break;
default:
Message = "%s could not be read.";
break;
}
char Buffer[1024];
sprintf(Buffer, Message, Filename);
DemoErrorBox(Buffer);
}
static int LoadTextures()
{
glGenTextures(3, texture);
for(int i=0; i<3; i++){
Image_t * Image = File::ReadImageFile(TexturePaths[i]);
if(!Image){
DisplayFileError(TexturePaths[i]);
return false;
}
glBindTexture(GL_TEXTURE_2D, texture[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->Width, Image->Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->Data);
free(Image->Data);
free(Image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
return 1;
}
static int InitGL()
{
if(!LoadTextures())
return false;
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glEnable(GL_RESCALE_NORMAL);
glDisable(GL_BLEND);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glFrontFace(GL_CW);
return 1;
}
static int ResizeScene(uint16_t width, uint16_t height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);
// glScalef(-1.0f, 1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 1;
}
static void TransformVertices(Bone_t& Bone)
{
glTranslatef(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z);
float Matrix[16];
FindQuaternionMatrix(Matrix, &Bone.Rotation);
glMultMatrixf(Matrix);
unsigned MeshIndex = 0;
unsigned BoneIndex;
for(unsigned i=1; i<MeshCount; i++){
if(!strcmp(Bone.Name, MeshActivate[i])){
MeshIndex = i;
break;
}
}
Mesh_t& Mesh = Meshes[MeshIndex];
for(BoneIndex=0; BoneIndex<Mesh.BindingCount; BoneIndex++){
if(!strcmp(Bone.Name, Mesh.BoneNames[Mesh.BoneBindings[BoneIndex].BoneIndex]))
break;
}
if(BoneIndex < Mesh.BindingCount){
for(unsigned i=0; i<Mesh.BoneBindings[BoneIndex].RealVertexCount; i++){
unsigned VertexIndex = Mesh.BoneBindings[BoneIndex].FirstRealVertex + i;
Vertex_t& RelativeVertex = Mesh.VertexData[VertexIndex];
Vertex_t& AbsoluteVertex = Mesh.TransformedVertexData[VertexIndex];
glTranslatef(RelativeVertex.Coord.x, RelativeVertex.Coord.y, RelativeVertex.Coord.z);
glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
AbsoluteVertex.Coord.x = Matrix[12];
AbsoluteVertex.Coord.y = Matrix[13];
AbsoluteVertex.Coord.z = Matrix[14];
glTranslatef(-RelativeVertex.Coord.x, -RelativeVertex.Coord.y, -RelativeVertex.Coord.z);
}
for(unsigned i=0; i<Mesh.BoneBindings[BoneIndex].BlendVertexCount; i++){
unsigned VertexIndex = Mesh.RealVertexCount + Mesh.BoneBindings[BoneIndex].FirstBlendVertex + i;
Vertex_t& RelativeVertex = Mesh.VertexData[VertexIndex];
Vertex_t& AbsoluteVertex = Mesh.TransformedVertexData[VertexIndex];
glTranslatef(RelativeVertex.Coord.x, RelativeVertex.Coord.y, RelativeVertex.Coord.z);
glGetFloatv(GL_MODELVIEW_MATRIX, Matrix);
AbsoluteVertex.Coord.x = Matrix[12];
AbsoluteVertex.Coord.y = Matrix[13];
AbsoluteVertex.Coord.z = Matrix[14];
glTranslatef(-RelativeVertex.Coord.x, -RelativeVertex.Coord.y, -RelativeVertex.Coord.z);
}
}
if(Bone.ChildrenCount == 1){
TransformVertices(*Bone.Children[0]);
}else if(Bone.ChildrenCount > 1){
for(unsigned i=0; i<Bone.ChildrenCount; i++){
glPushMatrix();
TransformVertices(*Bone.Children[i]);
glPopMatrix();
}
}
}
static void BlendVertices()
{
for(unsigned i=0; i<MeshCount; i++){
Mesh_t& Mesh = Meshes[i];
for(unsigned i=0; i<Mesh.BlendVertexCount; i++){
Vertex_t& BlendVertex = Mesh.TransformedVertexData[Mesh.RealVertexCount + i];
float Weight = BlendVertex.BlendData.Weight;
Vertex_t& RealVertex = Mesh.TransformedVertexData[BlendVertex.BlendData.OtherVertex];
RealVertex.Coord.x =
Weight * BlendVertex.Coord.x +
(1-Weight) * RealVertex.Coord.x;
RealVertex.Coord.y =
Weight * BlendVertex.Coord.y +
(1-Weight) * RealVertex.Coord.y;
RealVertex.Coord.z =
Weight * BlendVertex.Coord.z +
(1-Weight) * RealVertex.Coord.z;
}
}
}
static void DrawMeshes()
{
glPointSize(2.0);
glColor3f(1.0, 1.0, 1.0);
glPushMatrix();
glLoadIdentity();
TransformVertices(Skeleton.Bones[0]);
glPopMatrix();
BlendVertices();
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
for(unsigned i=0; i<MeshCount; i++){
glBindTexture(GL_TEXTURE_2D, texture[Mesh_UseTexture[i]]);
glVertexPointer(3, GL_FLOAT, sizeof(Vertex_t), &Meshes[i].TransformedVertexData[0].Coord);
glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex_t), &Meshes[i].TransformedVertexData[0].TextureCoord);
glDrawElements(GL_TRIANGLES, Meshes[i].FaceCount*3, GL_UNSIGNED_INT, Meshes[i].FaceData);
}
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
static void AdvanceFrame(Skeleton_t& Skeleton, Animation_t& Animation, float TimeDelta)
{
float Duration = (float)Animation.Motions[0].FrameCount/30;
AnimationTime += TimeDelta;
AnimationTime = fmodf(AnimationTime, Duration); //Loop the animation
for(unsigned i=0; i<Animation.MotionsCount; i++){
unsigned BoneIndex = FindBone(Skeleton, Animation.Motions[i].BoneName, Skeleton.BoneCount);
if(BoneIndex == (unsigned)-1) continue;
Bone_t& Bone = Skeleton.Bones[BoneIndex];
unsigned Frame = AnimationTime*30;
float FractionShown = AnimationTime*30 - Frame;
unsigned NextFrame = (Frame+1 != Animation.Motions[0].FrameCount) ? Frame+1 : 0;
if(Animation.Motions[i].HasTranslation){
Translation_t& Translation = Animation.Motions[i].Translations[Frame];
Translation_t& NextTranslation = Animation.Motions[i].Translations[NextFrame];
Bone.Translation.x = (1-FractionShown)*Translation.x + FractionShown*NextTranslation.x;
Bone.Translation.y = (1-FractionShown)*Translation.y + FractionShown*NextTranslation.y;
Bone.Translation.z = (1-FractionShown)*Translation.z + FractionShown*NextTranslation.z;
}
if(Animation.Motions[i].HasRotation){
Rotation_t& Rotation = Animation.Motions[i].Rotations[Frame];
Rotation_t& NextRotation = Animation.Motions[i].Rotations[NextFrame];
//Use nlerp to interpolate
float w1 = 1.0f - FractionShown, w2 = FractionShown;
if(DotProduct(&Rotation, &NextRotation) < 0)
w1 *= -1;
Bone.Rotation.x = w1*Rotation.x + w2*NextRotation.x;
Bone.Rotation.y = w1*Rotation.y + w2*NextRotation.y;
Bone.Rotation.z = w1*Rotation.z + w2*NextRotation.z;
Bone.Rotation.w = w1*Rotation.w + w2*NextRotation.w;
Normalize(&Bone.Rotation);
}
}
}
static void DrawBonesSkeleton(Bone_t& Bone)
{
glPointSize(5.0);
glTranslatef(Bone.Translation.x, Bone.Translation.y, Bone.Translation.z);
float RotationMatrix[16];
FindQuaternionMatrix(RotationMatrix, &Bone.Rotation);
glMultMatrixf(RotationMatrix);
if(!strcmp(Bone.Name, "ROOT"))
glColor3f(1.0, 0.0, 0.0);
else if(!strcmp(Bone.Name, "HEAD"))
glColor3f(1.0, 1.0, 0.0);
else
glColor3f(0.0, 1.0, 0.0);
glBegin(GL_POINTS); glVertex3f(0, 0, 0); glEnd();
if(Bone.ChildrenCount == 1){
DrawBonesSkeleton(*Bone.Children[0]);
}else if(Bone.ChildrenCount > 1){
for(unsigned i=0; i<Bone.ChildrenCount; i++){
glPushMatrix();
DrawBonesSkeleton(*Bone.Children[i]);
glPopMatrix();
}
}
}
static void DrawSkeleton()
{
glPushMatrix();
DrawBonesSkeleton(Skeleton.Bones[0]);
glPopMatrix();
}
static int DrawScene(float TimeDelta, uint8_t keys[256])
{
//Handle user interaction
if(keys['A']) /*{if(zoom <=-1.0f) zoom+=0.05f; }*/ zoom+=3*TimeDelta;
if(keys['S']) /*{if(zoom >=-10.0f) zoom-=0.05f; }*/ zoom-=3*TimeDelta;
if(keys[KEY_UP]){ if((Character.Rotation.x-=60*TimeDelta) <=-360) Character.Rotation.x+=360; }
if(keys[KEY_DOWN]){ if((Character.Rotation.x+=60*TimeDelta) >=360) Character.Rotation.x-=360; }
if(keys[KEY_LEFT]){ if((Character.Rotation.y-=60*TimeDelta) <=-360) Character.Rotation.y+=360; }
if(keys[KEY_RIGHT]){ if((Character.Rotation.y+=60*TimeDelta) >=360) Character.Rotation.y-=360; }
if(keys['X']){ if((Character.Rotation.z-=60*TimeDelta) <=-360) Character.Rotation.z+=360; }
if(keys['Z']){ if((Character.Rotation.z+=60*TimeDelta) >=360) Character.Rotation.z-=360; }
if(keys['K']){ Character.Translation.y-=3*TimeDelta; }
if(keys['I']){ Character.Translation.y+=3*TimeDelta; }
if(keys['J']){ Character.Translation.x-=3*TimeDelta; }
if(keys['L']){ Character.Translation.x+=3*TimeDelta; }
if(keys['Q']){ if(!PressedQ){ PressedQ = 1; ShowSkeleton = !ShowSkeleton; }} else PressedQ = 0;
if(keys['N']){ AdvanceFrame(Skeleton, Animation, TimeDelta); }
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear the screen and the depth buffer
glLoadIdentity();
glTranslatef(Character.Translation.x, Character.Translation.y, zoom + Character.Translation.z);
glRotatef(Character.Rotation.x,1.0f,0.0f,0.0f);
glRotatef(Character.Rotation.y,0.0f,1.0f,0.0f);
glRotatef(Character.Rotation.z,0.0f,0.0f,1.0f);
if(ShowMesh){
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glColor3f(1.0, 1.0, 1.0);
DrawMeshes();
}
if(ShowSkeleton){
glClear(GL_DEPTH_BUFFER_BIT);
DrawSkeleton();
}
return true;
}
static bool Read(const char * Filename, uint8_t ** InData){
*InData = File::ReadFile(Filename);
if(*InData != NULL){
VBFile.set(*InData, File::FileSize);
return true;
}
DisplayFileError(Filename);
return false;
}
static int Startup()
{
uint8_t * InData;
if(!Read("skeleton.skel", &InData))
return 0;
ReadSkeleton(Skeleton);
free(InData);
for(unsigned i=0; i<MeshCount; i++){
if(!Read(MeshPaths[i], &InData))
return 0;
ReadMesh(Meshes[i]);
free(InData);
}
if(!Read("animation.anim", &InData))
return 0;
ReadAnimation(Animation);
free(InData);
AdvanceFrame(Skeleton, Animation, 0);
return 1;
}
extern "C" {
const DemoConfig Demo = {
"libvitaboy - Renderer", //Title
640,480, //Width, Height
Startup, //Startup
NULL, //Shutdown
InitGL, //InitGL
ResizeScene, //ResizeScene
DrawScene //DrawScene
};
}

10
library/libvitaboy/THANKS Normal file
View file

@ -0,0 +1,10 @@
--------------------------------|----------------------------------------------------------------
| Thanks to | for |
|--------------------------------|----------------------------------------------------------------|
| Don Hopkins | Kickstarting The Sims 1 customization, encouraging fine |
| | individuals to document the game, and most importantly, |
| | sharing with us his documentation of his VitaBoy skeletal |
| | character animation library used in The Sims 1, in the form |
| | of articles and videos. Dozens of thanks from each one of us. |
| (*) <http://www.donhopkins.com/> |
-------------------------------------------------------------------------------------------------

159
library/libvitaboy/anim.cpp Normal file
View file

@ -0,0 +1,159 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
anim.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
static unsigned motionnumber = 0;
void ReadAnimation(Animation_t& Animation){
printf("===== Animation =====\n");
Animation.Version = VBFile.readint32();
printf("Version: %u\n", Animation.Version);
Animation.Name = VBFile.readstring2();
printf("Name: %s\n", Animation.Name);
Animation.Duration = VBFile.readfloat();
printf("Duration: %g\n", Animation.Duration/1000);
Animation.Distance = VBFile.readfloat();
printf("Distance: %g\n", Animation.Distance);
Animation.IsMoving = VBFile.readint8();
printf("IsMoving: %u\n", Animation.IsMoving);
Animation.TranslationsCount = VBFile.readint32();
printf("TranslationsCount: %u\n", Animation.TranslationsCount);
Animation.TranslationsOffset = VBFile.getpos();
VBFile.seekto(Animation.TranslationsOffset + 12*Animation.TranslationsCount);
Animation.RotationsCount = VBFile.readint32();
printf("RotationsCount: %u\n", Animation.RotationsCount);
Animation.RotationsOffset = VBFile.getpos();
VBFile.seekto(Animation.RotationsOffset + 16*Animation.RotationsCount);
Animation.MotionsCount = VBFile.readint32();
printf("MotionsCount: %u\n", Animation.MotionsCount);
Animation.Motions = (Motion_t*) malloc(Animation.MotionsCount * sizeof(Motion_t));
for(unsigned i=0; i<Animation.MotionsCount; i++){
ReadMotion(Animation, Animation.Motions[i]);
}
}
void ReadMotion(Animation_t& Animation, Motion_t& Motion){
motionnumber++;
printf("\n\n [Motion %u]\n", motionnumber);
Motion.Unknown = VBFile.readint32();
printf(" | Unknown: %u\n", Motion.Unknown);
Motion.BoneName = VBFile.readstring();
printf(" | BoneName: %s\n", Motion.BoneName);
Motion.FrameCount = VBFile.readint32();
printf(" | FrameCount: %u\n", Motion.FrameCount);
Motion.Duration = VBFile.readfloat();
printf(" | Duration: %g\n", Motion.Duration/1000);
Motion.HasTranslation = VBFile.readint8();
printf(" | HasTranslation: %u\n", Motion.HasTranslation);
Motion.HasRotation = VBFile.readint8();
printf(" | HasRotation: %u\n", Motion.HasRotation);
Motion.FirstTranslation = VBFile.readint32();
if(Motion.HasTranslation)
printf(" | FirstTranslation: %u\n", Motion.FirstTranslation);
Motion.FirstRotation = VBFile.readint32();
if(Motion.HasRotation)
printf(" | FirstRotation: %u\n", Motion.FirstRotation);
if(Motion.HasTranslation){
Motion.Translations = (Translation_t*) malloc(Motion.FrameCount * sizeof(Translation_t));
unsigned pos = VBFile.getpos();
VBFile.seekto(Animation.TranslationsOffset + 12*Motion.FirstTranslation);
for(unsigned i=0; i<Motion.FrameCount; i++){
Motion.Translations[i].x = -VBFile.readfloat();
Motion.Translations[i].y = VBFile.readfloat();
Motion.Translations[i].z = VBFile.readfloat();
}
VBFile.seekto(pos);
}
if(Motion.HasRotation){
Motion.Rotations = (Rotation_t*) malloc(Motion.FrameCount * sizeof(Rotation_t));
unsigned pos = VBFile.getpos();
VBFile.seekto(Animation.RotationsOffset + 16*Motion.FirstRotation);
for(unsigned i=0; i<Motion.FrameCount; i++){
Motion.Rotations[i].x = VBFile.readfloat();
Motion.Rotations[i].y = -VBFile.readfloat();
Motion.Rotations[i].z = -VBFile.readfloat();
Motion.Rotations[i].w = VBFile.readfloat();
}
VBFile.seekto(pos);
}
Motion.HasPropsLists = VBFile.readint8();
printf(" | HasPropsLists: %u\n", Motion.HasPropsLists);
if(Motion.HasPropsLists){
ReadPropsLists(Motion);
}
Motion.HasTimePropsLists = VBFile.readint8();
printf(" | HasTimePropsLists: %u\n", Motion.HasTimePropsLists);
if(Motion.HasTimePropsLists){
ReadTimePropsLists(Motion);
}
}
void ReadPropsList(PropsList_t& PropsList){
unsigned count = PropsList.PropsCount = VBFile.readint32();
printf(" | | | PropsCount: %u\n", count);
PropsList.Props = (Prop_t*) malloc(count * sizeof(Prop_t));
for(unsigned i=0; i<count; i++){
printf(" | | | [Prop %u]\n", i+1);
ReadPropEntries(PropsList.Props[i]);
}
}
void ReadPropsLists(Motion_t& Motion){
unsigned count = Motion.PropsListsCount = VBFile.readint32();
Motion.PropsLists = (PropsList_t*) malloc(count * sizeof(PropsList_t));
for(unsigned i=0; i<count; i++){
ReadPropsList(Motion.PropsLists[i]);
}
}
void ReadTimePropsList(TimePropsList_t& TimePropsList){
unsigned count = TimePropsList.TimePropsCount = VBFile.readint32();
printf(" | | TimePropsCount: %u\n", count);
TimePropsList.TimeProps = (TimeProp_t*) malloc(count * sizeof(TimeProp_t));
for(unsigned i=0; i<count; i++){
printf(" | | [TimeProp %u]\n", i+1);
TimePropsList.TimeProps[i].ID = VBFile.readint32();
printf(" | | | ID: %u\n", TimePropsList.TimeProps[i].ID);
ReadPropsList(TimePropsList.TimeProps[i].PropsList);
}
}
void ReadTimePropsLists(Motion_t& Motion){
unsigned count = Motion.TimePropsListsCount = VBFile.readint32();
printf(" | TimePropsListsCount: %u\n", count);
Motion.TimePropsLists = (TimePropsList_t*) malloc(count * sizeof(TimePropsList_t));
for(unsigned i=0; i<count; i++){
printf(" | [TimePropsList %u]\n", i+1);
ReadTimePropsList(Motion.TimePropsLists[i]);
}
}

View file

@ -0,0 +1,35 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
apr.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadAppearance(Appearance_t& Appearance){
printf("\n========== Appearance ==========\n");
Appearance.Version = VBFile.readint32();
printf("Version: %u\n", Appearance.Version);
ReadAsset(Appearance.Thumbnail, NOGROUP);
Appearance.BindingCount = VBFile.readint32();
printf("Binding count: %u\n", Appearance.BindingCount);
Appearance.Bindings = (Asset_t*) malloc(Appearance.BindingCount * sizeof(Asset_t));
for(unsigned i=0; i<Appearance.BindingCount; i++){
printf("\n [Binding %u]\n", i);
ReadAsset(Appearance.Bindings[i], NOGROUP);
}
}

View file

@ -0,0 +1,40 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
bnd.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadBinding(Binding_t& Binding){
printf("\n========== Binding ==========\n");
Binding.Version = VBFile.readint32();
printf("Version: %u\n", Binding.Version);
Binding.BoneName = VBFile.readstring();
printf("Bone name: %s\n", Binding.BoneName);
Binding.MeshDef = VBFile.readint32();
if(Binding.MeshDef){
printf("\n Mesh:\n");
ReadAsset(Binding.Mesh, READGROUP);
}
Binding.AppearanceDef = VBFile.readint32();
if(Binding.AppearanceDef){
printf("\n Appearance:\n");
ReadAsset(Binding.Appearance, READGROUP);
}
}

View file

@ -0,0 +1,33 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
col.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadCollection(Collection_t& Collection){
printf("\n========== Collection ==========\n");
Collection.POCount = VBFile.readint32();
printf("Purchasable Outfit count: %u\n", Collection.POCount);
Collection.PurchasableOutfits = (PODef_t*) malloc(Collection.POCount * sizeof(PODef_t));
for(unsigned i=0; i<Collection.POCount; i++){
printf("\n [Purchasable Outfit %u]\n", i);
Collection.PurchasableOutfits[i].Index = VBFile.readint32();
printf(" | Index: %u\n", Collection.PurchasableOutfits[i].Index);
ReadAsset(Collection.PurchasableOutfits[i].PO, NOGROUP);
}
}

View file

@ -0,0 +1,11 @@
/* config.h - libvitaboy build configuration */
/* Name of package */
#define PACKAGE "libvitaboy"
/* Version number of package */
#define VERSION_A 1
#define VERSION_B 0
#define VERSION_C 1
#define VERSION_STR "1.0.1"
#define REVISION 0

View file

@ -0,0 +1,28 @@
/*
libvitaboy - Copyright (c) 2012 Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadHandGroup(HandGroup_t& HandGroup){
printf("\n========== Hand Group ==========\n");
HandGroup.Version = VBFile.readint32();
printf("Version: %u\n", HandGroup.Version);
for(unsigned i=0; i<18; i++){
printf("\n [Purchasable Outfit %u]\n", i);
ReadAsset(HandGroup.HandAppearances[i], NOGROUP);
}
}

View file

@ -0,0 +1,93 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
libvitaboy.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <math.h>
#include "libvitaboy.hpp"
VBFile_t VBFile;
void ReadAsset(Asset_t& Asset, bool ReadGroup){
Asset.Group = (ReadGroup) ? VBFile.readint32() : 0xA96F6D42;
printf(" | Group: %u\n", Asset.Group);
Asset.File = VBFile.readint32();
printf(" | File: %u\n", Asset.File);
Asset.Type = VBFile.readint32();
printf(" | Type: %u\n", Asset.Type);
}
void ReadPropEntry(KeyValuePair_t& Entry){
Entry.Key = VBFile.readstring();
printf(" | | | | | Key: %s\n", Entry.Key);
Entry.Value = VBFile.readstring();
printf(" | | | | | Value: %s\n", Entry.Value);
}
void ReadPropEntries(Prop_t& Prop){
unsigned count = Prop.EntriesCount = VBFile.readint32();
printf(" | | | | EntriesCount: %u\n", Prop.EntriesCount);
Prop.Entries = (KeyValuePair_t*) malloc(count * sizeof(KeyValuePair_t));
for(unsigned i=0; i<count; i++){
printf(" | | | | [Entry %u]\n", i+1);
ReadPropEntry(Prop.Entries[i]);
}
}
float DotProduct(Rotation_t * q1, Rotation_t * q2){
return q1->x*q2->x + q1->y*q2->y + q1->z*q2->z + q1->w*q2->w;
}
void Normalize(Rotation_t * q){
float magnitude = q->x*q->x + q->y*q->y + q->z*q->z + q->w*q->w;
if(magnitude != 0){
magnitude = 1.0f/sqrt(magnitude);
q->x *= magnitude;
q->y *= magnitude;
q->z *= magnitude;
q->w *= magnitude;
}
}
void FindQuaternionMatrix(float * Matrix, Rotation_t * Quaternion){
float x2 = Quaternion->x * Quaternion->x;
float y2 = Quaternion->y * Quaternion->y;
float z2 = Quaternion->z * Quaternion->z;
float xy = Quaternion->x * Quaternion->y;
float xz = Quaternion->x * Quaternion->z;
float yz = Quaternion->y * Quaternion->z;
float wx = Quaternion->w * Quaternion->x;
float wy = Quaternion->w * Quaternion->y;
float wz = Quaternion->w * Quaternion->z;
Matrix[0] = 1.0f - 2.0f * (y2 + z2);
Matrix[1] = 2.0f * (xy - wz);
Matrix[2] = 2.0f * (xz + wy);
Matrix[3] = 0.0f;
Matrix[4] = 2.0f * (xy + wz);
Matrix[5] = 1.0f - 2.0f * (x2 + z2);
Matrix[6] = 2.0f * (yz - wx);
Matrix[7] = 0.0f;
Matrix[8] = 2.0f * (xz - wy);
Matrix[9] = 2.0f * (yz + wx);
Matrix[10] = 1.0f - 2.0f * (x2 + y2);
Matrix[11] = 0.0f;
Matrix[12] = 0.0f;
Matrix[13] = 0.0f;
Matrix[14] = 0.0f;
Matrix[15] = 1.0f;
}

View file

@ -0,0 +1,407 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
libvitaboy.hpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef LIBVITABOY_HPP
#define LIBVITABOY_HPP
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <FileHandler.hpp>
/****
** Bytestream
*/
class VBFile_t {
private:
const uint8_t *Buffer, *Position;
unsigned Size;
public:
inline void set(const void *_Buffer, unsigned _Size){
Buffer = (const uint8_t*) _Buffer;
Position = (const uint8_t*) _Buffer;
Size = _Size;
}
inline unsigned getpos(){
return Position-Buffer;
}
inline void seekto(unsigned offset){
Position = Buffer+offset;
}
inline void seekahead(unsigned count){
Position += count;
}
inline void seekback(unsigned count){
Position -= count;
}
inline uint32_t readint32(){
uint32_t value = (uint32_t)((Position[0]<<(8*3)) | (Position[1]<<(8*2)) | (Position[2]<<(8*1)) | (Position[3]<<(8*0)));
Position += 4;
return value;
}
inline uint32_t readint16(){
uint16_t value = (uint16_t)((Position[0]<<(8*1)) | (Position[1]<<(8*0)));
Position += 2;
return value;
}
inline uint32_t readint8(){
uint8_t value = (uint8_t)((Position[0]<<(8*0)));
Position += 1;
return value;
}
inline float readfloat(){
union { uint32_t i; float f; } value;
value.i = (uint32_t)((Position[0]<<(8*0)) | (Position[1]<<(8*1)) | (Position[2]<<(8*2)) | (Position[3]<<(8*3)));
Position += 4;
return value.f;
}
inline void readbytes(void* Destination, unsigned length){
memcpy(Destination, Position, length);
Position += length;
}
inline char* readstring(){
//Read a Pascal string with 1 length byte
unsigned length = readint8();
char *string = (char*) malloc(length+1);
readbytes(string, length);
string[length] = '\0';
return string;
}
inline char* readstring2(){
//Read a Pascal string with 2 length bytes
unsigned length = readint16();
char *string = (char*) malloc(length+1);
readbytes(string, length);
string[length] = '\0';
return string;
}
};
extern VBFile_t VBFile;
/****
** Common
*/
enum ReadGroup {
NOGROUP,
READGROUP
};
struct Translation_t {
float x, y, z;
};
struct Rotation_t {
float x, y, z, w;
};
struct KeyValuePair_t {
char * Key;
char * Value;
};
struct Prop_t {
uint32_t EntriesCount;
KeyValuePair_t * Entries;
};
struct PropsList_t {
uint32_t PropsCount;
Prop_t * Props;
};
void ReadAsset(Asset_t& Asset, bool ReadGroup);
void ReadPropEntry(KeyValuePair_t& Entry);
void ReadPropEntries(Prop_t& Prop);
void ReadPropsList(PropsList_t& PropsList);
float DotProduct(Rotation_t * q1, Rotation_t * q2);
void Normalize(Rotation_t * q);
void CombineQuaternions(Rotation_t * Destination, Rotation_t * Source);
void FindQuaternionMatrix(float * Matrix, Rotation_t * Quaternion);
/****
** Animation (*.anim)
*/
struct TimeProp_t {
uint32_t ID;
PropsList_t PropsList;
};
struct TimePropsList_t {
uint32_t TimePropsCount;
TimeProp_t * TimeProps;
};
struct Motion_t {
uint32_t Unknown;
char * BoneName;
uint32_t FrameCount;
float Duration; //Converted to seconds
uint8_t HasTranslation;
uint8_t HasRotation;
uint32_t FirstTranslation;
uint32_t FirstRotation;
Translation_t * Translations;
Rotation_t * Rotations;
uint8_t HasPropsLists;
uint32_t PropsListsCount;
PropsList_t * PropsLists;
uint8_t HasTimePropsLists;
uint32_t TimePropsListsCount;
TimePropsList_t * TimePropsLists;
};
struct Animation_t {
uint32_t Version;
char * Name;
float Duration; //Converted to seconds
float Distance;
uint8_t IsMoving;
uint32_t TranslationsCount;
uint32_t RotationsCount;
uint32_t MotionsCount;
unsigned TranslationsOffset;
unsigned RotationsOffset;
Motion_t * Motions;
};
void ReadAnimation(Animation_t& Animation);
void ReadMotion(Animation_t& Animation, Motion_t& Motion);
void ReadPropsLists(Motion_t& Motion);
void ReadTimePropsList(TimePropsList_t& TimePropsList);
void ReadTimePropsLists(Motion_t& Motion);
/****
** Appearance (*.apr)
*/
struct Appearance_t {
uint32_t Version;
Asset_t Thumbnail;
uint32_t BindingCount;
Asset_t * Bindings;
};
void ReadAppearance(Appearance_t& Appearance);
/****
** Binding (*.bnd)
*/
struct Binding_t {
uint32_t Version;
char * BoneName;
uint32_t MeshDef;
Asset_t Mesh;
uint32_t AppearanceDef;
Asset_t Appearance;
};
void ReadBinding(Binding_t& Binding);
/****
** Collection (*.col)
*/
struct PODef_t {
uint32_t Index;
Asset_t PO;
};
struct Collection_t {
uint32_t POCount;
PODef_t * PurchasableOutfits;
};
void ReadCollection(Collection_t& Collection);
/****
** Hand Group (*.hag)
*/
struct HandGroup_t {
uint32_t Version;
Asset_t HandAppearances[18];
};
void ReadHandGroup(HandGroup_t& HandGroup);
/****
** Mesh (*.mesh)
*/
struct TextureVertex_t {
float u, v;
};
struct Coord_t {
float x, y, z;
};
struct TextureCoord_t {
float u, v;
};
struct NormalCoord_t {
float x, y, z;
};
struct BlendData_t {
float Weight;
unsigned OtherVertex;
};
struct Vertex_t {
Coord_t Coord;
TextureCoord_t TextureCoord;
NormalCoord_t NormalCoord;
unsigned BoneIndex;
BlendData_t BlendData;
};
struct Face_t {
unsigned VertexA, VertexB, VertexC;
};
struct BoneBinding_t {
unsigned BoneIndex;
unsigned FirstRealVertex;
unsigned RealVertexCount;
unsigned FirstBlendVertex;
unsigned BlendVertexCount;
};
struct Mesh_t {
uint32_t Version;
uint32_t BoneCount;
char ** BoneNames;
uint32_t FaceCount;
Face_t * FaceData;
uint32_t BindingCount;
BoneBinding_t * BoneBindings;
uint32_t RealVertexCount;
uint32_t BlendVertexCount;
uint32_t TotalVertexCount;
Vertex_t * VertexData;
Vertex_t * TransformedVertexData;
};
void ReadMesh(Mesh_t& Mesh);
/****
** Outfit (*.oft)
*/
enum OutfitColor {
OutfitColor_Light,
OutfitColor_Medium,
OutfitColor_Dark
};
enum OutfitRegion {
OutfitRegion_Head = 0,
OutfitRegion_Body = 18
};
struct Outfit_t {
uint32_t Version;
uint32_t Unknown;
Asset_t Appearance[3];
uint32_t Group;
uint32_t Region;
};
void ReadOutfit(Outfit_t& Outfit);
/****
** Purchasable Outfit (*.po)
*/
struct PurchasableOutfit_t {
uint32_t Version;
uint32_t Unknown;
uint32_t OutfitDef;
Asset_t Outfit;
uint32_t CollectionDef;
Asset_t Collection;
};
void ReadPurchasableOutfit(PurchasableOutfit_t& PurchasableOutfit);
/****
** Skeleton (*.skel)
*/
struct Bone_t {
uint32_t Unknown;
char * Name;
char * ParentsName;
uint8_t HasProps;
PropsList_t PropsList;
Translation_t Translation;
Rotation_t Rotation;
uint32_t CanTranslate;
uint32_t CanRotate;
uint32_t CanBlend;
float WiggleValue;
float WigglePower;
unsigned ChildrenCount;
Bone_t ** Children;
};
struct Skeleton_t {
uint32_t Version;
char * Name;
uint16_t BoneCount;
Bone_t * Bones;
};
void ReadSkeleton(Skeleton_t& Bone);
void ReadBone(Skeleton_t& Skeleton, Bone_t& Bone, unsigned Index);
unsigned FindBone(Skeleton_t& Skeleton, const char * BoneName, unsigned Count);
#endif

View file

@ -0,0 +1,95 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
mesh.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadMesh(Mesh_t& Mesh){
printf("\n========== Mesh ==========\n");
Mesh.Version = VBFile.readint32();
printf("Version: %u\n", Mesh.Version);
Mesh.BoneCount = VBFile.readint32();
printf("BoneCount: %u\n", Mesh.BoneCount);
Mesh.BoneNames = (char**) malloc(Mesh.BoneCount * sizeof(char*));
for(unsigned i=0; i<Mesh.BoneCount; i++){
Mesh.BoneNames[i] = VBFile.readstring();
printf("| Bone %u: %s\n", i+1, Mesh.BoneNames[i]);
}
Mesh.FaceCount = VBFile.readint32();
printf("FaceCount: %u\n", Mesh.FaceCount);
Mesh.FaceData = (Face_t*) malloc(Mesh.FaceCount * sizeof(Face_t));
for(unsigned i=0; i<Mesh.FaceCount; i++){
Mesh.FaceData[i].VertexA = VBFile.readint32();
Mesh.FaceData[i].VertexB = VBFile.readint32();
Mesh.FaceData[i].VertexC = VBFile.readint32();
}
Mesh.BindingCount = VBFile.readint32();
Mesh.BoneBindings = (BoneBinding_t*) malloc(Mesh.BindingCount * sizeof(BoneBinding_t));
printf("BindingCount: %u\n", Mesh.BindingCount);
for(unsigned i=0; i<Mesh.BindingCount; i++){
Mesh.BoneBindings[i].BoneIndex = VBFile.readint32();
Mesh.BoneBindings[i].FirstRealVertex = VBFile.readint32();
Mesh.BoneBindings[i].RealVertexCount = VBFile.readint32();
Mesh.BoneBindings[i].FirstBlendVertex = VBFile.readint32();
Mesh.BoneBindings[i].BlendVertexCount = VBFile.readint32();
}
Mesh.RealVertexCount = VBFile.readint32();
printf("RealVertexCount: %u\n", Mesh.RealVertexCount);
TextureVertex_t * TextureVertexData = (TextureVertex_t*) malloc(Mesh.RealVertexCount * sizeof(TextureVertex_t));
for(unsigned i=0; i<Mesh.RealVertexCount; i++){
TextureVertexData[i].u = VBFile.readfloat();
TextureVertexData[i].v = -VBFile.readfloat();
}
Mesh.BlendVertexCount = VBFile.readint32();
printf("BlendVertexCount: %u\n", Mesh.BlendVertexCount);
BlendData_t * BlendData = (BlendData_t*) malloc(Mesh.BlendVertexCount * sizeof(BlendData_t));
for(unsigned i=0; i<Mesh.BlendVertexCount; i++){
BlendData[i].Weight = (float)VBFile.readint32()/0x8000;
BlendData[i].OtherVertex = VBFile.readint32();
}
Mesh.TotalVertexCount = VBFile.readint32();
printf("TotalVertexCount: %u\n", Mesh.TotalVertexCount);
Mesh.VertexData = (Vertex_t*) malloc(Mesh.TotalVertexCount * sizeof(Vertex_t));
Mesh.TransformedVertexData = (Vertex_t*) malloc(Mesh.TotalVertexCount * sizeof(Vertex_t));
for(unsigned i=0; i<Mesh.TotalVertexCount; i++){
Mesh.VertexData[i].Coord.x = -VBFile.readfloat();
Mesh.VertexData[i].Coord.y = VBFile.readfloat();
Mesh.VertexData[i].Coord.z = VBFile.readfloat();
Mesh.TransformedVertexData[i].NormalCoord.x = -VBFile.readfloat();
Mesh.TransformedVertexData[i].NormalCoord.y = VBFile.readfloat();
Mesh.TransformedVertexData[i].NormalCoord.z = VBFile.readfloat();
if(i<Mesh.RealVertexCount){
//Fixed vertex
Mesh.TransformedVertexData[i].TextureCoord.u = TextureVertexData[i].u;
Mesh.TransformedVertexData[i].TextureCoord.v = TextureVertexData[i].v;
}else{
//Blended vertex
Mesh.TransformedVertexData[i].BlendData.Weight = BlendData[i-Mesh.RealVertexCount].Weight;
Mesh.TransformedVertexData[i].BlendData.OtherVertex = BlendData[i-Mesh.RealVertexCount].OtherVertex;
}
}
free(TextureVertexData);
free(BlendData);
}

View file

@ -0,0 +1,39 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
oft.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadOutfit(Outfit_t& Outfit){
printf("\n========== Outfit ==========\n");
Outfit.Version = VBFile.readint32();
printf("Version: %u\n", Outfit.Version);
Outfit.Unknown = VBFile.readint32();
printf("Unknown: %u\n", Outfit.Unknown);
const char* Colors[] = {"Light", "Medium", "Dark"};
for(unsigned i=0; i<3; i++){
printf("\n [%s Appearance]\n", Colors[i]);
ReadAsset(Outfit.Appearance[i], NOGROUP);
}
Outfit.Group = VBFile.readint32();
printf("Group: %u\n", Outfit.Group);
Outfit.Region = VBFile.readint32();
printf("Region: %u\n", Outfit.Region);
}

40
library/libvitaboy/po.cpp Normal file
View file

@ -0,0 +1,40 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
po.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadPurchasableOutfit(PurchasableOutfit_t& PurchasableOutfit){
printf("\n========== Purchasable Outfit ==========\n");
PurchasableOutfit.Version = VBFile.readint32();
printf("Version: %u\n", PurchasableOutfit.Version);
PurchasableOutfit.Unknown = VBFile.readint32();
printf("Unknown: %u\n", PurchasableOutfit.Unknown);
PurchasableOutfit.OutfitDef = VBFile.readint32();
if(PurchasableOutfit.OutfitDef){
printf("\n Outfit:\n");
ReadAsset(PurchasableOutfit.Outfit, READGROUP);
}
PurchasableOutfit.CollectionDef = VBFile.readint32();
if(PurchasableOutfit.CollectionDef){
printf("\n Collection:\n");
ReadAsset(PurchasableOutfit.Collection, READGROUP);
}
}

View file

@ -0,0 +1,35 @@
/* Name of package */
#define PACKAGE "libvitaboy"
/* Version number of package */
#define VERSION_A 1
#define VERSION_B 0
#define VERSION_C 1
#define VERSION_STR "1.0.1"
#define REVISION 0
1 VERSIONINFO
FILEVERSION VERSION_A,VERSION_B,VERSION_C,REVISION
PRODUCTVERSION VERSION_A,VERSION_B,VERSION_C,REVISION
FILEOS 0x00040000L /* VOS_NT - 32-bit Windows */
FILETYPE 2 /* DLL */
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904B0"
BEGIN
VALUE "CompanyName", "Niotso project"
VALUE "FileDescription", "Free, open source C++ OpenGL TSO character rendering and animation library"
VALUE "FileVersion", VERSION_STR
VALUE "InternalName", PACKAGE
VALUE "LegalCopyright", "Copyright © 2012"
VALUE "OriginalFilename", PACKAGE".dll"
VALUE "ProductName", PACKAGE
VALUE "ProductVersion", VERSION_STR
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 0x04B0
END
END

View file

@ -0,0 +1,97 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
skel.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "libvitaboy.hpp"
void ReadSkeleton(Skeleton_t& Skeleton){
printf("\n========== Skeleton ==========\n");
Skeleton.Version = VBFile.readint32();
printf("Version: %u\n", Skeleton.Version);
Skeleton.Name = VBFile.readstring();
printf("Name: %s\n", Skeleton.Name);
Skeleton.BoneCount = VBFile.readint16();
printf("BoneCount: %u\n", Skeleton.BoneCount);
Skeleton.Bones = (Bone_t*) malloc(Skeleton.BoneCount * sizeof(Bone_t));
for(unsigned i=0; i<Skeleton.BoneCount; i++){
printf("\n [Bone %u]\n", i);
ReadBone(Skeleton, Skeleton.Bones[i], i);
}
}
void ReadBone(Skeleton_t& Skeleton, Bone_t& Bone, unsigned Index){
Bone.Unknown = VBFile.readint32();
printf(" | Unknown: %u\n", Bone.Unknown);
Bone.Name = VBFile.readstring();
printf(" | Name: %s\n", Bone.Name);
Bone.ParentsName = VBFile.readstring();
printf(" | Parent's name: %s\n", Bone.ParentsName);
Bone.HasProps = VBFile.readint8();
printf(" | HasProps: %u\n", Bone.HasProps);
if(Bone.HasProps){
ReadPropsList(Bone.PropsList);
}
printf(" | Translation:\n");
Bone.Translation.x = -VBFile.readfloat();
printf(" | | x: %g\n", Bone.Translation.x);
Bone.Translation.y = VBFile.readfloat();
printf(" | | y: %g\n", Bone.Translation.y);
Bone.Translation.z = VBFile.readfloat();
printf(" | | z: %g\n", Bone.Translation.z);
printf(" | Rotation:\n");
Bone.Rotation.x = VBFile.readfloat();
printf(" | | x: %g\n", Bone.Rotation.x);
Bone.Rotation.y = -VBFile.readfloat();
printf(" | | y: %g\n", Bone.Rotation.y);
Bone.Rotation.z = -VBFile.readfloat();
printf(" | | z: %g\n", Bone.Rotation.z);
Bone.Rotation.w = VBFile.readfloat();
printf(" | | w: %g\n", Bone.Rotation.w);
Bone.CanTranslate = VBFile.readint32();
printf(" | CanTranslate: %u\n", Bone.CanTranslate);
Bone.CanRotate = VBFile.readint32();
printf(" | CanRotate: %u\n", Bone.CanRotate);
Bone.CanBlend = VBFile.readint32();
printf(" | CanBlend: %u\n", Bone.CanBlend);
Bone.WiggleValue = VBFile.readfloat();
printf(" | WiggleValue: %g\n", Bone.WiggleValue);
Bone.WigglePower = VBFile.readfloat();
printf(" | WigglePower: %g\n", Bone.WigglePower);
Bone.ChildrenCount = 0;
Bone.Children = (Bone_t**) malloc((Skeleton.BoneCount-Index-1) * sizeof(Bone_t*));
unsigned Parent = FindBone(Skeleton, Bone.ParentsName, Index);
if(Parent != (unsigned)-1){
Bone_t& ParentBone = Skeleton.Bones[Parent];
ParentBone.Children[ParentBone.ChildrenCount] = &Bone;
ParentBone.ChildrenCount++;
}
}
unsigned FindBone(Skeleton_t& Skeleton, const char * BoneName, unsigned Count){
for(unsigned i=0; i<Count; i++){
if(!strcmp(Skeleton.Bones[i].Name, BoneName)) return i;
}
return (unsigned)-1;
}

View file

@ -0,0 +1,159 @@
/*
libvitaboy - Open source OpenGL TSO character animation library
vbparse.cpp - Copyright (c) 2012 Niotso Project <http://niotso.org/>
Author(s): Fatbag <X-Fi6@phppoll.org>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <stdio.h>
#include <strings.h>
#include <FileHandler.hpp>
#include "libvitaboy.hpp"
enum VBFileType {
VBFILE_ANIM,
VBFILE_APR,
VBFILE_BND,
VBFILE_COL,
VBFILE_HAG,
VBFILE_MESH,
VBFILE_OFT,
VBFILE_PO,
VBFILE_SKEL
};
int main(int argc, char *argv[]){
int type;
char * InFile;
if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){
printf("Usage: vbparse [-t type] infile\n"
"Parse a TSO VitaBoy file.\n"
"\n"
"Supported types:\n"
" (*) ANIM - Animation\n"
" (*) APR - Appearance\n"
" (*) BND - Binding\n"
" (*) COL - Collection\n"
" (*) HAG - Hand group\n"
" (*) MESH - Mesh\n"
" (*) OFT - Outfit\n"
" (*) PO - Purchasable object\n"
" (*) SKEL - Skeleton\n"
"\n"
"Report bugs to <X-Fi6@phppoll.org>.\n"
"vbparse is maintained by the Niotso project.\n"
"Home page: <http://www.niotso.org/>");
return 0;
}
if(argc >= 4 && !strcmp(argv[1], "-t")){
if(!stricmp(argv[2], "anim")) type = 0;
else if(!stricmp(argv[2], "apr")) type = 1;
else if(!stricmp(argv[2], "bnd")) type = 2;
else if(!stricmp(argv[2], "col")) type = 3;
else if(!stricmp(argv[2], "hag")) type = 4;
else if(!stricmp(argv[2], "mesh")) type = 5;
else if(!stricmp(argv[2], "oft")) type = 6;
else if(!stricmp(argv[2], "po")) type = 7;
else if(!stricmp(argv[2], "skel")) type = 8;
else{
printf("%sUnrecognized type '%s'", "vbparse: Error: ", argv[2]);
return -1;
}
InFile = argv[3];
}else{
char * pos = strrchr(argv[1], '.') + 1;
if(!stricmp(pos, "anim")) type = 0;
else if(!stricmp(pos, "apr")) type = 1;
else if(!stricmp(pos, "bnd")) type = 2;
else if(!stricmp(pos, "col")) type = 3;
else if(!stricmp(pos, "hag")) type = 4;
else if(!stricmp(pos, "mesh")) type = 5;
else if(!stricmp(pos, "oft")) type = 6;
else if(!stricmp(pos, "po")) type = 7;
else if(!stricmp(pos, "skel")) type = 8;
else{
printf("%sUnrecognized type", "vbparse: Error: ");
return -1;
}
InFile = argv[1];
}
uint8_t *InData = File::ReadFile(InFile);
if(InData == NULL){
const char * Message;
switch(File::Error){
case FERR_NOT_FOUND:
Message = "%s does not exist.";
break;
case FERR_OPEN:
Message = "%s could not be opened for reading.";
break;
case FERR_BLANK:
Message = "%s is corrupt or invalid.";
break;
case FERR_MEMORY:
Message = "Memory for %s could not be allocated.";
break;
default:
Message = "%s could not be read.";
break;
}
printf(Message, InFile);
return -1;
}
VBFile.set(InData, File::FileSize);
switch(type){
case VBFILE_ANIM:
Animation_t Animation;
ReadAnimation(Animation);
break;
case VBFILE_APR:
Appearance_t Appearance;
ReadAppearance(Appearance);
break;
case VBFILE_BND:
Binding_t Binding;
ReadBinding(Binding);
break;
case VBFILE_COL:
Collection_t Collection;
ReadCollection(Collection);
break;
case VBFILE_HAG:
HandGroup_t HandGroup;
ReadHandGroup(HandGroup);
break;
case VBFILE_MESH:
Mesh_t Mesh;
ReadMesh(Mesh);
break;
case VBFILE_OFT:
Outfit_t Outfit;
ReadOutfit(Outfit);
break;
case VBFILE_PO:
PurchasableOutfit_t PurchasableOutfit;
ReadPurchasableOutfit(PurchasableOutfit);
break;
case VBFILE_SKEL:
Skeleton_t Skeleton;
ReadSkeleton(Skeleton);
}
return 0;
}