Пример #1
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut = new List <StaticDoor>();

            // Iterate through all subrecords
            int recordCount = 0;

            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3   subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3   subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix   = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3   modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                    Matrix4x4 modelMatrix   = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    if (modelData.Doors != null)
                    {
                        doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix));
                    }

                    // Add or combine
                    if (combiner == null || IsCityGate(obj.ModelIdNum))
                    {
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    }
                    else
                    {
                        combiner.Add(ref modelData, modelMatrix);
                    }
                }

                // Increment record count
                recordCount++;
            }
        }
Пример #2
0
        /// <summary>
        /// Adds another ModelCombiner to this one.
        /// </summary>
        /// <param name="other">Other ModelCombiner.</param>
        /// <param name="matrix">Transform to apply</param>
        public void Add(ModelCombiner other, Matrix4x4 matrix)
        {
            // Do nothing if sealed
            if (isSealed || other.isSealed)
            {
                return;
            }

            // Add other items to this builder
            foreach (var item in other.builderDictionary)
            {
                BatchData batchData = item.Value;
                AddData(item.Key, ref batchData, matrix);
            }
        }
Пример #3
0
        private static void AddProps(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut = new List <StaticDoor>();

            // Iterate through all misc records
            foreach (DFBlock.RmbBlock3dObjectRecord obj in blockData.RmbBlock.Misc3dObjectRecords)
            {
                // Get model transform
                Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos + propsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;
                Vector3   modelRotation = new Vector3(-obj.XRotation / BlocksFile.RotationDivisor, -obj.YRotation / BlocksFile.RotationDivisor, -obj.ZRotation / BlocksFile.RotationDivisor);
                Vector3   modelScale    = GetModelScaleVector(obj);
                Matrix4x4 modelMatrix   = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), modelScale);

                // Get model data
                ModelData modelData;
                dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                // Does this model have doors?
                if (modelData.Doors != null)
                {
                    doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));
                }

                // Import custom GameObject
                if (MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix) != null)
                {
                    continue;
                }

                // Use Daggerfall Model
                // Add or combine
                if (combiner == null || IsBulletinBoard(obj.ModelIdNum) || PlayerActivate.HasCustomActivation(obj.ModelIdNum))
                {
                    AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                }
                else
                {
                    combiner.Add(ref modelData, modelMatrix);
                }
            }
        }
Пример #4
0
        private static void AddProps(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut = new List <StaticDoor>();

            // Iterate through all misc records
            foreach (DFBlock.RmbBlock3dObjectRecord obj in blockData.RmbBlock.Misc3dObjectRecords)
            {
                // Get model transform
                Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos + propsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;
                Vector3   modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 modelMatrix   = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                // Get model data
                ModelData modelData;
                dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                // Does this model have doors?
                if (modelData.Doors != null)
                {
                    doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));
                }

                // Add or combine
                if (combiner == null)
                {
                    AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                }
                else
                {
                    combiner.Add(ref modelData, modelMatrix);
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Instantiate base RDB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <param name="textureTable">Optional texture table for dungeon.</param>
        /// <param name="allowExitDoors">Add exit doors to block.</param>
        /// <param name="cloneFrom">Clone and build on a prefab object template.</param>
        /// <param name="serialize">Allow for serialization of supported sub-objects.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(
            ref DFBlock blockData,
            Dictionary<int, ActionLink> actionLinkDict,
            int[] textureTable = null,
            bool allowExitDoors = true,
            DaggerfallRDBBlock cloneFrom = null,
            bool serialize = true)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return null;

            // Use default texture table if one not specified
            if (textureTable == null)
                textureTable = StaticTextureTables.DefaultTextureTable;

            // Create gameobject
            GameObject go;
            string name = string.Format("DaggerfallBlock [{0}]", blockData.Name);
            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent<DaggerfallRDBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;
            if (dfUnity.Option_CombineRDB)
                combiner = new ModelCombiner();

            // Add parent node
            GameObject modelsNode = new GameObject("Models");
            GameObject actionModelsNode = new GameObject("Action Models");
            modelsNode.transform.parent = go.transform;
            actionModelsNode.transform.parent = go.transform;

            // Add models
            List<StaticDoor> exitDoors;
            AddModels(
                dfUnity,
                ref blockData,
                actionLinkDict,
                textureTable,
                allowExitDoors,
                out exitDoors,
                serialize,
                combiner,
                modelsNode.transform,
                actionModelsNode.transform);

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObject cgo = GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                    cgo.GetComponent<DaggerfallMesh>().SetDungeonTextures(textureTable);
                }
            }

            // Add exit doors
            if (exitDoors.Count > 0)
            {
                DaggerfallStaticDoors c = go.AddComponent<DaggerfallStaticDoors>();
                c.Doors = exitDoors.ToArray();
            }

            return go;
        }
