retreev / PangLib

Series of tools to interact with Pangya PC MMO game files

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add *pet utilities

pixeldesu opened this issue · comments

There are a vast amount of file types related to models and animation, namely:

  • *.pet
  • *.apet
  • *.bpet
  • *.mpet

Handling all file types also involves these files of course, so we need fitting utilities and documentation for them!

Some research on (m)pet files and structures included inside them:

According to @hsreina there seem to be various different versions of *pet files, some easier being denoted by having the VERS section with a version number. Without that, you can just deem it "legacy".

Structures and current research:

General

All of the structures have one thing in common, the first integer after the 4-length char denoting the structure (e.g. TEXT) is the size of the whole structure and then usually a count of how many entries there are in the specific section.

Textures - TEXT

struct Texture {
	string Name; // null-terminated (?)
	// there's quite a bit more unknown data here, texture maps maybe?
}

Bones - BONE

struct Bone {
	string Name; // null-terminated
	byte Parent; // ID of the parent element
	float[12] Matrix; // Bone-matrix data, matching up with perspective projection
}

Perspective projection: https://en.wikipedia.org/wiki/3D_projection#Perspective_projection

Mesh - MESH

The first count of this structure is for the number of vertices of the mesh.

struct Vertex {
	float x;
	float y;
	float z;
	BoneInformation[] BoneInformation;
}

The array of BoneInformation structures continues until all Weight attributes accumulated have a sum of 0xFF.

struct BoneInformation {
	byte Weight;
	byte BoneID;
}

After the vertices, the next integer following denotes the number of Polygons.

struct Polygon {
	PolygonIndex[3] Indices;
}

Each Polygon contains 3 PolygonIndex structures. These contain the position inside the 3D space (x, y, z) and information for the UV mapping of the textures (u, v)

struct PolygonIndex {
	float x;
	float y;
	float z;
	float u;
	float v;
}

Motion - MOTI

struct Motion {
	uint nameLength;
	string name; // read nameLength bytes
    uint motionStart;
	uint motionEnd;
	uint typeNameLength;
	string typeName; // read typeLength bytes
	uint type; // looks to be null usually
	uint boneNameLength; 
	string boneName; // read boneNameLength bytes
}

Collision Boxes - COLL

struct CollisionBox {
	uint u1;
	uint u2;
	uint nameLength;
	string name;
	uint boneNameLength;
	string boneName;
	byte u3; // some kind of bool flag, I guess?
	uint u4;
	uint u5;
	float  minx;
    float  miny;
    float  minz;
    float  maxx;
    float  maxy;
    float  maxz;
}

Animation - ANIM

TODO

Face Animation - FANM

TODO

??? - FRAM

TODO - Most of the files that includes this only show an empty section here.

??? - SMTL

Only included in files with a VERS section.

TODO - Most of the files that includes this only show an empty section here.

The texture is more like that

struct Vertex {
	char matName[0x20];
	char name[0x20];
	unsigned int un1;
	unsigned int un2;
	unsigned int un3;
}

un1, un2, un3 are important, but I never searched too much about them. But you can add a specular effect to the model by add a texture with those params after the other textures

texture.un1 = 0x00460001;
texture.un2 = 0xFFFFFFFF;
texture.un3 = 0x00000001;
texture.name[0] = 0;
texture.matName[0] = 0;

strcat(texture.name, "!specular_ellipse_md.jpg");

It's used to make some items more shiny.

You also have the VERS chunk who is not present on all puppet files.
It help to detect version changes on the puppet files.
there were some changes in some chunks based on those versions
Structure is as follow:

struct TPuppetVersion{
	unsigned char Minor; // 0x01, 0x02, 0x03
	unsigned char Major; // 0x01
	unsigned char c; // 0xFE
	unsigned char d; // 0xFF
};

I always considered Puppets with no VERS chunk in it as legacy version 1.0
So the current existing versions are
1.0
1.1
1.2
1.3

Some more stuff I just found out, quickly skimming over it:

Motion - MOTI

(also includes the common size and count values)

struct Motion {
	uint nameLength;
	string name; // read nameLength bytes
    uint motionStart;
	uint motionEnd;
	uint typeNameLength;
	string typeName; // read typeLength bytes
	uint type; // looks to be null usually
	uint boneNameLength; 
	string boneName; // read boneNameLength bytes
}

Edit: Adjusted this a bit as I ended up skipping a line while analyzing the values. Found two more which look like rotational information to me. For the replay tape the values for motionStart and motionEnd are 0/359, which makes up a 360 degree rotation, but on other models it's either less than that or even over 360, so I'm not entirely sure if this discovery is correct.

And more, still some unknown values inbetween, the rest makes sense tho:

Collision Box - COLL

struct CollisionBox {
	uint u1;
	uint u2;
	uint nameLength;
	string name;
	uint boneNameLength;
	string boneName;
	byte u3; // some kind of bool flag, I guess?
	uint u4;
	uint u5;
	float  minx;
    float  miny;
    float  minz;
    float  maxx;
    float  maxy;
    float  maxz;
}

Added the base library PangLib.PET and handled most of the cases written down here.

Stuff that isn't handled yet:

  • Following sections:
    • VERS
    • TEXT
    • SMTL
    • ANIM
    • FANM
    • FRAM
  • Some structures being different in different versions (as supplied by VERS), need to test the library with more pet files to figure this out

While there are still some issues in files like .apet and the other specific ones, this is now mostly implemented and usable, as seen in https://github.com/pangyatools/PETViewer-Unity