/// <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);
    }
예제 #2
0
        /// <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);
        }
예제 #3
0
        /// <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);
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        /// <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);
        }
예제 #7
0
        /// <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);
        }