Пример #6
0
        public static GameObject CreateCombinedMeshGameObject(
            ModelCombiner combiner,
            string meshName,
            Transform parent,
            bool makeStatic = false)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            // Create gameobject
            GameObject go = new GameObject(meshName);

            if (parent)
            {
                go.transform.parent = parent;
            }

            // Assign components
            DaggerfallMesh dfMesh       = go.AddComponent <DaggerfallMesh>();
            MeshFilter     meshFilter   = go.GetComponent <MeshFilter>();
            MeshRenderer   meshRenderer = go.GetComponent <MeshRenderer>();

            // Assign mesh and materials
            CachedMaterial[] cachedMaterials;
            int[]            textureKeys;
            bool             hasAnimations;
            Mesh             mesh = dfUnity.MeshReader.GetCombinedMesh(
                dfUnity,
                combiner,
                out cachedMaterials,
                out textureKeys,
                out hasAnimations,
                dfUnity.MeshReader.AddMeshTangents,
                dfUnity.MeshReader.AddMeshLightmapUVs);

            // Assign animated materials component if required
            if (hasAnimations)
            {
                AssignAnimateTextureComponent(cachedMaterials, go);
            }

            // Assign mesh and materials array
            if (mesh)
            {
                meshFilter.sharedMesh        = mesh;
                meshRenderer.sharedMaterials = GetMaterialArray(cachedMaterials);
                dfMesh.SetDefaultTextures(textureKeys);
            }

            // Assign collider
            if (dfUnity.Option_AddMeshColliders)
            {
                MeshCollider collider = go.AddComponent <MeshCollider>();
                collider.sharedMesh = mesh;
            }

            // Assign static
            if (makeStatic)
            {
                go.isStatic = true;
            }

            return(go);
        }
Пример #7
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            int layoutX,
            int layoutY,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            out List <StaticBuilding> buildingsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut     = new List <StaticDoor>();
            buildingsOut = new List <StaticBuilding>();

            // Iterate through all subrecords
            int recordCount = 0;

            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3   subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3   subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix   = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                bool firstModel = true;
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3   modelRotation = new Vector3(-obj.XRotation / BlocksFile.RotationDivisor, -obj.YRotation / BlocksFile.RotationDivisor, -obj.ZRotation / BlocksFile.RotationDivisor);
                    Vector3   modelScale    = GetModelScaleVector(obj);
                    Matrix4x4 modelMatrix   = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), modelScale);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    StaticDoor[] staticDoors = null;
                    if (modelData.Doors != null)
                    {
                        staticDoors = GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix);
                    }

                    // Store building information for first model of record
                    // First model is main record structure, others are attachments like posts
                    // Only main structure is needed to resolve building after hit-test
                    int buildingKey = 0;
                    if (firstModel)
                    {
                        // Create building key for this record - considered experimental for now
                        buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)recordCount);

                        StaticBuilding staticBuilding = new StaticBuilding();
                        staticBuilding.modelMatrix = modelMatrix;
                        staticBuilding.recordIndex = recordCount;
                        staticBuilding.centre      = new Vector3(modelData.DFMesh.Centre.X, modelData.DFMesh.Centre.Y, modelData.DFMesh.Centre.Z) * MeshReader.GlobalScale;
                        staticBuilding.size        = new Vector3(modelData.DFMesh.Size.X, modelData.DFMesh.Size.Y, modelData.DFMesh.Size.Z) * MeshReader.GlobalScale;
                        buildingsOut.Add(staticBuilding);
                        firstModel = false;
                    }

                    bool dontCreateStaticDoors = false;

                    // Import custom GameObject or use Daggerfall Model
                    GameObject go;
                    if (go = MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix))
                    {
                        // Find doors
                        if (staticDoors != null && staticDoors.Length > 0)
                        {
                            CustomDoor.InitDoors(go, staticDoors, buildingKey, out dontCreateStaticDoors);
                        }
                    }
                    else if (combiner == null || IsCityGate(obj.ModelIdNum) || IsBulletinBoard(obj.ModelIdNum) || PlayerActivate.HasCustomActivation(obj.ModelIdNum))
                    {
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    }
                    else
                    {
                        combiner.Add(ref modelData, modelMatrix);
                    }

                    if (modelData.Doors != null && !dontCreateStaticDoors)
                    {
                        doorsOut.AddRange(staticDoors);
                    }
                }

                // Increment record count
                recordCount++;
            }
        }
