2

SO, I read tons of same topics but I couldn't come with the solution. I've made an importer (binary to struct) code using C++ and now I want to make shiny forms and transfer my code properly. C# is a lot different from C++ in this case and so I had to redo a lot of stuff already and there're more to come. Here's my C++ code:

#include "stdafx.h"
#include "half.h"
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
using half_float::half;

#pragma pack(push, 1)
struct Group {
    uint8_t Name[32];
};
struct WeaponBonesData {
    uint8_t WeaponBoneName[32];
    uint8_t Unknown5[48];
    uint32_t WeaponBoneID;
};
struct TexturesData {
    uint32_t TextureType;
    uint8_t TextureName[256];
};
struct Shader {
    float DetailTileU;
    uint32_t Unknown7;
    float DetailTileV;
    uint32_t Unknown8;
    uint32_t DirtTileU;
    uint32_t Unknown9;
    uint32_t DirtTileV;
    uint32_t Unknown10;
};
struct VertexData {
    half X;
    half Y;
    half Z;
    half Sep1;
    bool bone0;
    bool bone1;
    bool weight;
    bool Sep2;
    bool normX;
    bool normY;
    bool normZ;
    bool Sep3;
    half U;
    half V;
    uint32_t Unknown11[2];
};
struct IndexData {
    uint16_t ind1;
    uint16_t ind2;
    uint16_t ind3;
};
struct Geometry {
    vector<VertexData> Vertices;
    vector<IndexData> Indices;
};
struct rigid_model {
    uint32_t rigid_material_ID;
    vector<uint32_t> LodSize;
    vector<uint32_t> LodVerticesOffset;
    vector<uint32_t> VerticesCount;
    vector<uint32_t> LodIndicesOffset;
    vector<uint32_t> IndicesCount;
    vector<float> GroupMinX;
    vector<float> GroupMinY;
    vector<float> GroupMinZ;
    vector<float> GroupMaxX;
    vector<float> GroupMaxY;
    vector<float> GroupMaxZ;
    uint8_t ShaderMaterial[12];
    uint8_t Unknown1[20];
    uint16_t Unknown2;
    vector<Group> GroupName;
    uint8_t TexturesDir[256];
    uint8_t Unknown3[422];
    uint32_t WeaponBonesCount;
    uint32_t TexturesCount;
    uint8_t Unknown4[140];
    WeaponBonesData WeaponBones[5];
    vector<TexturesData> TexData;
    uint32_t NullMask;
    Shader ShaderParams;
    uint32_t AlphaMode;
    vector<Geometry>  Mesh;
};
struct RMV2 {
    uint8_t Signature[4];
    uint32_t ModelType;
    uint32_t LodsCount;
    uint8_t SkeletonName[128];
    vector<uint32_t> GroupsCount;
    vector<uint32_t> VDCount;
    vector<uint32_t> IDCount;
    vector<uint32_t> StartOffset;
    vector<float> ZoomFactor;
    vector<rigid_model> lod;
};
#pragma pack(pop)

ostream& operator<<(ostream& os, const WeaponBonesData& WBD) {
    return os << WBD.WeaponBoneName << WBD.Unknown5 << WBD.WeaponBoneID;
}
ostream& operator<<(ostream& os, const Group& g) {
    return os << g.Name;
}

