public static Quaternion ToQuaternion(this Vector3 v) { Matrix m = Matrix.Identity * Matrix.RotationX(v.x) * Matrix.RotationY(v.y) * Matrix.RotationZ(v.z); SharpDX.Quaternion dxQuat = SharpDX.Quaternion.RotationMatrix(m); return(new Quaternion(dxQuat.X, dxQuat.Y, dxQuat.Z, dxQuat.W)); }
/// <summary> /// Occurs second in the ward data output flow and reads all housing territories for their appropriate /// plot placeholders and calculates plot locations from them.<br /> /// /// This <i>would</i> be read from HousingMapMarkerInfo but the height values are incorrect there, /// and would mess up camera movement. X coordinates are negated due to the map reflection in Unity.<br /> /// /// This method takes a very long time due to Territory instantiation. /// </summary> private static void ReadTerritoryPlots(ARealmReversed realm, ref List <Plot> plots) { List <TerritoryType> housingTeriTypes = GetHousingTerritoryTypes(realm); WardSetting[] settings = JsonConvert.DeserializeObject <WardSetting[]>(File.ReadAllText(FFXIVHSPaths.GetWardSettingsJson())); foreach (TerritoryType tType in housingTeriTypes) { SaintCoinach.Graphics.Territory t = new SaintCoinach.Graphics.Territory(tType); LgbFile bg = null; //Get the ward's information from the wardsettings.json string groupName = "", plotName = "", subdivisionName = ""; foreach (WardSetting ws in settings) { if (ws.Territory.ToString() == t.Name.ToUpper()) { plotName = ws.plotName; groupName = ws.group; subdivisionName = ws.subdivisionSuffix + groupName; } } //We only care about bg.lgb for this territory foreach (LgbFile lgbFile in t.LgbFiles) { if (lgbFile.File.Path.EndsWith("bg.lgb")) { bg = lgbFile; } } if (bg != null) { //Define main and subdiv groups var mainGroup = bg.Groups .Where(_ => _.Name == groupName) .Select(_ => _); var subDivGroup = bg.Groups .Where(_ => _.Name == subdivisionName) .Select(_ => _); //Get main and subdiv plot lists and sort by index var mainPlotList = plots.Where(_ => _.ward.ToString() == t.Name.ToUpper()) .Where(_ => _.subdiv == false) .Select(_ => _).ToList(); var subdivPlotList = plots.Where(_ => _.ward.ToString() == t.Name.ToUpper()) .Where(_ => _.subdiv == true) .Select(_ => _).ToList(); mainPlotList.Sort((p1, p2) => p1.index.CompareTo(p2.index)); subdivPlotList.Sort((p1, p2) => p1.index.CompareTo(p2.index)); int plotIndex = 0; foreach (var lgbGroup in mainGroup.ToArray()) { foreach (var lgbGimmickEntry in lgbGroup.Entries.OfType <LgbGimmickEntry>()) { foreach (var sgbGroup in lgbGimmickEntry.Gimmick.Data.OfType <SgbGroup>()) { foreach (var modelEntry in sgbGroup.Entries.OfType <SgbModelEntry>()) { if (modelEntry.Model.Model.File.Path.Contains(plotName)) { //Position is in gimmick header, not transformedmodel SaintCoinach.Graphics.Vector3 position = lgbGimmickEntry.Header.Translation; SaintCoinach.Graphics.Vector3 rotation = lgbGimmickEntry.Header.Rotation; Vector3 pos = new Vector3(position.X * -1, position.Y, position.Z); Quaternion rot = new Vector3(rotation.X, rotation.Y, rotation.Z).ToQuaternion(); mainPlotList[plotIndex].position = pos; mainPlotList[plotIndex].rotation = rot; plotIndex++; } } } } } plotIndex = 0; foreach (var lgbGroup in subDivGroup.ToArray()) { foreach (var lgbGimmickEntry in lgbGroup.Entries.OfType <LgbGimmickEntry>()) { foreach (var sgbGroup in lgbGimmickEntry.Gimmick.Data.OfType <SgbGroup>()) { foreach (var modelEntry in sgbGroup.Entries.OfType <SgbModelEntry>()) { if (modelEntry.Model.Model.File.Path.Contains(plotName)) { //Position is in gimmick header, not transformedmodel SaintCoinach.Graphics.Vector3 position = lgbGimmickEntry.Header.Translation; SaintCoinach.Graphics.Vector3 rotation = lgbGimmickEntry.Header.Rotation; Vector3 pos = new Vector3(position.X * -1, position.Y, position.Z); Quaternion rot = new Vector3(rotation.X, rotation.Y, rotation.Z).ToQuaternion(); subdivPlotList[plotIndex].position = pos; subdivPlotList[plotIndex].rotation = rot; plotIndex++; } } } } } } } }