Пример #8
0
        /// <summary>
        /// Instantiate base RMB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <param name="layoutX">X coordinate in parent map layout.</param>
        /// /// <param name="layoutY">Y coordinate in parent map layout.</param>
        /// <param name="cloneFrom">Prefab to clone from.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(ref DFBlock blockData, int layoutX, int layoutY, DaggerfallRMBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor>     modelDoors;
            List <StaticDoor>     propDoors;
            List <StaticBuilding> modelBuildings;

            // Add models and static props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, layoutX, layoutY, ref blockData, out modelDoors, out modelBuildings, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Combine list of doors found in models and props
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }

            // Assign building key to each door
            for (int i = 0; i < allDoors.Count; i++)
            {
                StaticDoor door = allDoors[i];
                door.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)door.recordIndex);
                allDoors[i]      = door;
            }

            // Assign building key to each building
            for (int i = 0; i < modelBuildings.Count; i++)
            {
                StaticBuilding building = modelBuildings[i];
                building.buildingKey = BuildingDirectory.MakeBuildingKey((byte)layoutX, (byte)layoutY, (byte)building.recordIndex);
                modelBuildings[i]    = building;
            }

            // Add static doors component
            if (allDoors.Count > 0)
            {
                AddStaticDoors(allDoors.ToArray(), go);
            }

            // Add static buildings component
            if (modelBuildings.Count > 0)
            {
                AddStaticBuildings(modelBuildings.ToArray(), go);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Пример #9
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List <StaticDoor> doorsOut,
            out List <StaticBuilding> buildingsOut,
            ModelCombiner combiner = null,
            Transform parent       = null)
        {
            doorsOut     = new List <StaticDoor>();
            buildingsOut = new List <StaticBuilding>();

            // Iterate through all subrecords
            int recordCount = 0;

            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3   subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3   subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix   = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                bool firstModel = true;
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3   modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3   modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                    Matrix4x4 modelMatrix   = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    if (modelData.Doors != null)
                    {
                        doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix));
                    }

                    // Store building information for first model of record
                    // First model is main record structure, others are attachments like posts
                    // Only main structure is needed to resolve building after hit-test
                    if (firstModel)
                    {
                        StaticBuilding staticBuilding = new StaticBuilding();
                        staticBuilding.modelMatrix = modelMatrix;
                        staticBuilding.recordIndex = recordCount;
                        staticBuilding.centre      = new Vector3(modelData.DFMesh.Centre.X, modelData.DFMesh.Centre.Y, modelData.DFMesh.Centre.Z) * MeshReader.GlobalScale;
                        staticBuilding.size        = new Vector3(modelData.DFMesh.Size.X, modelData.DFMesh.Size.Y, modelData.DFMesh.Size.Z) * MeshReader.GlobalScale;
                        buildingsOut.Add(staticBuilding);
                        firstModel = false;
                    }

                    // Import custom GameObject
                    if (MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, parent, modelMatrix) != null)
                    {
                        continue;
                    }

                    // Use Daggerfall Model
                    // Add or combine
                    if (combiner == null || IsCityGate(obj.ModelIdNum))
                    {
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    }
                    else
                    {
                        combiner.Add(ref modelData, modelMatrix);
                    }
                }

                // Increment record count
                recordCount++;
            }
        }