void read(RMV2 &rmv2, char filename[128]) {
    ifstream model(filename, ios::in | ios::binary);
    if (model.fail()) {
        cout << "ERROR! Invalid file name" << endl;
        system("pause");
        exit(0);
    }
    model.read((char*)&rmv2, 140);

    rigid_model data;
    uint32_t temp;
    float temp2;
    TexturesData TD;
    VertexData vertex;
    IndexData index;
    Geometry geometry;
    Group group;
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.GroupsCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.VDCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.IDCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.StartOffset.push_back(temp);
        model.read((char*)&temp2, sizeof(float));
        rmv2.ZoomFactor.push_back(temp2);
    }
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        for (size_t j = 0; j < rmv2.GroupsCount[i]; j++) {
            model.read((char*)&data.rigid_material_ID, sizeof(data.rigid_material_ID));
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodSize.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodVerticesOffset.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.VerticesCount.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodIndicesOffset.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.IndicesCount.push_back(temp);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinX.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinY.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinZ.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxX.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxY.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxZ.push_back(temp2);
            model.read((char*)&data.ShaderMaterial, sizeof(data.ShaderMaterial));
            model.read((char*)&data.Unknown1, sizeof(data.Unknown1));
            model.read((char*)&data.Unknown2, sizeof(data.Unknown2));
            model.read((char*)&group, sizeof(group));
            data.GroupName.push_back(group);
            model.read((char*)&data.TexturesDir, sizeof(data.TexturesDir));
            model.read((char*)&data.Unknown3, sizeof(data.Unknown3));
            model.read((char*)&data.WeaponBonesCount, sizeof(data.WeaponBonesCount));
            model.read((char*)&data.TexturesCount, sizeof(data.TexturesCount));
            model.read((char*)&data.Unknown4, sizeof(data.Unknown4));
            for (size_t k = 0; k < data.WeaponBonesCount; k++) {
                model.read((char*)&data.WeaponBones[k].WeaponBoneName, sizeof(data.WeaponBones[k].WeaponBoneName));
                model.read((char*)&data.WeaponBones[k].Unknown5, sizeof(data.WeaponBones[k].Unknown5));
                model.read((char*)&data.WeaponBones[k].WeaponBoneID, sizeof(data.WeaponBones[k].WeaponBoneID));
            }
            for (size_t k = 0; k < data.TexturesCount; k++) {
                model.read((char*)&TD, sizeof(TD));
                data.TexData.push_back(TD);
            }
            model.read((char*)&data.NullMask, sizeof(data.NullMask));
            if (data.rigid_material_ID == 79) {
                model.read((char*)&data.ShaderParams.DetailTileU, sizeof(data.ShaderParams.DetailTileU));
                model.read((char*)&data.ShaderParams.Unknown7, sizeof(data.ShaderParams.Unknown7));
                model.read((char*)&data.ShaderParams.DetailTileV, sizeof(data.ShaderParams.DetailTileV));
                model.read((char*)&data.ShaderParams.Unknown8, sizeof(data.ShaderParams.Unknown8));
                model.read((char*)&data.ShaderParams.DirtTileU, sizeof(data.ShaderParams.DirtTileU));
                model.read((char*)&data.ShaderParams.Unknown9, sizeof(data.ShaderParams.Unknown9));
                model.read((char*)&data.ShaderParams.DirtTileV, sizeof(data.ShaderParams.DirtTileV));
                model.read((char*)&data.ShaderParams.Unknown10, sizeof(data.ShaderParams.Unknown10));
            }
            model.read((char*)&data.AlphaMode, sizeof(data.AlphaMode));
            for (size_t k = 0; k < data.VerticesCount[j]; k++) {
                model.read((char*)&vertex, sizeof(vertex));
                geometry.Vertices.push_back(vertex);
            }
            for (size_t k = 0; k < data.IndicesCount[j] / 3; k++) {
                model.read((char*)&index, sizeof(index));
                geometry.Indices.push_back(index);
            }
            data.Mesh.push_back(geometry);
            geometry = {};
        }
        rmv2.lod.push_back(data);
        data = {};
    }
    model.close();
}

