public static alien_pak_model Load(string FullFilePath) { alien_pak_model Result = new alien_pak_model(); Result.PAK = Generic.PAK.Load(FullFilePath, true); Result.Models = new List <alien_pak_model_entry>(Result.PAK.Header.EntryCount); for (int EntryIndex = 0; EntryIndex < Result.PAK.Header.EntryCount; ++EntryIndex) { byte[] EntryBuffer = Result.PAK.EntryDatas[EntryIndex]; BinaryReader Stream = new BinaryReader(new MemoryStream(EntryBuffer)); alien_pak_model_entry Model = new alien_pak_model_entry(); // TODO: Maybe this stuff can be moved to AlienLoadPAK, probably using an 'alien_pak_entry' value to check if // it is an array of entries. alien_pak_model_entry_header EntryHeader = Utilities.Consume <alien_pak_model_entry_header>(ref Stream); EntryHeader.FirstChunkIndex = BinaryPrimitives.ReverseEndianness(EntryHeader.FirstChunkIndex); EntryHeader.ChunkCount = BinaryPrimitives.ReverseEndianness(EntryHeader.ChunkCount); Model.Header = EntryHeader; Model.ChunkInfos = Utilities.ConsumeArray <alien_pak_model_chunk_info>(ref Stream, EntryHeader.ChunkCount); Utilities.Align(ref Stream, 16); Model.Chunks = new List <byte[]>(EntryHeader.ChunkCount); for (int ChunkIndex = 0; ChunkIndex < EntryHeader.ChunkCount; ++ChunkIndex) { alien_pak_model_chunk_info ChunkInfo = Model.ChunkInfos[ChunkIndex]; ChunkInfo.BINIndex = BinaryPrimitives.ReverseEndianness(ChunkInfo.BINIndex); ChunkInfo.Offset = BinaryPrimitives.ReverseEndianness(ChunkInfo.Offset); ChunkInfo.Size = BinaryPrimitives.ReverseEndianness(ChunkInfo.Size); Model.ChunkInfos[ChunkIndex] = ChunkInfo; Stream.BaseStream.Position = ChunkInfo.Offset; byte[] Chunk = Stream.ReadBytes(ChunkInfo.Size); Model.Chunks.Add(Chunk); } Result.Models.Add(Model); } return(Result); }
private void LoadModel(int EntryIndex) { if (EntryIndex < 0 || EntryIndex >= Result.ModelsPAK.Models.Count) { Debug.LogWarning("Asked to load model at index " + EntryIndex + ", which is out of bounds!"); //return new GameObject(); return; } alien_pak_model_entry ChunkArray = Result.ModelsPAK.Models[EntryIndex]; for (int ChunkIndex = 0; ChunkIndex < ChunkArray.Header.ChunkCount; ++ChunkIndex) { int BINIndex = ChunkArray.ChunkInfos[ChunkIndex].BINIndex; alien_model_bin_model_info Model = Result.ModelsBIN.Models[BINIndex]; //if (Model.BlockSize == 0) continue; alien_vertex_buffer_format VertexInput = Result.ModelsBIN.VertexBufferFormats[Model.VertexFormatIndex]; alien_vertex_buffer_format VertexInputLowDetail = Result.ModelsBIN.VertexBufferFormats[Model.VertexFormatIndexLowDetail]; BinaryReader Stream = new BinaryReader(new MemoryStream(ChunkArray.Chunks[ChunkIndex])); List <List <alien_vertex_buffer_format_element> > Elements = new List <List <alien_vertex_buffer_format_element> >(); alien_vertex_buffer_format_element ElementHeader = new alien_vertex_buffer_format_element(); foreach (alien_vertex_buffer_format_element Element in VertexInput.Elements) { if (Element.ArrayIndex == 0xFF) { ElementHeader = Element; continue; } while (Elements.Count - 1 < Element.ArrayIndex) { Elements.Add(new List <alien_vertex_buffer_format_element>()); } Elements[Element.ArrayIndex].Add(Element); } Elements.Add(new List <alien_vertex_buffer_format_element>() { ElementHeader }); List <UInt16> InIndices = new List <UInt16>(); List <Vector3> InVertices = new List <Vector3>(); List <Vector3> InNormals = new List <Vector3>(); List <Vector4> InTangents = new List <Vector4>(); List <Vector2> InUVs0 = new List <Vector2>(); List <Vector2> InUVs1 = new List <Vector2>(); List <Vector2> InUVs2 = new List <Vector2>(); List <Vector2> InUVs3 = new List <Vector2>(); List <Vector2> InUVs7 = new List <Vector2>(); //TODO: implement skeleton lookup for the indexes List <Vector4> InBoneIndexes = new List <Vector4>(); //The indexes of 4 bones that affect each vertex List <Vector4> InBoneWeights = new List <Vector4>(); //The weights for each bone for (int VertexArrayIndex = 0; VertexArrayIndex < Elements.Count; ++VertexArrayIndex) { alien_vertex_buffer_format_element Inputs = Elements[VertexArrayIndex][0]; if (Inputs.ArrayIndex == 0xFF) { for (int i = 0; i < Model.IndexCount; i++) { InIndices.Add(Stream.ReadUInt16()); } } else { for (int VertexIndex = 0; VertexIndex < Model.VertexCount; ++VertexIndex) { for (int ElementIndex = 0; ElementIndex < Elements[VertexArrayIndex].Count; ++ElementIndex) { alien_vertex_buffer_format_element Input = Elements[VertexArrayIndex][ElementIndex]; switch (Input.VariableType) { case alien_vertex_input_type.AlienVertexInputType_v3: { Vector3 Value = new Vector3(Stream.ReadSingle(), Stream.ReadSingle(), Stream.ReadSingle()); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_N: InNormals.Add(Value); break; case alien_vertex_input_slot.AlienVertexInputSlot_T: InTangents.Add(new Vector4(Value.x, Value.y, Value.z, 0)); break; case alien_vertex_input_slot.AlienVertexInputSlot_UV: //TODO: 3D UVW break; } ; break; } case alien_vertex_input_type.AlienVertexInputType_u32_C: { int Value = Stream.ReadInt32(); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_C: //?? break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_i: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_BI: InBoneIndexes.Add(Value); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_f: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); Value /= 255.0f; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_BW: float Sum = Value.x + Value.y + Value.z + Value.w; InBoneWeights.Add(Value / Sum); break; case alien_vertex_input_slot.AlienVertexInputSlot_UV: InUVs2.Add(new Vector2(Value.x, Value.y)); InUVs3.Add(new Vector2(Value.z, Value.w)); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v2s16_UV: { Vector2 Value = new Vector2(Stream.ReadInt16(), Stream.ReadInt16()); Value /= 2048.0f; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_UV: if (Input.VariantIndex == 0) { InUVs0.Add(Value); } else if (Input.VariantIndex == 1) { // TODO: We can figure this out based on alien_vertex_buffer_format_element. //Material->Material.Flags |= Material_HasTexCoord1; InUVs1.Add(Value); } else if (Input.VariantIndex == 2) { InUVs2.Add(Value); } else if (Input.VariantIndex == 3) { InUVs3.Add(Value); } else if (Input.VariantIndex == 7) { InUVs7.Add(Value); } break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4s16_f: { Vector4 Value = new Vector4(Stream.ReadInt16(), Stream.ReadInt16(), Stream.ReadInt16(), Stream.ReadInt16()); Value /= (float)Int16.MaxValue; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_P: InVertices.Add(Value); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_NTB: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); Value /= (float)byte.MaxValue - 0.5f; Value.Normalize(); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_N: InNormals.Add(Value); break; case alien_vertex_input_slot.AlienVertexInputSlot_T: break; case alien_vertex_input_slot.AlienVertexInputSlot_B: break; } } break; } } } } CATHODE.Utilities.Align(ref Stream, 16); } if (InVertices.Count == 0) { continue; } Mesh thisMesh = new Mesh(); thisMesh.name = Result.ModelsBIN.ModelFilePaths[BINIndex] + ": " + Result.ModelsBIN.ModelLODPartNames[BINIndex]; thisMesh.SetVertices(InVertices); thisMesh.SetNormals(InNormals); thisMesh.SetIndices(InIndices, MeshTopology.Triangles, 0); //0?? thisMesh.SetTangents(InTangents); thisMesh.SetUVs(0, InUVs0); thisMesh.SetUVs(1, InUVs1); thisMesh.SetUVs(2, InUVs2); thisMesh.SetUVs(3, InUVs3); thisMesh.SetUVs(7, InUVs7); //thisMesh.SetBoneWeights(InBoneWeights.ToArray()); thisMesh.RecalculateBounds(); thisMesh.RecalculateNormals(); thisMesh.RecalculateTangents(); GameObjectHolder ThisModelPart = new GameObjectHolder(); ThisModelPart.LocalScale = new Vector3(Model.ScaleFactor, Model.ScaleFactor, Model.ScaleFactor); ThisModelPart.Name = Result.ModelsBIN.ModelFilePaths[BINIndex] + ": " + Result.ModelsBIN.ModelLODPartNames[BINIndex] + " (" + Result.ModelsMTL.MaterialNames[Model.MaterialLibraryIndex] + ")"; ThisModelPart.MainMesh = thisMesh; ThisModelPart.DefaultMaterial = Model.MaterialLibraryIndex; LoadedModels[BINIndex] = ThisModelPart; } }
private void LoadMeshAssets() { AssetDatabase.StartAssetEditing(); for (int i = 0; i < levelData.ModelsPAK.Models.Count; i++) { alien_pak_model_entry ChunkArray = levelData.ModelsPAK.Models[i]; for (int ChunkIndex = 0; ChunkIndex < ChunkArray.Header.ChunkCount; ++ChunkIndex) { int BINIndex = ChunkArray.ChunkInfos[ChunkIndex].BINIndex; alien_model_bin_model_info Model = levelData.ModelsBIN.Models[BINIndex]; //if (Model.BlockSize == 0) continue; alien_vertex_buffer_format VertexInput = levelData.ModelsBIN.VertexBufferFormats[Model.VertexFormatIndex]; alien_vertex_buffer_format VertexInputLowDetail = levelData.ModelsBIN.VertexBufferFormats[Model.VertexFormatIndexLowDetail]; BinaryReader Stream = new BinaryReader(new MemoryStream(ChunkArray.Chunks[ChunkIndex])); List <List <alien_vertex_buffer_format_element> > Elements = new List <List <alien_vertex_buffer_format_element> >(); alien_vertex_buffer_format_element ElementHeader = new alien_vertex_buffer_format_element(); foreach (alien_vertex_buffer_format_element Element in VertexInput.Elements) { if (Element.ArrayIndex == 0xFF) { ElementHeader = Element; continue; } while (Elements.Count - 1 < Element.ArrayIndex) { Elements.Add(new List <alien_vertex_buffer_format_element>()); } Elements[Element.ArrayIndex].Add(Element); } Elements.Add(new List <alien_vertex_buffer_format_element>() { ElementHeader }); List <UInt16> InIndices = new List <UInt16>(); List <Vector3> InVertices = new List <Vector3>(); List <Vector3> InNormals = new List <Vector3>(); List <Vector4> InTangents = new List <Vector4>(); List <Vector2> InUVs0 = new List <Vector2>(); List <Vector2> InUVs1 = new List <Vector2>(); List <Vector2> InUVs2 = new List <Vector2>(); List <Vector2> InUVs3 = new List <Vector2>(); List <Vector2> InUVs7 = new List <Vector2>(); //TODO: implement skeleton lookup for the indexes List <Vector4> InBoneIndexes = new List <Vector4>(); //The indexes of 4 bones that affect each vertex List <Vector4> InBoneWeights = new List <Vector4>(); //The weights for each bone for (int VertexArrayIndex = 0; VertexArrayIndex < Elements.Count; ++VertexArrayIndex) { alien_vertex_buffer_format_element Inputs = Elements[VertexArrayIndex][0]; if (Inputs.ArrayIndex == 0xFF) { for (int x = 0; x < Model.IndexCount; x++) { InIndices.Add(Stream.ReadUInt16()); } } else { for (int VertexIndex = 0; VertexIndex < Model.VertexCount; ++VertexIndex) { for (int ElementIndex = 0; ElementIndex < Elements[VertexArrayIndex].Count; ++ElementIndex) { alien_vertex_buffer_format_element Input = Elements[VertexArrayIndex][ElementIndex]; switch (Input.VariableType) { case alien_vertex_input_type.AlienVertexInputType_v3: { Vector3 Value = new Vector3(Stream.ReadSingle(), Stream.ReadSingle(), Stream.ReadSingle()); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_N: InNormals.Add(Value); break; case alien_vertex_input_slot.AlienVertexInputSlot_T: InTangents.Add(new Vector4(Value.x, Value.y, Value.z, 0)); break; case alien_vertex_input_slot.AlienVertexInputSlot_UV: //TODO: 3D UVW break; } ; break; } case alien_vertex_input_type.AlienVertexInputType_u32_C: { int Value = Stream.ReadInt32(); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_C: //?? break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_i: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_BI: InBoneIndexes.Add(Value); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_f: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); Value /= 255.0f; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_BW: float Sum = Value.x + Value.y + Value.z + Value.w; InBoneWeights.Add(Value / Sum); break; case alien_vertex_input_slot.AlienVertexInputSlot_UV: InUVs2.Add(new Vector2(Value.x, Value.y)); InUVs3.Add(new Vector2(Value.z, Value.w)); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v2s16_UV: { Vector2 Value = new Vector2(Stream.ReadInt16(), Stream.ReadInt16()); Value /= 2048.0f; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_UV: if (Input.VariantIndex == 0) { InUVs0.Add(Value); } else if (Input.VariantIndex == 1) { // TODO: We can figure this out based on alien_vertex_buffer_format_element. //Material->Material.Flags |= Material_HasTexCoord1; InUVs1.Add(Value); } else if (Input.VariantIndex == 2) { InUVs2.Add(Value); } else if (Input.VariantIndex == 3) { InUVs3.Add(Value); } else if (Input.VariantIndex == 7) { InUVs7.Add(Value); } break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4s16_f: { Vector4 Value = new Vector4(Stream.ReadInt16(), Stream.ReadInt16(), Stream.ReadInt16(), Stream.ReadInt16()); Value /= (float)Int16.MaxValue; switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_P: InVertices.Add(Value); break; } break; } case alien_vertex_input_type.AlienVertexInputType_v4u8_NTB: { Vector4 Value = new Vector4(Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte()); Value /= (float)byte.MaxValue - 0.5f; Value.Normalize(); switch (Input.ShaderSlot) { case alien_vertex_input_slot.AlienVertexInputSlot_N: InNormals.Add(Value); break; case alien_vertex_input_slot.AlienVertexInputSlot_T: break; case alien_vertex_input_slot.AlienVertexInputSlot_B: break; } } break; } } } } CATHODE.Utilities.Align(ref Stream, 16); } if (InVertices.Count == 0) { continue; } Mesh thisMesh = new Mesh(); thisMesh.name = levelData.ModelsBIN.ModelFilePaths[BINIndex] + ": " + levelData.ModelsBIN.ModelLODPartNames[BINIndex]; thisMesh.SetVertices(InVertices); thisMesh.SetNormals(InNormals); thisMesh.SetIndices(InIndices, MeshTopology.Triangles, 0); //0?? thisMesh.SetTangents(InTangents); thisMesh.SetUVs(0, InUVs0); thisMesh.SetUVs(1, InUVs1); thisMesh.SetUVs(2, InUVs2); thisMesh.SetUVs(3, InUVs3); thisMesh.SetUVs(7, InUVs7); //thisMesh.SetBoneWeights(InBoneWeights.ToArray()); thisMesh.RecalculateBounds(); thisMesh.RecalculateNormals(); thisMesh.RecalculateTangents(); //TODO: do this as proper submeshes string fullFilePath = "Assets/Resources/" + SharedVals.instance.LevelName + "/Meshes/" + levelData.ModelsBIN.ModelFilePaths[BINIndex] + "_" + levelData.ModelsBIN.ModelLODPartNames[BINIndex] + "_" + ChunkIndex + ".asset"; string fileDirectory = GetDirectory(fullFilePath); if (!Directory.Exists(fileDirectory)) { Directory.CreateDirectory(fileDirectory); } AssetDatabase.CreateAsset(thisMesh, fullFilePath); } } AssetDatabase.StopAssetEditing(); }