Пример #10
0
        /// <summary>
        /// Adds models and their actions to scene.
        /// </summary>
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            Dictionary<int, ActionLink> actionLinkDict,
            int[] textureTable,
            bool allowExitDoors,
            out List<StaticDoor> exitDoorsOut,
            bool serialize,
            ModelCombiner combiner = null,
            Transform modelsParent = null,
            Transform actionModelsParent = null)
        {
            exitDoorsOut = new List<StaticDoor>();

            // Iterate object groups
            foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList)
            {
                // Skip empty object groups
                if (null == group.RdbObjects)
                {
                    continue;
                }

                // Iterate objects in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    // Add models
                    if (obj.Type == DFBlock.RdbResourceTypes.Model)
                    {
                        // Get model reference index and id
                        int modelReference = obj.Resources.ModelResource.ModelIndex;
                        uint modelId = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;

                        // Filter exit door models where flag not set
                        if (modelId == exitDoorModelID && !allowExitDoors)
                            continue;

                        // Filter action door models
                        // These must be added by AddActionDoors()
                        if (IsActionDoor(ref blockData, obj, modelReference))
                            continue;

                        // Get matrix
                        Matrix4x4 modelMatrix = GetModelMatrix(obj);

                        // Get model data
                        ModelData modelData;
                        dfUnity.MeshReader.GetModelData(modelId, out modelData);

                        // Add to static doors
                        exitDoorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));

                        // Check if model has an action record
                        bool hasAction = HasAction(obj);

                        // Special handling for tapestries and banners
                        // Some of these are so far out from wall player can become stuck behind them
                        // Adding model invidually without collider to avoid problem
                        // Not sure if these object ever actions, but bypass this hack if they do
                        if (modelId >= minTapestryID && modelId <= maxTapestryID && !hasAction)
                        {
                            AddStandaloneModel(dfUnity, ref modelData, modelMatrix, modelsParent, hasAction, true);
                            continue;
                        }

                        // Add or combine
                        GameObject standaloneObject = null;
                        Transform parent = (hasAction) ? actionModelsParent : modelsParent;
                        if (combiner == null || hasAction)
                        {
                            standaloneObject = AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent, hasAction);
                            standaloneObject.GetComponent<DaggerfallMesh>().SetDungeonTextures(textureTable);
                        }
                        else
                        {
                            combiner.Add(ref modelData, modelMatrix);
                        }

                        // Add action
                        if (hasAction && standaloneObject != null)
                            AddActionModelHelper(standaloneObject, actionLinkDict, obj, ref blockData, serialize);
                    }
                }
            }
        }
