mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
DebugRaycaster now reports a plane perpendicular to its normal and rotated so that the plane's positive y is as close to 'up' relative to the planet as possible
This commit is contained in:
parent
33737482bd
commit
c1a7750ad5
@ -19,14 +19,21 @@ namespace NewHorizons.Utility.DebugMenu
|
|||||||
|
|
||||||
class DebugMenuNomaiText : DebugSubmenu
|
class DebugMenuNomaiText : DebugSubmenu
|
||||||
{
|
{
|
||||||
private Vector2 recentPropsScrollPosition = Vector2.zero;
|
|
||||||
private HashSet<string> favoriteProps = new HashSet<string>();
|
|
||||||
public static readonly char separatorCharacter = '☧'; // since no chars are illegal in game object names, I picked one that's extremely unlikely to be used to be a separator
|
|
||||||
private static readonly string favoritePropsPlayerPrefKey = "FavoriteProps";
|
|
||||||
|
|
||||||
internal DebugPropPlacer _dpp;
|
|
||||||
internal DebugRaycaster _drc;
|
internal DebugRaycaster _drc;
|
||||||
|
|
||||||
|
class NomaiTextTree
|
||||||
|
{
|
||||||
|
public GameObject text;
|
||||||
|
public int variation;
|
||||||
|
public float arcLengthLocationOnParent;
|
||||||
|
|
||||||
|
public List<NomaiTextTree> children = new List<NomaiTextTree>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NomaiTextTree> textTrees = new List<NomaiTextTree>();
|
||||||
|
NomaiTextTree currentTree;
|
||||||
|
|
||||||
|
|
||||||
internal override string SubmenuName()
|
internal override string SubmenuName()
|
||||||
{
|
{
|
||||||
return "Text Placer";
|
return "Text Placer";
|
||||||
@ -34,15 +41,12 @@ namespace NewHorizons.Utility.DebugMenu
|
|||||||
|
|
||||||
internal override void OnInit(DebugMenu menu)
|
internal override void OnInit(DebugMenu menu)
|
||||||
{
|
{
|
||||||
_dpp = menu.GetComponent<DebugPropPlacer>();
|
|
||||||
_drc = menu.GetComponent<DebugRaycaster>();
|
_drc = menu.GetComponent<DebugRaycaster>();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void OnAwake(DebugMenu menu)
|
internal override void OnAwake(DebugMenu menu)
|
||||||
{
|
{
|
||||||
_dpp = menu.GetComponent<DebugPropPlacer>();
|
|
||||||
_drc = menu.GetComponent<DebugRaycaster>();
|
_drc = menu.GetComponent<DebugRaycaster>();
|
||||||
LoadFavoriteProps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void OnBeginLoadMod(DebugMenu debugMenu)
|
internal override void OnBeginLoadMod(DebugMenu debugMenu)
|
||||||
@ -52,73 +56,26 @@ namespace NewHorizons.Utility.DebugMenu
|
|||||||
|
|
||||||
internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config)
|
internal override void LoadConfigFile(DebugMenu menu, PlanetConfig config)
|
||||||
{
|
{
|
||||||
_dpp.FindAndRegisterPropsFromConfig(config);
|
// TODO: populate textTrees
|
||||||
}
|
|
||||||
|
|
||||||
private void LoadFavoriteProps()
|
|
||||||
{
|
|
||||||
string favoritePropsPlayerPref = PlayerPrefs.GetString(favoritePropsPlayerPrefKey);
|
|
||||||
|
|
||||||
if (favoritePropsPlayerPref == null || favoritePropsPlayerPref == "") return;
|
|
||||||
|
|
||||||
var favoritePropPaths = favoritePropsPlayerPref.Split(separatorCharacter);
|
|
||||||
foreach (string favoriteProp in favoritePropPaths)
|
|
||||||
{
|
|
||||||
DebugPropPlacer.RecentlyPlacedProps.Add(favoriteProp);
|
|
||||||
this.favoriteProps.Add(favoriteProp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal override void OnGUI(DebugMenu menu)
|
internal override void OnGUI(DebugMenu menu)
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// DebugPropPlacer
|
|
||||||
//
|
|
||||||
GUILayout.Label("Currently placing: ");
|
|
||||||
_dpp.SetCurrentObject(GUILayout.TextArea(_dpp.currentObject));
|
|
||||||
|
|
||||||
GUILayout.Space(5);
|
GUILayout.Space(5);
|
||||||
|
|
||||||
// List of recently placed objects
|
|
||||||
GUILayout.Label("Recently placed objects");
|
|
||||||
recentPropsScrollPosition = GUILayout.BeginScrollView(recentPropsScrollPosition, GUILayout.Width(menu.EditorMenuSize.x), GUILayout.Height(500));
|
|
||||||
foreach (string propPath in DebugPropPlacer.RecentlyPlacedProps)
|
|
||||||
{
|
|
||||||
GUILayout.BeginHorizontal();
|
|
||||||
|
|
||||||
var propPathElements = propPath[propPath.Length-1] == '/'
|
|
||||||
? propPath.Substring(0, propPath.Length-1).Split('/')
|
|
||||||
: propPath.Split('/');
|
|
||||||
string propName = propPathElements[propPathElements.Length - 1];
|
|
||||||
|
|
||||||
string favoriteButtonIcon = favoriteProps.Contains(propPath) ? "★" : "☆";
|
|
||||||
if (GUILayout.Button(favoriteButtonIcon, GUILayout.ExpandWidth(false)))
|
|
||||||
{
|
|
||||||
if (favoriteProps.Contains(propPath))
|
|
||||||
{
|
|
||||||
favoriteProps.Remove(propPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
favoriteProps.Add(propPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] favoritePropsArray = favoriteProps.ToArray<string>();
|
|
||||||
PlayerPrefs.SetString(favoritePropsPlayerPrefKey, string.Join(separatorCharacter + "", favoritePropsArray));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button(propName))
|
|
||||||
{
|
|
||||||
_dpp.SetCurrentObject(propPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
GUILayout.EndHorizontal();
|
|
||||||
}
|
|
||||||
GUILayout.EndScrollView();
|
|
||||||
|
|
||||||
GUILayout.Space(5);
|
GUILayout.Space(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawSpiralControls(int indentationLevel, NomaiTextTree tree)
|
||||||
|
{
|
||||||
|
GUILayout.BeginHorizontal();
|
||||||
|
GUILayout.Space(5*indentationLevel);
|
||||||
|
|
||||||
|
GUILayout.EndHorizontal();
|
||||||
|
|
||||||
|
tree.children.ForEach(child => DrawSpiralControls(indentationLevel+1, child));
|
||||||
|
}
|
||||||
|
|
||||||
internal override void PreSave(DebugMenu menu)
|
internal override void PreSave(DebugMenu menu)
|
||||||
{
|
{
|
||||||
UpdateLoadedConfigsForRecentSystem(menu);
|
UpdateLoadedConfigsForRecentSystem(menu);
|
||||||
@ -126,46 +83,46 @@ namespace NewHorizons.Utility.DebugMenu
|
|||||||
|
|
||||||
private void UpdateLoadedConfigsForRecentSystem(DebugMenu menu)
|
private void UpdateLoadedConfigsForRecentSystem(DebugMenu menu)
|
||||||
{
|
{
|
||||||
var newDetails = _dpp.GetPropsConfigByBody();
|
//var newDetails = _dpp.GetPropsConfigByBody();
|
||||||
|
|
||||||
Logger.Log("Updating config files. New Details Counts by planet: " + string.Join(", ", newDetails.Keys.Select(x => x + $" ({newDetails[x].Length})")));
|
//Logger.Log("Updating config files. New Details Counts by planet: " + string.Join(", ", newDetails.Keys.Select(x => x + $" ({newDetails[x].Length})")));
|
||||||
|
|
||||||
Dictionary<string, string> planetToConfigPath = new Dictionary<string, string>();
|
//Dictionary<string, string> planetToConfigPath = new Dictionary<string, string>();
|
||||||
|
|
||||||
// Get all configs
|
//// Get all configs
|
||||||
foreach (var filePath in menu.loadedConfigFiles.Keys)
|
//foreach (var filePath in menu.loadedConfigFiles.Keys)
|
||||||
{
|
//{
|
||||||
Logger.Log("potentially updating copy of config at " + filePath);
|
// Logger.Log("potentially updating copy of config at " + filePath);
|
||||||
|
|
||||||
if (menu.loadedConfigFiles[filePath].starSystem != Main.Instance.CurrentStarSystem) return;
|
// if (menu.loadedConfigFiles[filePath].starSystem != Main.Instance.CurrentStarSystem) return;
|
||||||
if (menu.loadedConfigFiles[filePath].name == null || AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name) == null) { Logger.Log("Failed to update copy of config at " + filePath); continue; }
|
// if (menu.loadedConfigFiles[filePath].name == null || AstroObjectLocator.GetAstroObject(menu.loadedConfigFiles[filePath].name) == null) { Logger.Log("Failed to update copy of config at " + filePath); continue; }
|
||||||
|
|
||||||
var astroObjectName = DebugPropPlacer.GetAstroObjectName(menu.loadedConfigFiles[filePath].name);
|
// var astroObjectName = DebugPropPlacer.GetAstroObjectName(menu.loadedConfigFiles[filePath].name);
|
||||||
planetToConfigPath[astroObjectName] = filePath;
|
// planetToConfigPath[astroObjectName] = filePath;
|
||||||
|
|
||||||
if (!newDetails.ContainsKey(astroObjectName)) continue;
|
// if (!newDetails.ContainsKey(astroObjectName)) continue;
|
||||||
|
|
||||||
if (menu.loadedConfigFiles[filePath].Props == null) menu.loadedConfigFiles[filePath].Props = new External.Modules.PropModule();
|
// if (menu.loadedConfigFiles[filePath].Props == null) menu.loadedConfigFiles[filePath].Props = new External.Modules.PropModule();
|
||||||
menu.loadedConfigFiles[filePath].Props.details = newDetails[astroObjectName];
|
// menu.loadedConfigFiles[filePath].Props.details = newDetails[astroObjectName];
|
||||||
|
|
||||||
Logger.Log("successfully updated copy of config file for " + astroObjectName);
|
// Logger.Log("successfully updated copy of config file for " + astroObjectName);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// find all new planets that do not yet have config paths
|
//// find all new planets that do not yet have config paths
|
||||||
var planetsThatDoNotHaveConfigFiles = newDetails.Keys.Where(x => !planetToConfigPath.ContainsKey(x)).ToList();
|
//var planetsThatDoNotHaveConfigFiles = newDetails.Keys.Where(x => !planetToConfigPath.ContainsKey(x)).ToList();
|
||||||
foreach (var astroObjectName in planetsThatDoNotHaveConfigFiles)
|
//foreach (var astroObjectName in planetsThatDoNotHaveConfigFiles)
|
||||||
{
|
//{
|
||||||
Logger.Log("Fabricating new config file for " + astroObjectName);
|
// Logger.Log("Fabricating new config file for " + astroObjectName);
|
||||||
|
|
||||||
var filepath = "planets/" + Main.Instance.CurrentStarSystem + "/" + astroObjectName + ".json";
|
// var filepath = "planets/" + Main.Instance.CurrentStarSystem + "/" + astroObjectName + ".json";
|
||||||
PlanetConfig c = new PlanetConfig();
|
// PlanetConfig c = new PlanetConfig();
|
||||||
c.starSystem = Main.Instance.CurrentStarSystem;
|
// c.starSystem = Main.Instance.CurrentStarSystem;
|
||||||
c.name = astroObjectName;
|
// c.name = astroObjectName;
|
||||||
c.Props = new PropModule();
|
// c.Props = new PropModule();
|
||||||
c.Props.details = newDetails[astroObjectName];
|
// c.Props.details = newDetails[astroObjectName];
|
||||||
|
|
||||||
menu.loadedConfigFiles[filepath] = c;
|
// menu.loadedConfigFiles[filepath] = c;
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,9 +94,9 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
// TODO: implement sectors
|
// TODO: implement sectors
|
||||||
// if this hits a sector, store that sector and add a config file option for it
|
// if this hits a sector, store that sector and add a config file option for it
|
||||||
|
|
||||||
if (!data.hitObject.name.EndsWith("_Body"))
|
if (!data.hitBodyGameObject.name.EndsWith("_Body"))
|
||||||
{
|
{
|
||||||
Logger.Log("Cannot place object on non-body object: " + data.hitObject.name);
|
Logger.Log("Cannot place object on non-body object: " + data.hitBodyGameObject.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -106,7 +106,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
SetCurrentObject(DEFAULT_OBJECT);
|
SetCurrentObject(DEFAULT_OBJECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
GameObject prop = DetailBuilder.MakeDetail(data.hitObject, data.hitObject.GetComponentInChildren<Sector>(), currentObject, data.pos, data.norm, 1, false);
|
GameObject prop = DetailBuilder.MakeDetail(data.hitBodyGameObject, data.hitBodyGameObject.GetComponentInChildren<Sector>(), currentObject, data.pos, data.norm, 1, false);
|
||||||
PropPlacementData propData = RegisterProp_WithReturn(data.bodyName, prop);
|
PropPlacementData propData = RegisterProp_WithReturn(data.bodyName, prop);
|
||||||
|
|
||||||
// align with surface normal
|
// align with surface normal
|
||||||
@ -131,7 +131,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
Logger.Log($"Failed to place object {currentObject} on body ${data.hitObject} at location ${data.pos}.");
|
Logger.Log($"Failed to place object {currentObject} on body ${data.hitBodyGameObject} at location ${data.pos}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -12,9 +12,19 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
public bool hit;
|
public bool hit;
|
||||||
public Vector3 pos;
|
public Vector3 pos;
|
||||||
public Vector3 norm;
|
public Vector3 norm;
|
||||||
|
public Plane plane;
|
||||||
|
|
||||||
public string bodyName;
|
public string bodyName;
|
||||||
public string bodyPath;
|
public string bodyPath;
|
||||||
public GameObject hitObject;
|
public GameObject hitBodyGameObject;
|
||||||
|
public GameObject hitObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Plane
|
||||||
|
{
|
||||||
|
public Vector3 origin;
|
||||||
|
public Vector3 normal;
|
||||||
|
public Vector3 u; // the "+x" direction on the plane
|
||||||
|
public Vector3 v; // the "+y" direction on the plane
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.InputSystem;
|
using UnityEngine.InputSystem;
|
||||||
|
|
||||||
namespace NewHorizons.Utility.DebugUtilities
|
namespace NewHorizons.Utility.DebugUtilities
|
||||||
@ -9,7 +9,13 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
private OWRigidbody _rb;
|
private OWRigidbody _rb;
|
||||||
private GameObject _surfaceSphere;
|
private GameObject _surfaceSphere;
|
||||||
private GameObject _normalSphere1;
|
private GameObject _normalSphere1;
|
||||||
private GameObject _normalSphere2;
|
private GameObject _normalSphere2;
|
||||||
|
|
||||||
|
private GameObject _planeUpRightSphere;
|
||||||
|
private GameObject _planeUpLeftSphere;
|
||||||
|
private GameObject _planeDownRightSphere;
|
||||||
|
private GameObject _planeDownLeftSphere;
|
||||||
|
|
||||||
|
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
@ -35,19 +41,36 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
DebugRaycastData data = Raycast();
|
DebugRaycastData data = Raycast();
|
||||||
var posText = $"{{\"x\": {data.pos.x}, \"y\": {data.pos.y}, \"z\": {data.pos.z}}}";
|
var posText = $"{{\"x\": {data.pos.x}, \"y\": {data.pos.y}, \"z\": {data.pos.z}}}";
|
||||||
var normText = $"{{\"x\": {data.norm.x}, \"y\": {data.norm.y}, \"z\": {data.norm.z}}}";
|
var normText = $"{{\"x\": {data.norm.x}, \"y\": {data.norm.y}, \"z\": {data.norm.z}}}";
|
||||||
|
|
||||||
if(_surfaceSphere != null) GameObject.Destroy(_surfaceSphere);
|
if(_surfaceSphere != null) GameObject.Destroy(_surfaceSphere);
|
||||||
if(_normalSphere1 != null) GameObject.Destroy(_normalSphere1);
|
if(_normalSphere1 != null) GameObject.Destroy(_normalSphere1);
|
||||||
if(_normalSphere2 != null) GameObject.Destroy(_normalSphere2);
|
if(_normalSphere2 != null) GameObject.Destroy(_normalSphere2);
|
||||||
|
if(_planeUpRightSphere != null) GameObject.Destroy(_planeUpRightSphere );
|
||||||
|
if(_planeUpLeftSphere != null) GameObject.Destroy(_planeUpLeftSphere );
|
||||||
|
if(_planeDownLeftSphere != null) GameObject.Destroy(_planeDownLeftSphere );
|
||||||
|
if(_planeDownRightSphere != null) GameObject.Destroy(_planeDownRightSphere);
|
||||||
|
|
||||||
_surfaceSphere = AddDebugShape.AddSphere(data.hitObject, 0.1f, Color.green);
|
_surfaceSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, 0.1f, Color.green);
|
||||||
_normalSphere1 = AddDebugShape.AddSphere(data.hitObject, 0.01f, Color.red);
|
_normalSphere1 = AddDebugShape.AddSphere(data.hitBodyGameObject, 0.01f, Color.red);
|
||||||
_normalSphere2 = AddDebugShape.AddSphere(data.hitObject, 0.01f, Color.red);
|
_normalSphere2 = AddDebugShape.AddSphere(data.hitBodyGameObject, 0.01f, Color.red);
|
||||||
|
|
||||||
_surfaceSphere.transform.localPosition = data.pos;
|
_surfaceSphere.transform.localPosition = data.pos;
|
||||||
_normalSphere1.transform.localPosition = data.pos + data.norm * 0.5f;
|
_normalSphere1.transform.localPosition = data.pos + data.norm * 0.5f;
|
||||||
_normalSphere2.transform.localPosition = data.pos + data.norm;
|
_normalSphere2.transform.localPosition = data.pos + data.norm;
|
||||||
|
|
||||||
|
// plane corners
|
||||||
|
var planeSize = 0.5f;
|
||||||
|
var planePointSize = 0.05f;
|
||||||
|
_planeUpRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.green);
|
||||||
|
_planeUpLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan) ;
|
||||||
|
_planeDownLeftSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.blue) ;
|
||||||
|
_planeDownRightSphere = AddDebugShape.AddSphere(data.hitBodyGameObject, planePointSize, Color.cyan) ;
|
||||||
|
|
||||||
|
_planeUpRightSphere .transform.localPosition = data.plane.origin + data.plane.u*1*planeSize + data.plane.v*1*planeSize;
|
||||||
|
_planeUpLeftSphere .transform.localPosition = data.plane.origin + data.plane.u*-1*planeSize + data.plane.v*1*planeSize;
|
||||||
|
_planeDownLeftSphere .transform.localPosition = data.plane.origin + data.plane.u*-1*planeSize + data.plane.v*-1*planeSize;
|
||||||
|
_planeDownRightSphere.transform.localPosition = data.plane.origin + data.plane.u*1*planeSize + data.plane.v*-1*planeSize;
|
||||||
|
|
||||||
Logger.Log($"Raycast hit \"position\": {posText}, \"normal\": {normText} on [{data.bodyName}] at [{data.bodyPath}]");
|
Logger.Log($"Raycast hit \"position\": {posText}, \"normal\": {normText} on [{data.bodyName}] at [{data.bodyPath}]");
|
||||||
}
|
}
|
||||||
internal DebugRaycastData Raycast()
|
internal DebugRaycastData Raycast()
|
||||||
@ -65,14 +88,49 @@ namespace NewHorizons.Utility.DebugUtilities
|
|||||||
data.pos = hitInfo.transform.InverseTransformPoint(hitInfo.point);
|
data.pos = hitInfo.transform.InverseTransformPoint(hitInfo.point);
|
||||||
data.norm = hitInfo.transform.InverseTransformDirection(hitInfo.normal);
|
data.norm = hitInfo.transform.InverseTransformDirection(hitInfo.normal);
|
||||||
var o = hitInfo.transform.gameObject;
|
var o = hitInfo.transform.gameObject;
|
||||||
|
|
||||||
|
var hitAstroObject = o.GetComponent<AstroObject>() ?? o.GetComponentInParent<AstroObject>();
|
||||||
|
|
||||||
data.bodyName = o.name;
|
data.bodyName = o.name;
|
||||||
data.bodyPath = SearchUtilities.GetPath(o.transform);
|
data.bodyPath = SearchUtilities.GetPath(o.transform);
|
||||||
data.hitObject = hitInfo.transform.gameObject;
|
data.hitObject = o;
|
||||||
|
data.hitBodyGameObject = hitAstroObject?.gameObject;
|
||||||
|
data.plane = ConstructPlane(data);
|
||||||
}
|
}
|
||||||
_rb.EnableCollisionDetection();
|
_rb.EnableCollisionDetection();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal Plane ConstructPlane(DebugRaycastData data)
|
||||||
|
{
|
||||||
|
var U = data.pos - Vector3.zero; // U is the local "up" direction. the direction directly away from the center of the planet at this point. // pos is always relative to the body, so the body is considered to be at 0,0,0.
|
||||||
|
var R = data.pos; // R is our origin point for the plane
|
||||||
|
var N = data.norm.normalized; // N is the normal for this plane
|
||||||
|
|
||||||
|
if (Vector3.Cross(U, N) == Vector3.zero) U = new Vector3(0, 0, 1);
|
||||||
|
if (Vector3.Cross(U, N) == Vector3.zero) U = new Vector3(0, 1, 0); // if 0,0,1 was actually the same vector U already was (lol), try (0,1,0) instead
|
||||||
|
|
||||||
|
Logger.Log("U is " + U.ToString());
|
||||||
|
|
||||||
|
// stackoverflow.com/a/9605695
|
||||||
|
// I don't know exactly how this works, but I'm projecting a point that is located above the plane's origin, relative to the planet, onto the plane. this gets us our v vector
|
||||||
|
var q = (2*U)-R;
|
||||||
|
var dist = Vector3.Dot(N, q);
|
||||||
|
var v_raw = 2*U - dist*N;
|
||||||
|
var v = (R-v_raw).normalized;
|
||||||
|
|
||||||
|
var u = Vector3.Cross(N, v);
|
||||||
|
|
||||||
|
Plane p = new Plane()
|
||||||
|
{
|
||||||
|
origin = R,
|
||||||
|
normal = N,
|
||||||
|
u = u,
|
||||||
|
v = v
|
||||||
|
};
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user