lol skl

/*
League of Legends Custom Skin Tool-Kit
by Jahrain
This is a simple tool that can be used to compile and decompile .skn and .skl files
in order to create custom skin models for League of Legends
*/
#include<iostream>
#include<fstream>
#include<vector>
#include<string>
using namespace std;
 
struct Header {
    //Structure for header on skl files
    char fileType[8];
    int numObjects;
    int skeletonHash;
    int numElements;
};
 
struct Bone {
    //Structure for a bone in skl files
    char name[32];
    int parent;
    float scale;
    float matrix[3][4];
};
 
struct SkinModelHeader {
    //Structure for the Header in skn files
    int magic;
    short numMaterials;
    short numObjects;
};
struct SkinModelMaterial {
    //Structure for a material block in skn files
    int matIndex;
    char name[64];
    int startVertex;
    int numVertices;
    int startIndex;
    int numIndices;
};
struct SkinModelVertex {
    //Vertex block in skn files
    float position[3];
    char  boneIndex[4];
    float weights[4];
    float normal[3];
    float texcoords[2];
};
struct SkinModelData {
    //data block in skn files
    int numIndices;
    int numVertices;
    vector<short> indices;
    vector<SkinModelVertex> verteces;
};
 
struct SkinModel {
    //Skin model data structure
    SkinModelHeader header;
    vector<SkinModelMaterial> materials;
    SkinModelData modelData;
 
    void exportObj(string fileName) {
        //exports this skin model as a .obj file
        ofstream fout(fileName.c_str());
        for (int i = 0; i < modelData.verteces.size(); i++) {
            fout << "v " << modelData.verteces[i].position[0] << " " << modelData.verteces[i].position[1] << " " << modelData.verteces[i].position[2] << endl;
            fout << "vn " << modelData.verteces[i].normal[0] << " " << modelData.verteces[i].normal[1] << " " << modelData.verteces[i].normal[2] << endl;
            fout << "vt " << modelData.verteces[i].texcoords[0] << " " << 1-modelData.verteces[i].texcoords[1] << endl;
        }
        if (materials.size()) {
            fout << "g mat_" << materials[0].name << endl;
        }
        for (int i = 0;  i < modelData.numIndices/3; i++) {
            int a = modelData.indices[i*3] + 1;
            int b = modelData.indices[i*3 + 1] + 1;
            int c = modelData.indices[i*3 + 2] + 1;
            fout << "f " << a << '/' << a << '/' << a << " " << b << '/' << b << '/' << b << " " << c << '/' << c << '/' << c << endl;
        }
    }
 
    void exportSkn(string fileName) {
        //export this SkinModel as .skn which can be used by league of legends
        ofstream fout;
        fout.open(fileName.c_str(), ios::binary);
        fout.write((char*)(void*)&header,sizeof(SkinModelHeader));
        for (int i = 0; i < header.numMaterials; i++) {
            fout.write((char*)(void*)&materials[i], sizeof(SkinModelMaterial));
        }
        fout.write((char*)(void*)&modelData.numIndices,4);
        fout.write((char*)(void*)&modelData.numVertices,4);
        for (int i = 0; i < modelData.numIndices; i++) {
            fout.write((char*)(void*)&modelData.indices[i], 2);
        }
        for (int i = 0; i < modelData.numVertices; i++) {
            fout.write((char*)(void*)&modelData.verteces[i],sizeof(SkinModelVertex));
        }
    }
 
    void importSkn(string infile) {
        //import from .skn file
        ifstream fin;
        fin.open(infile.c_str(), ios::binary);
        if (fin.fail()) {
            cout << "ERROR: could not open " << infile << endl;
            exit(1);
        }
        fin.read((char*)(void*)&header,sizeof(SkinModelHeader));
 
        for (int i = 0; i < header.numMaterials; i++) {
            SkinModelMaterial mat;
            fin.read((char*)(void*)&mat, sizeof(SkinModelMaterial));
            materials.push_back(mat);
        }
 
        fin.read((char*)(void*)&modelData.numIndices,4);
        fin.read((char*)(void*)&modelData.numVertices,4);
 
        for (int i = 0; i < modelData.numIndices; i++) {
            short idx;
            fin.read((char*)(void*)&idx, 2);
            modelData.indices.push_back(idx);
        }
        for (int i = 0; i < modelData.numVertices; i++) {
            SkinModelVertex vtx;
            fin.read((char*)(void*)&vtx,sizeof(SkinModelVertex));
            modelData.verteces.push_back(vtx);
        }
    }
 
