public RmvRigidModel(byte[] data, string fileName)
        {
            ILogger logger = Logging.Create <RmvRigidModel>();

            logger.Here().Information($"Loading Rmv2RigidModel: {fileName}");
            if (data.Length == 0)
            {
                throw new Exception("Trying to load Rmv2RigidModel with no data, data size = 0");
            }

            FileName   = fileName;
            Header     = LoadModelHeader(data);
            LodHeaders = LoadLodHeaders(data);

            MeshList = new RmvSubModel[Header.LodCount][];
            for (int lodIndex = 0; lodIndex < Header.LodCount; lodIndex++)
            {
                var lodMeshCount = LodHeaders[lodIndex].MeshCount;
                MeshList[lodIndex] = new RmvSubModel[lodMeshCount];

                var sizeOffset = 0;
                for (int meshIndex = 0; meshIndex < lodMeshCount; meshIndex++)
                {
                    var offset = LodHeaders[lodIndex].FirstMeshOffset + sizeOffset;
                    MeshList[lodIndex][meshIndex] = new RmvSubModel(data, (int)offset, Header.SkeletonName);
                    sizeOffset += (int)MeshList[lodIndex][meshIndex].Header.ModelSize;
                }
            }

            logger.Here().Information("Loading done");
        }
        public Rmv2Geometry(RmvSubModel modelPart, IGeometryGraphicsContext context) : base(VertexPositionNormalTextureCustom.VertexDeclaration, context)
        {
            Pivot = new Vector3(modelPart.Header.Transform.Pivot.X, modelPart.Header.Transform.Pivot.Y, modelPart.Header.Transform.Pivot.Z);

            _vertexArray  = new VertexPositionNormalTextureCustom[modelPart.Mesh.VertexList.Length];
            _indexList    = (ushort[])modelPart.Mesh.IndexList.Clone();
            _vertedFormat = modelPart.Header.VertextType;

            for (int i = 0; i < modelPart.Mesh.VertexList.Length; i++)
            {
                var vertex = modelPart.Mesh.VertexList[i];
                _vertexArray[i].Position = new Vector4(vertex.Postition.X, vertex.Postition.Y, vertex.Postition.Z, 1);

                _vertexArray[i].Normal            = new Vector3(vertex.Normal.X, vertex.Normal.Y, vertex.Normal.Z);
                _vertexArray[i].BiNormal          = new Vector3(vertex.BiNormal.X, vertex.BiNormal.Y, vertex.BiNormal.Z);
                _vertexArray[i].Tangent           = new Vector3(vertex.Tangent.X, vertex.Tangent.Y, vertex.Tangent.Z);
                _vertexArray[i].TextureCoordinate = new Vector2(vertex.Uv.X, vertex.Uv.Y);

                _vertexArray[i].BlendIndices = Vector4.Zero;
                _vertexArray[i].BlendWeights = Vector4.Zero;

                if (_vertedFormat == VertexFormat.Cinematic)
                {
                    _vertexArray[i].BlendIndices.X = vertex.BoneIndex[0];
                    _vertexArray[i].BlendIndices.Y = vertex.BoneIndex[1];
                    _vertexArray[i].BlendIndices.Z = vertex.BoneIndex[2];
                    _vertexArray[i].BlendIndices.W = vertex.BoneIndex[3];

                    _vertexArray[i].BlendWeights.X = vertex.BoneWeight[0];
                    _vertexArray[i].BlendWeights.Y = vertex.BoneWeight[1];
                    _vertexArray[i].BlendWeights.Z = vertex.BoneWeight[2];
                    _vertexArray[i].BlendWeights.W = vertex.BoneWeight[3];

                    WeightCount = 4;
                }
                else if (_vertedFormat == VertexFormat.Weighted)
                {
                    _vertexArray[i].BlendIndices.X = vertex.BoneIndex[0];
                    _vertexArray[i].BlendWeights.X = vertex.BoneWeight[0];

                    _vertexArray[i].BlendIndices.Y = vertex.BoneIndex[1];
                    _vertexArray[i].BlendWeights.Y = vertex.BoneWeight[1];
                    WeightCount = 2;
                }
            }

            RebuildVertexBuffer();
            RebuildIndexBuffer();
        }
        private bool ValidateTextures(RmvSubModel item0, RmvSubModel item1, out string textureErrorMsg)
        {
            if (item0.Textures.Count != item1.Textures.Count)
            {
                textureErrorMsg = $"{item0.Header.ModelName} has a different number of textures then {item1.Header.ModelName}";
                return(false);
            }

            foreach (var texture in item0.Textures)
            {
                var res = item1.Textures.Count(x => x.Path == texture.Path);
                if (res != 1)
                {
                    textureErrorMsg = $"{item1.Header.ModelName} does not contain texture {texture.Path}";
                    return(false);
                }
            }

            textureErrorMsg = null;
            return(true);
        }
        public byte[] Save(bool onlySaveVisibleNodes)
        {
            List <string> boneNames = new List <string>();

            if (Skeleton.AnimationProvider.Skeleton != null)
            {
                boneNames = Skeleton.AnimationProvider.Skeleton.BoneNames.ToList();
            }

            var lods        = GetLodNodes();
            var orderedLods = lods.OrderBy(x => x.LodValue);

            RmvSubModel[][] newMeshList = new RmvSubModel[orderedLods.Count()][];
            for (int lodIndex = 0; lodIndex < orderedLods.Count(); lodIndex++)
            {
                var meshes = GetMeshesInLod(lodIndex, onlySaveVisibleNodes);

                newMeshList[lodIndex] = new RmvSubModel[meshes.Count];

                for (int meshIndex = 0; meshIndex < meshes.Count; meshIndex++)
                {
                    newMeshList[lodIndex][meshIndex] = meshes[meshIndex].CreateRmvSubModel();
                    newMeshList[lodIndex][meshIndex].UpdateAttachmentPointList(boneNames);
                }
            }

            Model.MeshList = newMeshList;
            Model.UpdateOffsets();

            using MemoryStream ms = new MemoryStream();
            using var writer      = new BinaryWriter(ms);


            Model.SaveToByteArray(writer);
            return(ms.ToArray());
        }