void to_rmv2(RMV2 &rmv2, char filename[128]) {
    ofstream model(filename, ios::out | ios::binary);
    model.write((char*)&rmv2, 140);

    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        model.write((char*)&rmv2.GroupsCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.VDCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.IDCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.StartOffset[i], sizeof(uint32_t));
        model.write((char*)&rmv2.ZoomFactor[i], sizeof(float));
    }
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        for (size_t j = 0; j < rmv2.GroupsCount[i]; j++) {
            model.write((char*)&rmv2.lod[i].rigid_material_ID, sizeof(rmv2.lod[i].rigid_material_ID));
            model.write((char*)&rmv2.lod[i].LodSize[j], sizeof(rmv2.lod[i].LodSize[j]));
            model.write((char*)&rmv2.lod[i].LodVerticesOffset[j], sizeof(rmv2.lod[i].LodVerticesOffset[j]));
            model.write((char*)&rmv2.lod[i].VerticesCount[j], sizeof(rmv2.lod[i].VerticesCount[j]));
            model.write((char*)&rmv2.lod[i].LodIndicesOffset[j], sizeof(rmv2.lod[i].LodIndicesOffset[j]));
            model.write((char*)&rmv2.lod[i].IndicesCount[j], sizeof(rmv2.lod[i].IndicesCount[j]));
            model.write((char*)&rmv2.lod[i].GroupMinX[j], sizeof(rmv2.lod[i].GroupMinX[j]));
            model.write((char*)&rmv2.lod[i].GroupMinY[j], sizeof(rmv2.lod[i].GroupMinY[j]));
            model.write((char*)&rmv2.lod[i].GroupMinZ[j], sizeof(rmv2.lod[i].GroupMinZ[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxX[j], sizeof(rmv2.lod[i].GroupMaxX[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxY[j], sizeof(rmv2.lod[i].GroupMaxY[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxZ[j], sizeof(rmv2.lod[i].GroupMaxZ[j]));
            model.write((char*)&rmv2.lod[i].ShaderMaterial, sizeof(rmv2.lod[i].ShaderMaterial));
            model.write((char*)&rmv2.lod[i].Unknown1, sizeof(rmv2.lod[i].Unknown1));
            model.write((char*)&rmv2.lod[i].Unknown2, sizeof(rmv2.lod[i].Unknown2));
            model.write((char*)&rmv2.lod[i].GroupName[j], sizeof(rmv2.lod[i].GroupName[j]));
            model.write((char*)&rmv2.lod[i].TexturesDir, sizeof(rmv2.lod[i].TexturesDir));
            model.write((char*)&rmv2.lod[i].Unknown3, sizeof(rmv2.lod[i].Unknown3));
            model.write((char*)&rmv2.lod[i].WeaponBonesCount, sizeof(rmv2.lod[i].WeaponBonesCount));
            model.write((char*)&rmv2.lod[i].TexturesCount, sizeof(rmv2.lod[i].TexturesCount));
            model.write((char*)&rmv2.lod[i].Unknown4, sizeof(rmv2.lod[i].Unknown4));
            for (size_t k = 0; k < rmv2.lod[i].WeaponBonesCount; k++) {
                model.write((char*)&rmv2.lod[i].WeaponBones[k], sizeof(rmv2.lod[i].WeaponBones[k]));
            }
            for (size_t k = 0; k < rmv2.lod[i].TexturesCount; k++) {
                model.write((char*)&rmv2.lod[i].TexData[k], sizeof(rmv2.lod[i].TexData[k]));
            }
            model.write((char*)&rmv2.lod[i].NullMask, sizeof(rmv2.lod[i].NullMask));
            if (rmv2.lod[i].rigid_material_ID == 79) {
                model.write((char*)&rmv2.lod[i].ShaderParams.DetailTileU, sizeof(rmv2.lod[i].ShaderParams.DetailTileU));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown7, sizeof(rmv2.lod[i].ShaderParams.Unknown7));
                model.write((char*)&rmv2.lod[i].ShaderParams.DetailTileV, sizeof(rmv2.lod[i].ShaderParams.DetailTileV));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown8, sizeof(rmv2.lod[i].ShaderParams.Unknown8));
                model.write((char*)&rmv2.lod[i].ShaderParams.DirtTileU, sizeof(rmv2.lod[i].ShaderParams.DirtTileU));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown9, sizeof(rmv2.lod[i].ShaderParams.Unknown9));
                model.write((char*)&rmv2.lod[i].ShaderParams.DirtTileV, sizeof(rmv2.lod[i].ShaderParams.DirtTileV));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown10, sizeof(rmv2.lod[i].ShaderParams.Unknown10));
            }
            model.write((char*)&rmv2.lod[i].AlphaMode, sizeof(rmv2.lod[i].AlphaMode));
            for (size_t k = 0; k < rmv2.lod[i].VerticesCount[j]; k++) {
                model.write((char*)&rmv2.lod[i].Mesh[j].Vertices[k], sizeof(rmv2.lod[i].Mesh[j].Vertices[k]));
            }
            for (size_t k = 0; k < rmv2.lod[i].IndicesCount[j] / 3; k++) {
                model.write((char*)&rmv2.lod[i].Mesh[j].Indices[k], sizeof(rmv2.lod[i].Mesh[j].Indices[k]));
            }
        }
    }
    model.close();
}

