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 PlaceWagon(bool fromSave = false) { if (fromSave == false) { WagonMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; if (!transportManager.HasHorse()) { SetWagonPositionAndRotation(true); DaggerfallUI.MessageBox("You have no horse to pull your wagon."); ItemCollection playerItems = GameManager.Instance.PlayerEntity.Items; for (int i = 0; i < playerItems.Count; i++) { DaggerfallUnityItem item = playerItems.GetItem(i); if (item != null && item.IsOfTemplate(ItemGroups.Transportation, (int)Transportation.Small_cart)) { playerItems.RemoveItem(item); } } } else { SetWagonPositionAndRotation(); } } else { PlaceWagonOnGround(); } Wagon = MeshReplacement.ImportCustomGameobject(wagonModelID, null, WagonMatrix); if (Wagon == null) { Wagon = GameObjectHelper.CreateDaggerfallMeshGameObject(wagonModelID, null); } Wagon.transform.SetPositionAndRotation(WagonPosition, WagonRotation); if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon) { Wagon.SetActive(false); } else { Wagon.SetActive(true); } WagonDeployed = true; }
private static void DeployTent(bool fromSave = false) { if (fromSave == false) { TentMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; SetTentPositionAndRotation(); } //Attempt to load a model replacement Tent = MeshReplacement.ImportCustomGameobject(tentModelID, null, TentMatrix); if (Tent == null) { Tent = GameObjectHelper.CreateDaggerfallMeshGameObject(tentModelID, null); } //Set the model's position in the world Tent.transform.SetPositionAndRotation(TentPosition, TentRotation); Tent.SetActive(true); TentDeployed = true; }
public static void DeployTent(bool fromSave = false) { if (fromSave == false) { CampMapPixel = GameManager.Instance.PlayerGPS.CurrentMapPixel; SetTentPositionAndRotation(); DaggerfallUI.MessageBox("You set up camp"); } else { PlaceTentOnGround(); } //Attempt to load a model replacement Tent = MeshReplacement.ImportCustomGameobject(tentModelID, null, TentMatrix); Fire = GameObjectHelper.CreateDaggerfallBillboardGameObject(210, 1, null); if (Tent == null) { Tent = GameObjectHelper.CreateDaggerfallMeshGameObject(tentModelID, null); } //Set the model's position in the world Tent.transform.SetPositionAndRotation(TentPosition, TentRotation); if (GameManager.Instance.PlayerEnterExit.IsPlayerInsideDungeon) { FirePosition = Tent.transform.position + (Tent.transform.up * 0.8f); Tent.SetActive(false); } else { FirePosition = Tent.transform.position + (Tent.transform.forward * 3) + (Tent.transform.up * 0.8f); Tent.SetActive(true); } Fire.transform.SetPositionAndRotation(FirePosition, TentRotation); Fire.SetActive(true); AddTorchAudioSource(Fire); GameObject lightsNode = new GameObject("Lights"); lightsNode.transform.parent = Fire.transform; AddLight(DaggerfallUnity.Instance, Fire, lightsNode.transform); CampDeployed = true; FireLit = true; }
private void Display3dModelSelection(int selectedIdx) { if (goModel) { Object.Destroy(goModel); goModel = null; } // Position camera and set model id uint modelId = 0; if (housesForSale == null) { camera.transform.position = new Vector3(0, 12, DaggerfallBankManager.GetShipCameraDist((ShipType)selectedIdx)); modelId = DaggerfallBankManager.GetShipModelId((ShipType)selectedIdx); } else { camera.transform.position = new Vector3(0, 3, -20); BuildingSummary house = housesForSale[selectedIdx]; modelId = house.ModelID; } // Inject custom GameObject if available else create standard mesh game object for the model goModel = MeshReplacement.ImportCustomGameobject(modelId, goBankPurchase.transform, new Matrix4x4()); if (goModel == null) { goModel = GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, goBankPurchase.transform); } goModel.layer = layer; // Apply current climate ClimateBases climateBase = ClimateSwaps.FromAPIClimateBase(GameManager.Instance.PlayerGPS.ClimateSettings.ClimateType); ClimateSeason season = (DaggerfallUnity.WorldTime.Now.SeasonValue == DaggerfallDateTime.Seasons.Winter) ? ClimateSeason.Winter : ClimateSeason.Summer; DaggerfallMesh dfMesh = goModel.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, season, WindowStyle.Day); }
public static GameObject Add3dObject(DFBlock.RdbObject obj, ref DFBlock.RdbModelReference[] modelReferenceList) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Get model reference index and id int modelReference = obj.Resources.ModelResource.ModelIndex; uint modelId = modelReferenceList[modelReference].ModelIdNum; // Get matrix Vector3 modelRotation = new Vector3(-obj.Resources.ModelResource.XRotation / BlocksFile.RotationDivisor, -obj.Resources.ModelResource.YRotation / BlocksFile.RotationDivisor, -obj.Resources.ModelResource.ZRotation / BlocksFile.RotationDivisor); Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(modelId, out modelData); // Get GameObject GameObject modelGO = MeshReplacement.ImportCustomGameobject(modelId, null, modelMatrix, false); if (modelGO == null) { if (modelData.DFMesh.TotalVertices != 0) { modelGO = GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, null); modelGO.transform.position = modelMatrix.GetColumn(3); modelGO.transform.rotation = modelMatrix.rotation; modelGO.transform.localScale = modelMatrix.lossyScale; } else { Debug.LogError("Custom model not found for modelId " + modelId); } } return(modelGO); }
/// <summary> /// Add interior models. /// </summary> private void AddModels(PlayerGPS.DiscoveredBuilding buildingData) { 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; // 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 object from being combined if (obj.ModelIdNum == ladderModelId) { stopCombine = true; } // Get model transform Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // 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 go = MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, node.transform, modelMatrix); // Otherwise use Daggerfall mesh - combine or add if (!go) { if (dfUnity.Option_CombineRMB && !stopCombine) { combiner.Add(ref modelData, modelMatrix); } else { // Add individual GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(obj.ModelIdNum, node.transform, dfUnity.Option_SetStaticFlags); go.transform.position = modelMatrix.GetColumn(3); go.transform.rotation = GameObjectHelper.QuaternionFromMatrix(modelMatrix); // Update climate DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } // Make ladder collider convex if (obj.ModelIdNum == ladderModelId) { var meshCollider = go.GetComponent <MeshCollider>(); if (meshCollider) { meshCollider.convex = true; } go.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, go, buildingData); } } // Add combined GameObject if (dfUnity.Option_CombineRMB) { if (combiner.VertexCount > 0) { combiner.Apply(); GameObject go = GameObjectHelper.CreateCombinedMeshGameObject(combiner, "CombinedModels", node.transform, dfUnity.Option_SetStaticFlags); // Update climate DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } // Add static doors component DaggerfallStaticDoors c = this.gameObject.AddComponent <DaggerfallStaticDoors>(); c.Doors = doors.ToArray(); }
/// <summary> /// Add action doors to parent transform. /// </summary> private void AddActionDoors() { // Using 9000-9005 here but identical door models are also found at 900x, 910x, through to 980x // They seem to be duplicate models but can have different model origins so not all ranges are suitable const int doorModelBaseId = 9000; GameObject actionDoorsNode = new GameObject("Action Doors"); actionDoorsNode.transform.parent = this.transform; foreach (DFBlock.RmbBlockDoorRecord obj in recordData.Interior.BlockDoorRecords) { // Create unique LoadID for save sytem ulong loadID = (ulong)(blockData.Position + obj.Position); // Get model transform Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Vector3 modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; // Instantiate door prefab and add model - DoorModelIndex is modulo to known-good range just in case // A custom prefab can be provided by mods and must include DaggerfallActionDoor component with all requirements. uint modelId = (uint)(doorModelBaseId + obj.DoorModelIndex % 5); GameObject go = MeshReplacement.ImportCustomGameobject(modelId, actionDoorsNode.transform, Matrix4x4.identity); if (!go) { go = GameObjectHelper.InstantiatePrefab(dfUnity.Option_InteriorDoorPrefab.gameObject, string.Empty, actionDoorsNode.transform, Vector3.zero); GameObjectHelper.CreateDaggerfallMeshGameObject(modelId, actionDoorsNode.transform, false, go, true); // Resize box collider to new mesh bounds BoxCollider boxCollider = go.GetComponent <BoxCollider>(); MeshRenderer meshRenderer = go.GetComponent <MeshRenderer>(); if (boxCollider != null && meshRenderer != null) { boxCollider.center = meshRenderer.bounds.center; boxCollider.size = meshRenderer.bounds.size; } // Update climate DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } // Apply transforms go.transform.rotation = Quaternion.Euler(modelRotation); go.transform.position = modelPosition; // Get action door script DaggerfallActionDoor actionDoor = go.GetComponent <DaggerfallActionDoor>(); // Assign loadID if (actionDoor) { actionDoor.LoadID = loadID; } if (SaveLoadManager.Instance != null) { go.AddComponent <SerializableActionDoor>(); } } }
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++; } }
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++; } }
/// <summary> /// Add interior models. /// </summary> private void AddModels() { 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) { // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(obj.ModelIdNum, out modelData); // Get model position by type (3 seems to indicate props/clutter) Vector3 modelPosition; if (obj.ObjectType == 3) { // 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); } else { modelPosition = new Vector3(obj.XPos, -obj.YPos, obj.ZPos) * MeshReader.GlobalScale; } // Get model transform Vector3 modelRotation = new Vector3(0, -obj.YRotation / BlocksFile.RotationDivisor, 0); Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), Vector3.one); // Does this model have doors? if (modelData.Doors != null) { doors.AddRange(GameObjectHelper.GetStaticDoors(ref modelData, entryDoor.blockIndex, entryDoor.recordIndex, modelMatrix)); } // Get GameObject if (MeshReplacement.ImportCustomGameobject(obj.ModelIdNum, node.transform, modelMatrix) == null) { // Use Daggerfall Mesh: Combine or add if (dfUnity.Option_CombineRMB) { combiner.Add(ref modelData, modelMatrix); } else { // Add GameObject GameObject go = GameObjectHelper.CreateDaggerfallMeshGameObject(obj.ModelIdNum, node.transform, dfUnity.Option_SetStaticFlags); go.transform.position = modelMatrix.GetColumn(3); go.transform.rotation = GameObjectHelper.QuaternionFromMatrix(modelMatrix); // Update climate DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } } // Add combined GameObject if (dfUnity.Option_CombineRMB) { if (combiner.VertexCount > 0) { combiner.Apply(); GameObject go = GameObjectHelper.CreateCombinedMeshGameObject(combiner, "CombinedModels", node.transform, dfUnity.Option_SetStaticFlags); // Update climate DaggerfallMesh dfMesh = go.GetComponent <DaggerfallMesh>(); dfMesh.SetClimate(climateBase, climateSeason, WindowStyle.Disabled); } } // Add static doors component DaggerfallStaticDoors c = this.gameObject.AddComponent <DaggerfallStaticDoors>(); c.Doors = doors.ToArray(); }
public static GameObject CreatePlacedObject(PlacedObjectData_v2 data, Transform parent, bool previewGo = false) { // Custom models like Handpainted Models have insanley different scales (< 0.0 to 200+) Set all models as a child to a parent, so // EditMode can uniformly scale properly. GameObject parentGo = new GameObject(); GameObject childGo; parentGo.transform.parent = parent; if (data.modelID == 0) { childGo = MeshReplacement.ImportCustomFlatGameobject(data.archive, data.record, Vector3.zero, parentGo.transform); if (childGo == null) { childGo = GameObjectHelper.CreateDaggerfallBillboardGameObject(data.archive, data.record, parentGo.transform); } } else { Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one); childGo = MeshReplacement.ImportCustomGameobject(data.modelID, parentGo.transform, matrix); if (childGo == null) { childGo = GameObjectHelper.CreateDaggerfallMeshGameObject(data.modelID, parentGo.transform); } } parentGo.transform.eulerAngles = Vector3.zero; childGo.transform.eulerAngles = Vector3.zero; if (previewGo) { data.isLight = true; } BoxCollider parentCollider = parentGo.AddComponent <BoxCollider>(); BoxCollider childCollider; //Expanding collider a little gives better hit detection. float buffer = 0.02f; // Some custom models have a box collider and are made of multiple smaller models. Get the parent collider size. if (childCollider = childGo.GetComponent <BoxCollider>()) { parentCollider.size = new Vector3((childCollider.size.x * childGo.transform.localScale.x) + buffer, (childCollider.size.y * childGo.transform.localScale.y) + buffer, (childCollider.size.z * childGo.transform.localScale.z) + buffer); parentCollider.center = new Vector3(childCollider.center.x * childGo.transform.localScale.x, childCollider.center.y * childGo.transform.localScale.y, childCollider.center.z * childGo.transform.localScale.z); // Child colliders screw with EditMode. GameObject.Destroy(childCollider); } else { Bounds childBounds = childGo.GetComponent <MeshFilter>().sharedMesh.bounds; parentCollider.size = new Vector3((childBounds.size.x * childGo.transform.localScale.x) + buffer, (childBounds.size.y * childGo.transform.localScale.y) + buffer, (childBounds.size.z * childGo.transform.localScale.z) + buffer); parentCollider.center = new Vector3(childBounds.center.x * childGo.transform.localScale.x, childBounds.center.y * childGo.transform.localScale.y, childBounds.center.z * childGo.transform.localScale.z); } parentCollider.isTrigger = true; parentGo.AddComponent <PlacedObject>(); SetPlacedObject(data, parentGo); return(parentGo); }
public static GameObject Add3dObject(DFBlock.RmbBlock3dObjectRecord rmbBlock) { DaggerfallUnity dfUnity = DaggerfallUnity.Instance; // Get model data ModelData modelData; dfUnity.MeshReader.GetModelData(rmbBlock.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 (rmbBlock.ObjectType == (int)InteractiveObject) { // 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(rmbBlock.XPos, rmbBlock.YPos, rmbBlock.ZPos) * MeshReader.GlobalScale; modelPosition += new Vector3(0, -bottom.y, 0); } else { modelPosition = new Vector3(rmbBlock.XPos, -rmbBlock.YPos, rmbBlock.ZPos) * MeshReader.GlobalScale; } // Fix 3D models with 0,0,0 scale if (rmbBlock.XScale == 0) { rmbBlock.XScale = 1; } if (rmbBlock.YScale == 0) { rmbBlock.YScale = 1; } if (rmbBlock.ZScale == 0) { rmbBlock.ZScale = 1; } // Get model transform Vector3 modelRotation = new Vector3(-rmbBlock.XRotation / BlocksFile.RotationDivisor, -rmbBlock.YRotation / BlocksFile.RotationDivisor, -rmbBlock.ZRotation / BlocksFile.RotationDivisor); Vector3 modelScale = new Vector3(rmbBlock.XScale, rmbBlock.YScale, rmbBlock.ZScale); Matrix4x4 modelMatrix = Matrix4x4.TRS(modelPosition, Quaternion.Euler(modelRotation), modelScale); // Inject custom GameObject if available GameObject modelGO = MeshReplacement.ImportCustomGameobject(rmbBlock.ModelIdNum, null, modelMatrix); if (modelGO == null) { if (modelData.DFMesh.TotalVertices != 0) { modelGO = DaggerfallWorkshop.Utility.GameObjectHelper.CreateDaggerfallMeshGameObject(rmbBlock.ModelIdNum, null); modelGO.transform.position = modelMatrix.GetColumn(3); modelGO.transform.rotation = modelMatrix.rotation; modelGO.transform.localScale = modelMatrix.lossyScale; } else { Debug.LogError("Custom model not found for modelId " + rmbBlock.ModelIdNum); } } return(modelGO); }