Пример #11
0
        public static GameObject CreateGameObject(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            bool disableGround = false,
            DaggerfallBillboardBatch natureBatch = null)
        {
            // Create gameobject
            GameObject go = new GameObject(string.Format("DaggerfallBlock [Name={0}]", blockData.Name));
            //go.AddComponent<DaggerfallBlock>();

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor> modelDoors;
            List <StaticDoor> propDoors;

            // Add models and props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Add doors
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }
            if (allDoors.Count > 0)
            {
                AddDoors(allDoors.ToArray(), go);
            }

            // Add block flats
            GameObject flatsNode = new GameObject("Flats");

            flatsNode.transform.parent = go.transform;
            AddBlockFlats(dfUnity, ref blockData, flatsNode.transform);

            // Add nature flats
            if (natureBatch == null)
            {
                AddNatureFlats(dfUnity, ref blockData, flatsNode.transform);
            }
            else
            {
                AddNatureFlatsToBatch(natureBatch, ref blockData);
            }

            // Add ground plane
            if (dfUnity.Option_SimpleGroundPlane && !disableGround)
            {
                AddSimpleGroundPlane(dfUnity, ref blockData, go.transform);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Пример #12
0
        private static void AddProps(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List<StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent = null)
        {
            doorsOut = new List<StaticDoor>();

            // Iterate through all misc records
            foreach (DFBlock.RmbBlock3dObjectRecord obj in blockData.RmbBlock.Misc3dObjectRecords)
            {
                // Get model transform
                Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos + propsOffsetY, obj.ZPos + BlocksFile.RMBDimension) * MeshReader.GlobalScale;
                Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                // Get model data
                ModelData modelData;
                dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                // Does this model have doors?
                if (modelData.Doors != null)
                    doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));

                // Add or combine
                if (combiner == null)
                    AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                else
                    combiner.Add(ref modelData, modelMatrix);
            }
        }
        public static GameObject CreateCombinedMeshGameObject(
            ModelCombiner combiner,
            string meshName,
            Transform parent,
            bool makeStatic = false)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            // Create gameobject
            GameObject go = new GameObject(meshName);
            if (parent)
                go.transform.parent = parent;

            // Assign components
            DaggerfallMesh dfMesh = go.AddComponent<DaggerfallMesh>();
            MeshFilter meshFilter = go.GetComponent<MeshFilter>();
            MeshRenderer meshRenderer = go.GetComponent<MeshRenderer>();

            // Assign mesh and materials
            CachedMaterial[] cachedMaterials;
            int[] textureKeys;
            bool hasAnimations;
            Mesh mesh = dfUnity.MeshReader.GetCombinedMesh(
                dfUnity,
                combiner,
                out cachedMaterials,
                out textureKeys,
                out hasAnimations,
                dfUnity.MeshReader.AddMeshTangents,
                dfUnity.MeshReader.AddMeshLightmapUVs);

            // Assign animated materials component if required
            if (hasAnimations)
                AssignAnimatedMaterialComponent(cachedMaterials, go);

            // Assign mesh and materials array
            if (mesh)
            {
                meshFilter.sharedMesh = mesh;
                meshRenderer.sharedMaterials = GetMaterialArray(cachedMaterials);
                dfMesh.SetDefaultTextures(textureKeys);
            }

            // Assign collider
            if (dfUnity.Option_AddMeshColliders)
            {
                MeshCollider collider = go.AddComponent<MeshCollider>();
                collider.sharedMesh = mesh;
            }

            // Assign static
            if (makeStatic)
                go.isStatic = true;

            return go;
        }
Пример #14
0
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            out List<StaticDoor> doorsOut,
            ModelCombiner combiner = null,
            Transform parent = null)
        {
            doorsOut = new List<StaticDoor>();

            // Iterate through all subrecords
            int recordCount = 0;
            foreach (DFBlock.RmbSubRecord subRecord in blockData.RmbBlock.SubRecords)
            {
                // Get subrecord transform
                Vector3 subRecordPosition = new Vector3(subRecord.XPos, 0, BlocksFile.RMBDimension - subRecord.ZPos) * MeshReader.GlobalScale;
                Vector3 subRecordRotation = new Vector3(0, -subRecord.YRotation / BlocksFile.RotationDivisor, 0);
                Matrix4x4 subRecordMatrix = Matrix4x4.TRS(subRecordPosition, Quaternion.Euler(subRecordRotation), Vector3.one);

                // Iterate through models in this subrecord
                foreach (DFBlock.RmbBlock3dObjectRecord obj in subRecord.Exterior.Block3dObjectRecords)
                {
                    // Get model transform
                    Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale;
                    Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0);
                    Matrix4x4 modelMatrix = subRecordMatrix * Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one);

                    // Get model data
                    ModelData modelData;
                    dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData);

                    // Does this model have doors?
                    if (modelData.Doors != null)
                        doorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, recordCount, modelMatrix));

                    // Add or combine
                    if (combiner == null || IsCityGate(obj.ModelIdNum))
                        AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent);
                    else
                        combiner.Add(ref modelData, modelMatrix);
                }

                // Increment record count
                recordCount++;
            }
        }