struct DAE {
    vector<char> Signature;
};

void convert(RMV2 &rmv2, DAE &dae) {
//  dae.Signature[0] = "<?xml version='1.0' encoding='utf - 8'?>";
}

void to_dae(DAE &dae, char filename[128]) {
    ofstream model(filename, ios::out | ios::binary);
    model.write((char*)&dae, 140);
    model.close();
}

int main(int argc, char *argv[])
{
    RMV2 rmv2;
    DAE dae;
    char filename[128], daeFilename[128];

    cout << "Filename: ";
    gets_s(filename, sizeof(filename));
    strcpy_s(daeFilename, filename);
    strcat_s(filename, ".rigid_model_v2");
    strcat_s(daeFilename, ".dae");

    read(rmv2,  filename);
    convert(rmv2, dae);
    to_dae(dae, daeFilename);
//  to_rmv2(rmv2, daeFilename);

//  cout << rmv2.lod[0].Mesh[0].Vertices[0].X << endl;
    cout << "Successfully converted to .dae" << endl;
    system("pause");
    return 0;
}

And here's my C# attempts:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace RMV2Convertor
{
    public partial class ConvertorForm : Form
    {
        public ConvertorForm()
        {
            InitializeComponent();
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Group
        {
            public Group(int size = 32)
            {
                sbyte[] Name = new sbyte[size];
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct WeaponBonesData
        {
            sbyte[] WeaponBoneName;
            sbyte[] Unknown5;
            uint WeaponBoneID;
            public WeaponBonesData(int size = 32)
            {
                WeaponBoneName = new sbyte[size];
                Unknown5 = new sbyte[48];
                WeaponBoneID = new uint();
            }
        }
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct TexturesData
        {
            uint TextureType;
            sbyte[] TextureName;
            public TexturesData(int size = 256)
            {
                TextureType = new uint();
                TextureName = new sbyte[size];
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Shader
        {
            float DetailTileU;
            uint Unknown7;
            float DetailTileV;
            uint Unknown8;
            uint DirtTileU;
            uint Unknown9;
            uint DirtTileV;
            uint Unknown10;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct VertexData
        {
            Half X;
            Half Y;
            Half Z;
            Half Sep1;
            bool bone0;
            bool bone1;
            bool weight;
            bool Sep2;
            bool normX;
            bool normY;
            bool normZ;
            bool Sep3;
            Half U;
            Half V;
            ulong Unknown11;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct IndexData
        {
            ushort ind1;
            ushort ind2;
            ushort ind3;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Geometry
        {
            List<VertexData> Vertices;
            List<IndexData> Indices;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct rigid_model
        {
            uint rigid_material_ID;
            List<uint> LodSize;
            List<uint> LodVerticesOffset;
            List<uint> VerticesCount;
            List<uint> LodIndicesOffset;
            List<uint> IndicesCount;
            List<float> GroupMinX;
            List<float> GroupMinY;
            List<float> GroupMinZ;
            List<float> GroupMaxX;
            List<float> GroupMaxY;
            List<float> GroupMaxZ;
            sbyte[] ShaderMaterial;
            sbyte[] Unknown1;
            ushort Unknown2;
            List<Group> GroupName;
            sbyte[] TexturesDir;
            sbyte[] Unknown3;
            uint WeaponBonesCount;
            uint TexturesCount;
            sbyte[] Unknown4;
            WeaponBonesData[] WeaponBones;
            List<TexturesData> TexData;
            uint NullMask;
            Shader ShaderParams;
            uint AlphaMode;
            List<Geometry> Mesh;
            public rigid_model(int size = 12)
            {
                rigid_material_ID = new uint();
                LodSize = new List<uint>();
                LodVerticesOffset = new List<uint>();
                VerticesCount = new List<uint>();
                LodIndicesOffset = new List<uint>();
                IndicesCount = new List<uint>();
                GroupMinX = new List<float>();
                GroupMinY = new List<float>();
                GroupMinZ = new List<float>();
                GroupMaxX = new List<float>();
                GroupMaxY = new List<float>();
                GroupMaxZ = new List<float>();
                ShaderMaterial = new sbyte[size];
                Unknown1 = new sbyte[20];
                Unknown2 = new ushort();
                GroupName = new List<Group>();
                TexturesDir = new sbyte[256];
                Unknown3 = new sbyte[422];
                WeaponBonesCount = new uint();
                TexturesCount = new uint();
                Unknown4 = new sbyte[140];
                WeaponBones = new WeaponBonesData[5];
                TexData = new List<TexturesData>();
                NullMask = new uint();
                ShaderParams = new Shader();
                AlphaMode = new uint();
                Mesh = new List<Geometry>();
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct RMV2
        {
            public char[] Signature;
            public uint ModelType;
            public uint LodsCount;
            public char[] SkeletonName;
            public List<uint> GroupsCount;
            public List<uint> VDCount;
            public List<uint> IDCount;
            public List<uint> StartOffset;
            public List<float> ZoomFactor;
            public List<rigid_model> lod;
            public RMV2(int size = 4)
            {
                Signature = new char[size];
                ModelType = new uint();
                LodsCount = new uint();
                SkeletonName = new char[128];
                GroupsCount = new List<uint>();
                VDCount = new List<uint>();
                IDCount = new List<uint>();
                StartOffset = new List<uint>();
                ZoomFactor = new List<float>();
                lod = new List<rigid_model>();
            }
        };

        void read(RMV2 rmv2, string filename)
        {
            using (BinaryReader model = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read), Encoding.ASCII))
            {
                rmv2.Signature = model.ReadChars(4);
            }
            MessageBox.Show(rmv2.Signature.ToString());
        }

        private void bOpenFileDialog_Click(object sender, EventArgs e)
        {
            Stream myStream = null;
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.InitialDirectory = "c:\\";
            openFileDialog1.Filter = "rigid_model_v2 files (*.rigid_model_v2)|*.rigid_model_v2|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;


            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if ((myStream = openFileDialog1.OpenFile()) != null)
                    {
                        using (myStream)
                        {
                            RMV2 rmv2 = new RMV2();
                            string filename = openFileDialog1.FileName;
                            read(rmv2, filename);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }
    }
}

So the most important question I need a solution for: How to read a binary file to structure?

1 Answer 1

1

To read a file simply call ReadAllBytes:

byte[] array = File.ReadAllBytes("file path");

You can define the corresponding property in your struct.

Sign up to request clarification or add additional context in comments.

1 Comment

Alright, so I read all file bytes and what do I do next? I mean should I assign bytes to corresponding variables in struct by size?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.