/// <summary> /// Adds a model info to the record if it's not already there. /// </summary> /// <param name="ModelId"></param> /// <returns></returns> public bool AddRecordById(int ModelId) { //if (ModelId > 65500) return false; InitArchFile(); uint uModelId = (uint)ModelId; // Test if model is actually in BSA database and has a mesh. If not skip int index = arch3dFile.GetRecordIndex(uModelId); if (index == -1) { Debug.Log("ModelId " + ModelId.ToString() + " not found in Daggerfall database"); return(false); } // Go reverse order down, and add successfully if you've found nothing until the point you find it's model-1 number in the index // Counts the least records this way // eg 1000 records, ask for ModelID 20000 assuming highest is 5000, then add // ModelID can never be lower than records // Check to ensure ID doesn't already exist. //if (record.Count <= ModelId) for (int i = record.Count - 1; i >= 0; i--) { if (record[i].ModelID >= ModelId) { return(false); } else if (record[i].ModelID < ModelId) { break; // Smaller than the highest model number. Perhaps you missed it? } } /* * foreach (DfModelRecord df in record) * { * if (df.ModelID == ModelId) * { * return false; * } * * * } */ DfModelRecord dfMod = new DfModelRecord(); dfMod.ModelID = ModelId; dfMod.Labels = new List <string>(); record.Add(dfMod); return(true); }
/// <summary> /// Loads model data for conversion. /// </summary> /// <param name="id">Model ID.</param> /// <param name="scale">Amount to scale model.</param> private void LoadModelData(uint id, float scale) { // Open ARCH3D.BSA Arch3dFile arch3dFile = new Arch3dFile( Path.Combine(arena2Path, "ARCH3D.BSA"), FileUsage.UseDisk, true); // Get DFMesh int record = arch3dFile.GetRecordIndex(id); DFMesh dfMesh = arch3dFile.GetMesh(record); // Scale DFMesh if (scale != 1.0f) { foreach (var mesh in dfMesh.SubMeshes) { foreach (var plane in mesh.Planes) { for (int point = 0; point < plane.Points.Length; point++) { plane.Points[point].X *= scale; plane.Points[point].Y *= scale; plane.Points[point].Z *= scale; } } } } // Load model data model = new ModelData(); model.DFMesh = dfMesh; LoadVertices(ref model); LoadIndices(ref model); }
/// <summary> /// Loads model data from DFMesh. /// </summary> /// <param name="id">Key of source mesh.</param> /// <param name="modelData">ModelData out.</param> /// <returns>True if successful.</returns> private bool LoadModelData(uint id, out ModelData modelData) { // Return from cache if present if (cacheModelData && modelDataDict.ContainsKey(id)) { modelData = modelDataDict[id]; return(true); } // New model object modelData = new ModelData(); // Find mesh index int index = arch3dFile.GetRecordIndex(id); if (index == -1) { return(false); } // Get DFMesh DFMesh dfMesh = arch3dFile.GetMesh(index); if (dfMesh.TotalVertices == 0) { return(false); } // Load mesh data modelData.DFMesh = dfMesh; LoadVertices(ref modelData); LoadIndices(ref modelData); AddModelTangents(ref modelData); CreateModelBuffers(graphicsDevice, ref modelData); // Load materials for (int i = 0; i < modelData.SubMeshes.Length; i++) { // Create material BaseMaterialEffect material = CreateModelMaterial( modelData.DFMesh.SubMeshes[i].TextureArchive, modelData.DFMesh.SubMeshes[i].TextureRecord); // Save key in submesh modelData.SubMeshes[i].MaterialKey = material.ID; } // Add to cache if (cacheModelData) { modelDataDict.Add(id, modelData); } return(true); }
/// <summary> /// ARCH3D.BSA: Modify base texture assigned to plane. /// </summary> /// <param name="MeshID">ID of mesh.</param> /// <param name="planeIndex">Plane index.</param> /// <param name="textureArchive">New texture archive index to set.</param> /// <param name="textureRecord">New texture record inex to set.</param> public void ModPlaneTexture(uint MeshID, int planeIndex, int textureArchive, int textureRecord) { // Load resources string path = Path.Combine(arena2Path, "ARCH3D.BSA"); Arch3dFile arch3dFile = new Arch3dFile( path, FileUsage.UseMemory, true); BsaFile bsaFile = new BsaFile( path, FileUsage.UseDisk, false); // Get mesh record int index = arch3dFile.GetRecordIndex(MeshID); arch3dFile.LoadRecord(index); Arch3dFile.MeshRecord record = arch3dFile.MeshRecords[index]; // Get binary record byte[] buffer = bsaFile.GetRecordBytes(index); // Compose new texture bitfield UInt16 textureBitfield = (UInt16)((textureArchive << 7) + textureRecord); // Get start position of plane header long position = record.PureMesh.Planes[planeIndex].Header.Position; // Offset to texture bitfield position += 2; // Create stream to binary record MemoryStream ms = new MemoryStream(buffer); ms.Position = position; // Write new bitfield BinaryWriter writer = new BinaryWriter(ms, Encoding.UTF8); writer.Write(textureBitfield); writer.Close(); // Save back binary record bsaFile.RewriteRecord(index, buffer); }
/// <summary> /// Loads model data. /// </summary> /// <param name="id">Key of source mesh.</param> /// <param name="modelData">ModelData out.</param> /// <param name="scale">Scale of model.</param> /// <returns>True if successful.</returns> public bool GetModelData(uint id, out ModelData modelData) { // New model object modelData = new ModelData(); // Ready check if (!IsReady) { return(false); } // Return from cache if present if (modelDict.ContainsKey((int)id)) { modelData = modelDict[(int)id]; return(true); } // Find mesh index int index = arch3dFile.GetRecordIndex(id); if (index == -1) { return(false); } // Get DFMesh DFMesh dfMesh = arch3dFile.GetMesh(index); if (dfMesh.TotalVertices == 0) { return(false); } // Load mesh data modelData.DFMesh = dfMesh; LoadVertices(ref modelData, GlobalScale); LoadIndices(ref modelData); // Add to cache modelDict.Add((int)id, modelData); return(true); }
/// <summary> /// Loads model data from DFMesh. /// </summary> /// <param name="id">Key of source mesh.</param> /// <param name="model">ModelData out.</param> /// <returns>True if successful.</returns> private bool LoadModelData(uint id, out ModelData model) { // Return from cache if present if (cacheModelData && modelDataDict.ContainsKey(id)) { model = modelDataDict[id]; return(true); } // New model object model = new ModelData(); // Find mesh index int index = arch3dFile.GetRecordIndex(id); if (index == -1) { return(false); } // Get DFMesh DFMesh dfMesh = arch3dFile.GetMesh(index); if (dfMesh.TotalVertices == 0) { return(false); } // Load mesh data model.DFMesh = dfMesh; LoadVertices(ref model); LoadIndices(ref model); AddModelTangents(ref model); CreateModelBuffers(ref model); // Add to cache if (cacheModelData) { modelDataDict.Add(id, model); } return(true); }
/// <summary> /// Exports a DFMesh object to Collada format. /// </summary> /// <param name="id">ID of DFMesh to export.</param> /// <param name="scale">Scale model by value.</param> /// <returns>True if successful.</returns> public bool DFMeshToCollada(uint id, float scale) { // Get source mesh int index = arch3dFile.GetRecordIndex(id); DFMesh dfMesh = arch3dFile.GetMesh(index); if (dfMesh.SubMeshes == null) { string error = string.Format("Model '{0}' not found", id); Console.WriteLine(error); throw new Exception(error); } // Test model output path if (!Directory.Exists(modelOutputPath)) { string error = string.Format("Model output path '{0}' does not exist.", modelOutputPath); Console.WriteLine(error); throw new Exception(error); } // Test or create image output path string fullImageOutputPath = Path.Combine(modelOutputPath, imageOutputRelativePath); if (!Directory.Exists(fullImageOutputPath)) { Directory.CreateDirectory(fullImageOutputPath); } // Scale model if (scale != 1.0f) { foreach (var mesh in dfMesh.SubMeshes) { foreach (var plane in mesh.Planes) { for (int point = 0; point < plane.Points.Length; point++) { plane.Points[point].X *= scale; plane.Points[point].Y *= scale; plane.Points[point].Z *= scale; } } } } // Create dae root string filePath = Path.Combine(modelOutputPath, dfMesh.ObjectId.ToString() + ".dae"); _daeElement root = dae.add(filePath); // Build dae file AddAsset(ref root); AddGeometry(ref root, ref dfMesh); AddImages(ref root, ref dfMesh); AddEffects(ref root, ref dfMesh); AddMaterials(ref root, ref dfMesh); AddVisualScene(ref root, ref dfMesh); // Write dae file dae.writeAll(); return(true); }