Пример #15
0
        /// <summary>
        /// Instantiate base RMB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(ref DFBlock blockData, DaggerfallRMBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;
            if (!dfUnity.IsReady)
                return null;

            // Create gameobject
            GameObject go;
            string name = string.Format("DaggerfallBlock [{0}]", blockData.Name);
            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent<DaggerfallRMBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;
            if (dfUnity.Option_CombineRMB)
                combiner = new ModelCombiner();

            // Lists to receive any doors found in this block
            List<StaticDoor> modelDoors;
            List<StaticDoor> propDoors;

            // Add models and static props
            GameObject modelsNode = new GameObject("Models");
            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Add doors
            List<StaticDoor> allDoors = new List<StaticDoor>();
            if (modelDoors.Count > 0) allDoors.AddRange(modelDoors);
            if (propDoors.Count > 0) allDoors.AddRange(propDoors);
            if (allDoors.Count > 0)
                AddStaticDoors(allDoors.ToArray(), go);

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return go;
        }
Пример #16
0
        /// <summary>
        /// Adds models and their actions to scene.
        /// </summary>
        private static void AddModels(
            DaggerfallUnity dfUnity,
            ref DFBlock blockData,
            int[] textureTable,
            bool allowExitDoors,
            out List <StaticDoor> exitDoorsOut,
            ModelCombiner combiner       = null,
            Transform modelsParent       = null,
            Transform actionModelsParent = null)
        {
            exitDoorsOut = new List <StaticDoor>();

            // Action record linkages
            Dictionary <int, ActionLink> actionLinkDict = new Dictionary <int, ActionLink>();

            // Iterate object groups
            int groupIndex = 0;

            foreach (DFBlock.RdbObjectRoot group in blockData.RdbBlock.ObjectRootList)
            {
                // Skip empty object groups
                if (null == group.RdbObjects)
                {
                    groupIndex++;
                    continue;
                }

                // Iterate objects in this group
                foreach (DFBlock.RdbObject obj in group.RdbObjects)
                {
                    // Add models
                    if (obj.Type == DFBlock.RdbResourceTypes.Model)
                    {
                        // Get model reference index and id
                        int  modelReference = obj.Resources.ModelResource.ModelIndex;
                        uint modelId        = blockData.RdbBlock.ModelReferenceList[modelReference].ModelIdNum;

                        // Filter exit door models where flag not set
                        if (modelId == exitDoorModelID && !allowExitDoors)
                        {
                            continue;
                        }

                        // Filter action door models
                        // These must be added by AddActionDoors()
                        if (IsActionDoor(ref blockData, obj, modelReference))
                        {
                            continue;
                        }

                        // Get matrix
                        Matrix4x4 modelMatrix = GetModelMatrix(obj);

                        // Get model data
                        ModelData modelData;
                        dfUnity.MeshReader.GetModelData(modelId, out modelData);

                        // Add to static doors
                        exitDoorsOut.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, blockData.Index, 0, modelMatrix));

                        // Check if model has an action record
                        bool hasAction = HasAction(obj);

                        // Special handling for tapestries and banners
                        // Some of these are so far out from wall player can become stuck behind them
                        // Adding model invidually without collider to avoid problem
                        // Not sure if these object ever actions, but bypass this hack if they do
                        if (modelId >= minTapestryID && modelId <= maxTapestryID && !hasAction)
                        {
                            AddStandaloneModel(dfUnity, ref modelData, modelMatrix, modelsParent, hasAction, true);
                            continue;
                        }

                        // Add or combine
                        GameObject standaloneObject = null;
                        Transform  parent           = (hasAction) ? actionModelsParent : modelsParent;
                        if (combiner == null || hasAction)
                        {
                            standaloneObject = AddStandaloneModel(dfUnity, ref modelData, modelMatrix, parent, hasAction);
                            standaloneObject.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);
                        }
                        else
                        {
                            combiner.Add(ref modelData, modelMatrix);
                        }

                        // Add action
                        if (hasAction && standaloneObject != null)
                        {
                            AddAction(standaloneObject, blockData, obj, modelReference, groupIndex, actionLinkDict);
                        }
                    }
                }

                // Increment group index
                groupIndex++;
            }

            // Link action nodes
            LinkActionNodes(actionLinkDict);
        }