    void importMesh(string infile) {
        //import from ASCII mesh output from Maya Script
        //cout << "Compiling skin file: " << infile << " to binary file: " << outfile << endl;
        ifstream fin(infile.c_str());
        if (fin.fail()) {
            cout << "ERROR: could not open " << infile << endl;
            exit(1);
        }
        int numVerts;
        fin >> numVerts;
        modelData.numVertices = numVerts;
        for (int i = 0; i < numVerts; i++) {
            SkinModelVertex vtx;
            fin >> vtx.position[0] >> vtx.position[1] >> vtx.position[2];
 
            for (int j = 0;  j < 3; j++) {
                int boneIdx = 0;
                string boneIdxStr;
                fin >> boneIdxStr;
                if (boneIdxStr != "#NULL") {
                    string tmp;
                    for (int k = boneIdxStr.length() - 1; k >= 0; k--) {
                        if (boneIdxStr[k] == '_') {
                            boneIdxStr[k] = ' ';
                            break;
                        }
                    }
                }
                char name[32];
                sscanf(boneIdxStr.c_str(), "%s %d",name,&boneIdx);
                vtx.boneIndex[j] = boneIdx;
 
            }
            vtx.boneIndex[3] = 0;
            fin >> vtx.weights[0] >> vtx.weights[1] >> vtx.weights[2];
            vtx.weights[3] = 0;
            //normalize weights
            float weightSum = vtx.weights[0] + vtx.weights[1] + vtx.weights[2];
            vtx.weights[0] *= 1.0f/weightSum;
            vtx.weights[1] *= 1.0f/weightSum;
            vtx.weights[2] *= 1.0f/weightSum;
            fin >> vtx.normal[0] >> vtx.normal[1] >> vtx.normal[2];
            fin >> vtx.texcoords[0] >> vtx.texcoords[1];
            vtx.texcoords[1] = 1 - vtx.texcoords[1];        //flip the UVs
            modelData.verteces.push_back(vtx);
        }
        SkinModelMaterial mat;
        memset((void*)&mat,0,sizeof(SkinModelMaterial));
        fin >> mat.name;
        int numFaces;
        fin >> numFaces;
        string nameStr = string(mat.name);
        if (nameStr != "lambert1") {
            cout << "NOTE: The material name is " << nameStr << ". Make sure this matches the same material as the original skin file!!!" << endl;
            header.numMaterials = 1;
            mat.matIndex = 1;
            mat.numIndices = numFaces*3;
            mat.numVertices = numVerts;
            mat.startIndex = 0;
            mat.startVertex = 0;
            materials.push_back(mat);
        } else {
            cout << "WARNING: The default material was used because this model used the default material lambert1. Only do this if the original .skn file has no materials." << endl;
            header.numMaterials = 0;
        }
        header.magic = 1122867;
        header.numObjects = 1;
        modelData.numIndices = numFaces*3;
        for (int i = 0; i < numFaces; i++) {
            for (int j = 0; j < 3; j++) {
                short face;
                fin >> face;
                modelData.indices.push_back(face);
            }
        }
    }
 
};
 
void dumpSkeleton(string infile, string outfile) {
    //dump out the contents of a .skl file as ASCII for importing into Maya or some other 3d Application.
    ifstream fin;
    fin.open(infile.c_str(), ios::binary);
    if (fin.fail()) {
        cout << "ERROR: could not open " << infile << endl;
        exit(1);
    }
    ofstream fout(outfile.c_str());
    Header header;
    fin.read((char*)(void*)&header, sizeof(header));
    cout << "Found " << header.numElements << " bones" << endl;
    fout << header.fileType << endl;
    fout << header.numObjects << endl;
    fout << header.skeletonHash << endl;
    fout << header.numElements << endl;
    for (int i = 0; i < header.numElements; i++) {
        Bone bone;
        fin.read((char*)(void*)&bone, sizeof(Bone));
        fout << bone.name << endl;
        fout << bone.parent << endl;
        fout << bone.scale << endl;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                fout << bone.matrix[i][j] << " ";
            }
            fout << endl;
        }
    }
}
 
void compileSkeleton(string infile, string outfile) {
    //Compile the ASCII skeleton file back into a .skl file
    ifstream fin;
    fin.open(infile.c_str());
    if (fin.fail()) {
        cout << "ERROR: could not open " << infile << endl;
        exit(1);
    }
    ofstream fout;
    fout.open(outfile.c_str(), ios::binary);
    Header header;
 
    fin >> header.fileType;
    fin >> header.numObjects;
    fin >> header.skeletonHash;
    fin >> header.numElements;
 
    fout.write((const char*)&header,sizeof(Header));
    for (int i = 0; i < header.numElements; i++) {
        Bone bone;
        memset(bone.name,0,32);
        fin >> bone.name;
        fin >> bone.parent;
        fin >> bone.scale;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 4; j++) {
                fin >> bone.matrix[i][j];
            }
        }
        fout.write((const char*)&bone, sizeof(Bone));
    }
}
 
int main(int argc, char *argv[]) {
 
    if (argc != 5) {
        cout << "Usage: lolskintool <command> <type> <inputFile> <outputFile>" << endl;
        cout << "Valid commands are: c (compile), d (decompile)" << endl;
        cout << "Supported types are: skl (skeleton), skn (skin)" << endl;
        return 2;
    }
    string cmd = string(argv[1]);
    string type = string(argv[2]);
    string inputFile = string(argv[3]);
    string outputFile = string(argv[4]);
 
    if (cmd == "compile" || cmd == "c") {
        if (type == "skl" || type == "skeleton") {
            cout << "Compiling ASCII skeleton file: " << inputFile << " to binary .skl file: " << outputFile << endl;
            compileSkeleton(inputFile, outputFile);
            cout << "Done!" << endl;
        } else if (type == "skn" || type == "skin") {
            SkinModel model;
            cout << "Compiling ASCII skin mesh file: " << inputFile << " to binary .skn file: " << outputFile << endl;
            model.importMesh(inputFile);
            model.exportSkn(outputFile);
            cout << "Done!" << endl;
        } else {
            cout << "Unsupported file type" << endl;
            return 2;
        }
    } else if (cmd == "decompile" || cmd == "d") {
        if (type == "skl" || type == "skeleton") {
            cout << "Decompiling binary .skl file: " << inputFile << " to ASCII file: " << outputFile << endl;
            dumpSkeleton(inputFile, outputFile);
            cout << "Done!" << endl;
        } else if (type == "skn" || type == "skin") {
            cout << "Decompiling binary .skn file: " << inputFile << " to .obj file: " << outputFile << endl;
            SkinModel model;
            model.importSkn(inputFile);
            model.exportObj(outputFile);
            cout << "Done!" << endl;
        } else {
            cout << "Unsupported file type" << endl;
            return 2;
        }
    } else {
        cout << "Unsupported command" << endl;
        return 2;
    }
    return 0;
}

转载于:https://my.oschina.net/lyr/blog/128006

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值