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); } } }
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++; } }
/// <summary> /// Add interior models. /// </summary> private void AddModels(PlayerGPS.DiscoveredBuilding buildingData, bool isAutomapRun = false) { List <StaticDoor> doors = new List <StaticDoor>(); GameObject node = new GameObject("Models"); GameObject doorsNode = new GameObject("Doors"); node.transform.parent = this.transform; doorsNode.transform.parent = this.transform; // Iterate through models in this subrecord combiner.NewCombiner(); foreach (DFBlock.RmbBlock3dObjectRecord obj in recordData.Interior.Block3dObjectRecords) { bool stopCombine = false; // Filter out bad interior models if (IsBadInteriorModel(obj.ModelIdNum)) { continue; } // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData); // Get model position by type (3 seems to indicate props/clutter) // Also stop these from being combined as some may carry a loot container Vector3 modelPosition; if (obj.ObjectType == propModelType) { // Props axis needs to be transformed to lowest Y point Vector3 bottom = modelData.Vertices[0]; for (int i = 0; i < modelData.Vertices.Length; i++) { if (modelData.Vertices[i].y < bottom.y) { bottom = modelData.Vertices[i]; } } modelPosition = new Vector3(obj.XPos, obj.YPos, obj.ZPos) * MeshReader.GlobalScale; modelPosition += new Vector3(0, -bottom.y, 0); stopCombine = true; } else { modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; } // Stop special objects or those with actions from being combined if (obj.ModelIdNum == ladderModelId || PlayerActivate.HasCustomActivation(obj.ModelIdNum)) { stopCombine = true; } // Get model transform Vector3 modelRotation = new Vector3(-obj.XRotation / BlocksFile.RotationDivisor, -obj.YRotation / BlocksFile.RotationDivisor, -obj.ZRotation / BlocksFile.RotationDivisor); Vector3 modelScale = RMBLayout.GetModelScaleVector(obj); Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), modelScale); // Does this model have doors? if (modelData.Doors != null) { doors.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, entryDoor.blockIndex, entryDoor.recordIndex, modelMatrix)); } // Inject custom GameObject if available GameObject modelGO = MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, node.transform, modelMatrix); // Otherwise use Daggerfall mesh - combine or add if (!modelGO) { if (dfUnity.Option_CombineRMB && !stopCombine) { combiner.Add(ref modelData, modelMatrix); } else { // Add individual GameObject modelGO = GameObjectHelper.CreateDaggerfallMeshGameObject(obj.ModelIdNum, node.transform, dfUnity.Option_SetStaticFlags); modelGO.transform.position = modelMatrix.GetColumn(3); modelGO.transform.rotation = modelMatrix.rotation; modelGO.transform.localScale = modelMatrix.lossyScale; // Update climate DaggerfallMesh dfMesh = modelGO.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } if ((modelGO != null) && (isAutomapRun)) { modelGO.AddComponent <AutomapModel>(); } // Make ladder collider convex and ladder functionality, if set up as propModelType if (obj.ModelIdNum == ladderModelId && obj.ObjectType == propModelType) { var meshCollider = modelGO.GetComponent <MeshCollider>(); if (meshCollider) { meshCollider.convex = true; } modelGO.AddComponent <DaggerfallLadder>(); } // Optionally add action objects to specific furniture items (e.g. loot containers), except when laying out map (buildingType=AllValid) if (obj.ObjectType == propModelType && buildingData.buildingType != DFLocation.BuildingTypes.AllValid) { AddFurnitureAction(obj, modelGO, buildingData); } } // Add combined GameObject if (dfUnity.Option_CombineRMB) { if (combiner.VertexCount > 0) { combiner.Apply(); GameObject modelGO = GameObjectHelper.CreateCombinedMeshGameObject(combiner, "CombinedModels", node.transform, dfUnity.Option_SetStaticFlags); if ((modelGO != null) && (isAutomapRun)) { modelGO.AddComponent <AutomapModel>(); } // Update climate DaggerfallMesh dfMesh = modelGO.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } // Add static doors component DaggerfallStaticDoors c = this.gameObject.AddComponent <DaggerfallStaticDoors>(); c.Doors = doors.ToArray(); }