Пример #17
0
        /// <summary>
        /// Instantiate base RDB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <param name="textureTable">Optional texture table for dungeon.</param>
        /// <param name="allowExitDoors">Add exit doors to block.</param>
        /// <param name="cloneFrom">Clone and build on a prefab object template.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(
            ref DFBlock blockData,
            int[] textureTable           = null,
            bool allowExitDoors          = true,
            DaggerfallRDBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Use default texture table if one not specified
            if (textureTable == null)
            {
                textureTable = StaticTextureTables.DefaultTextureTable;
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent <DaggerfallRDBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRDB)
            {
                combiner = new ModelCombiner();
            }

            // Add parent node
            GameObject modelsNode       = new GameObject("Models");
            GameObject actionModelsNode = new GameObject("Action Models");

            modelsNode.transform.parent       = go.transform;
            actionModelsNode.transform.parent = go.transform;

            // Add models
            List <StaticDoor> exitDoors;

            AddModels(
                dfUnity,
                ref blockData,
                textureTable,
                allowExitDoors,
                out exitDoors,
                combiner,
                modelsNode.transform,
                actionModelsNode.transform);

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObject cgo = GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                    cgo.GetComponent <DaggerfallMesh>().SetDungeonTextures(textureTable);
                }
            }

            // Add exit doors
            if (exitDoors.Count > 0)
            {
                DaggerfallStaticDoors c = go.AddComponent <DaggerfallStaticDoors>();
                c.Doors = exitDoors.ToArray();
            }

            return(go);
        }
        /// <summary>
        /// Adds another ModelCombiner to this one.
        /// </summary>
        /// <param name="other">Other ModelCombiner.</param>
        /// <param name="matrix">Transform to apply</param>
        public void Add(ModelCombiner other, Matrix4x4 matrix)
        {
            // Do nothing if sealed
            if (isSealed || other.isSealed)
                return;

            // Add other items to this builder
            foreach (var item in other.builderDictionary)
            {
                BatchData batchData = item.Value;
                AddData(item.Key, ref batchData, matrix);
            }
        }
Пример #19
0
        /// <summary>
        /// Instantiate base RMB block by DFBlock data.
        /// </summary>
        /// <param name="blockData">Block data.</param>
        /// <returns>Block GameObject.</returns>
        public static GameObject CreateBaseGameObject(ref DFBlock blockData, DaggerfallRMBBlock cloneFrom = null)
        {
            DaggerfallUnity dfUnity = DaggerfallUnity.Instance;

            if (!dfUnity.IsReady)
            {
                return(null);
            }

            // Create gameobject
            GameObject go;
            string     name = string.Format("DaggerfallBlock [{0}]", blockData.Name);

            if (cloneFrom != null)
            {
                go = GameObjectHelper.InstantiatePrefab(cloneFrom.gameObject, name, null, Vector3.zero);
            }
            else
            {
                go = new GameObject(name);
                go.AddComponent <DaggerfallRMBBlock>();
            }

            // Setup combiner
            ModelCombiner combiner = null;

            if (dfUnity.Option_CombineRMB)
            {
                combiner = new ModelCombiner();
            }

            // Lists to receive any doors found in this block
            List <StaticDoor> modelDoors;
            List <StaticDoor> propDoors;

            // Add models and static props
            GameObject modelsNode = new GameObject("Models");

            modelsNode.transform.parent = go.transform;
            AddModels(dfUnity, ref blockData, out modelDoors, combiner, modelsNode.transform);
            AddProps(dfUnity, ref blockData, out propDoors, combiner, modelsNode.transform);

            // Add doors
            List <StaticDoor> allDoors = new List <StaticDoor>();

            if (modelDoors.Count > 0)
            {
                allDoors.AddRange(modelDoors);
            }
            if (propDoors.Count > 0)
            {
                allDoors.AddRange(propDoors);
            }
            if (allDoors.Count > 0)
            {
                AddStaticDoors(allDoors.ToArray(), go);
            }

            // Apply combiner
            if (combiner != null)
            {
                if (combiner.VertexCount > 0)
                {
                    combiner.Apply();
                    GameObjectHelper.CreateCombinedMeshGameObject(
                        combiner,
                        "CombinedModels",
                        modelsNode.transform,
                        dfUnity.Option_SetStaticFlags);
                }
            }

            return(go);
        }
Пример #20
0
        /// <summary>
        /// Gets Unity Mesh from previously combined model data.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleon for loading content.</param>
        /// <param name="combiner">ModelCombiner to build from.</param>
        /// <param name="cachedMaterialsOut">Array of cached materials in order of submesh.</param>
        /// <param name="textureKeysOut">Array of original texture keys in order of submesh.</param>
        /// <param name="hasAnimationsOut">True if one or more materials have animations.</param>
        /// <param name="solveTangents">Solve tangents for this mesh.</param>
        /// <param name="lightmapUVs">Add secondary lightmap UVs to this mesh.</param>
        /// <returns>Mesh object or null.</returns>
        public Mesh GetCombinedMesh(
            DaggerfallUnity dfUnity,
            ModelCombiner combiner,
            out CachedMaterial[] cachedMaterialsOut,
            out int[] textureKeysOut,
            out bool hasAnimationsOut,
            bool solveTangents = false,
            bool lightmapUVs = false)
        {
            cachedMaterialsOut = null;
            hasAnimationsOut = false;
            textureKeysOut = null;

            // Ready check
            if (!IsReady)
                return null;

            // Get combined model
            ModelCombiner.CombinedModel combinedModel;
            if (!combiner.GetCombinedModel(out combinedModel))
                return null;

            // Load materials
            cachedMaterialsOut = new CachedMaterial[combinedModel.SubMeshes.Length];
            textureKeysOut = new int[combinedModel.SubMeshes.Length];
            for (int i = 0; i < combinedModel.SubMeshes.Length; i++)
            {
                int archive = combinedModel.SubMeshes[i].TextureArchive;
                int record = combinedModel.SubMeshes[i].TextureRecord;
                textureKeysOut[i] = MaterialReader.MakeTextureKey((short)archive, (byte)record, (byte)0);

                // Add material to array
                CachedMaterial cachedMaterial;
                dfUnity.MaterialReader.GetCachedMaterial(archive, record, 0, out cachedMaterial);
                cachedMaterialsOut[i] = cachedMaterial;

                // Set animation flag
                if (cachedMaterial.singleFrameCount > 1 && !hasAnimationsOut)
                    hasAnimationsOut = true;
            }

            // Create mesh
            Mesh mesh = new Mesh();
            mesh.name = "CombinedMesh";
            mesh.vertices = combinedModel.Vertices;
            mesh.normals = combinedModel.Normals;
            mesh.uv = combinedModel.UVs;
            mesh.subMeshCount = combinedModel.SubMeshes.Length;

            // Set submesh triangles
            for (int s = 0; s < mesh.subMeshCount; s++)
            {
                var sub = combinedModel.SubMeshes[s];
                int[] triangles = new int[sub.PrimitiveCount * 3];
                for (int t = 0; t < sub.PrimitiveCount * 3; t++)
                {
                    triangles[t] = combinedModel.Indices[sub.StartIndex + t];
                }
                mesh.SetTriangles(triangles, s);
            }

            // Finalise mesh
            if (solveTangents) TangentSolver(mesh);
            if (lightmapUVs) AddLightmapUVs(mesh);
            mesh.RecalculateBounds();
            mesh.Optimize();

            return mesh;
        }