Jump to content

Direct object Reference to CelestialBody object


Recommended Posts

I want to add an object / linedraw that starts from the center of Kerbin in the map view. It needs to be visible regardless of which CB/Vessel/Node is the active/selected/focused item.

Using the code in this thread, I was able to get a sphere in the map scene as a way for me to learn about putting objects in the map screen, but I can't work out how to reference Kerbin as an entity directly so I can always use it as the reference object. The example only ultilsed the selected CB or vessel in the tracking center. I don't want to use the active object as this object/vector needs to be visible regardless of the selected vessel / CB

I've tried to reference the CB as seen below;

CelestialBody kerbin = FlightGlobals.Bodies[1];

The issue is assigning the appropriate transform to have the vector coming out from the planet

                myLineObj.transform.position = ScaledSpace.LocalToScaledSpace(kerbin.transform.position);
                myLineObj.transform.parent = kerbin.transform;
                myLineObj.transform.localScale = Vector3.one * scale_multiplier;
                myLineObj.transform.localPosition = Vector3.zero;
                myLineObj.transform.localRotation = Quaternion.identity;

Is there a primer on working with transforms / Vector3 / Quaternion stuff, as I'm struggling to get my head around it all.

Thanks in advance

Edited by wile1411
Link to comment
Share on other sites

Ok, you really just need to know how to declare them, which means for vector3d, you need a set of cart coords. 

They are declared by the following:

var myVector = Vector3d(x, y, z);
//creates a new instance of vector 3d using the constructor

As you can see, the vectors are created and stored with x y and z coords. 

Now, taking a look at the QuaternionD referneces, you declare it with the constructors seen here: https://kerbalspaceprogram.com/api/struct_unity_engine_1_1_quaternion_d.html#a3951bc29d076c2dcda4c5bbdde4b7db5

You need to get the position of the CB, and use that for your Vector3d 's.

I'm not sure what the w is for QuaternionD's, maybe someone else can offer more insight into that. 

Link to comment
Share on other sites

I've fixed most of the references to give the correct numbers for where Kerbin is in the scene.

I just need to work out how to convert: FlightGlobals.Bodies[1].transform into the Scaled scale numbers so I can assign it to my object.transform.parent.

myConeObj.transform.position = ScaledSpace.LocalToScaledSpace(FlightGlobals.Bodies[1].transform.position);
myConeObj.transform.parent = FlightGlobals.Bodies[1].transform;
myConeObj.transform.localScale = ScaledSpace.LocalToScaledSpace(FlightGlobals.Bodies[1].transform.localScale);
myConeObj.transform.localPosition = ScaledSpace.LocalToScaledSpace(FlightGlobals.Bodies[1].transform.localPosition);
myConeObj.transform.eulerAngles = new Vector3(90.0f, 0.0f, 0.0f);

the last line doesn't work quite how I want it to. It give me the myConeObj out of the equator (as I want) but it's in a fixed location and wont rotate with the body.

Link to comment
Share on other sites

1 hour ago, wile1411 said:

... the last line doesn't work quite how I want it to. It give me the myConeObj out of the equator (as I want) but it's in a fixed location and wont rotate with the body.

If you are fine with sharing your code, maybe you could post the code needed to draw your current cone. It might be fun to play around with it a little and learn something.

Edited by Rodhern
aeh, a bit of gibberish snuck in there
Link to comment
Share on other sites

The CelestialBody position in world coordinate is just cb.position, so :

myConeObj.transform.position = ScaledSpace.LocalToScaledSpace(FlightGlobals.Bodies[1].position);

hum. Why do you set position, parent and localPosition ? Either you have no parent and you move it by hand or you parent it and the local pos should be 0 0 0. If you set both you waste CPU.

Edited by sarbian
Link to comment
Share on other sites

2 hours ago, sarbian said:

The CelestialBody position in world coordinate is just cb.position, so :


myConeObj.transform.position = ScaledSpace.LocalToScaledSpace(FlightGlobals.Bodies[1].position);

hum. Why do you set position, parent and localPosition ? Either you have no parent and you move it by hand or you parent it and the local pos should be 0 0 0. If you set both you waste CPU.

Because I copied an example from 4 years ago for game with little documentation and bugger all knowledge on what I'm doing? :D Thanks for the info, that indeed did fix that issue.

I now need to work out how to get the cone to rotate with the body. As I understand it  using the below setting rotates the cone from pointing straight up to 90 down to the equator. 
myConObj.transform.eulerAngles = new Vector3(90.0f, 0.0f, 0.0f);

I'm pretty sure I can't use: myConObj.transform.localRotation = Quaternion.identity;  as that locks the rotate to "don't rotate". I think I'm after a Quaternion.LookRotation and need to look up more on how that works.

Or putting another way - I need to point red (right) and rotate green (up).

Edited by wile1411
Link to comment
Share on other sites

2 hours ago, Rodhern said:

If you are fine with sharing your code, maybe you could post the code needed to draw your current cone. It might be fun to play around with it a little and learn something.

The cone code I'm using is just the unity example to draw a procedural mesh. There's a few examples of various shape on this page.

http://wiki.unity3d.com/index.php/ProceduralPrimitives

Edited by wile1411
Link to comment
Share on other sites

4 hours ago, wile1411 said:

I'm pretty sure I can't use: myConObj.transform.localRotation = Quaternion.identity

I think you are very close though.

Let us assume that at some point you have your cone (positioned and) rotated so that it matches Kerbin in its zero rotation state. Then you can store that state with something like:

q1 := myConObj.transform.localRotation

Then in every frame update the rotation:

q2 := FlightGlobals.Bodies.[1].transform.localRotation

myConObj.transform.localRotation := Quaternion.op_Multiply(q1,q2)

 

Link to comment
Share on other sites

Instead of using "ScaledSpace.LocalToScaledSpace()" you can access the transform of the map object of the body/vessel you want :

CelestialBody.MapObject.trf
or
Vessel.mapObject.trf

And if you need your object to rotate with the body/vessel you can make it a child of the map object transform.

I've made something very similar to what your talking about for the last update of Antenna Helper where I display several circle in the map view representing the range of the DSN antenna. Check this file and this one (the "SetMapMarker" method).

Edited by Li0n
Link to comment
Share on other sites

@Rodhern solution is elegant but if you do not get Quaternion it may be a bit confusing to understand what is going on. So you can do something easier to understand :

Vector3 direction = positionOfTheObjectYouWantToPointTo -  myConObj.transform;
myConObj.transform.rotation = Quaternion.SetLookRotationy(direction);

 

Link to comment
Share on other sites

 

1 hour ago, sarbian said:

@Rodhern solution is elegant but if you do not get Quaternion it may be a bit confusing to understand what is going on. So you can do something easier to understand :


Vector3 direction = positionOfTheObjectYouWantToPointTo -  myConObj.transform;
myConObj.transform.rotation = Quaternion.SetLookRotationy(direction);

 

For the "positionOfTheObjectYouWantToPointTo" - if I just want to point the cone away from the celestial body, is it as simple as saying Vector3.right or does it need to be an actual ojbect? That's the problem with pointing away the reference CB, I don't want to look at it's direction.

Link to comment
Share on other sites

7 minutes ago, wile1411 said:

 

For the "positionOfTheObjectYouWantToPointTo" - if I just want to point the cone away from the celestial body, is it as simple as saying Vector3.right or does it need to be an actual ojbect? That's the problem with pointing away the reference CB, I don't want to look at it's direction.

It s a Vector3. It can be a constant like Vector3.right but it could be the position of the sun ( Planetarium.Sun.MapObject.trf.position ), the parent body (cb.parent.MapObject.trf.position), ...

Link to comment
Share on other sites

OK - I've got the cone up again, but it's acting weird when I I use timewarp or move the camera.. Initially it's got a really loose connection with the world in that it lags behind where it should be if I move the mouse quickly. When I time warp, it shakes around like mad to the point where there is 3-4 after image cones dancing about. You can see in my logging that the localPosition is all skewif

[LOG 00:37:43.459] [PlanetariumCamera]: Focus: Kerbin
[LOG 00:37:43.467] [TestCone] CelestialBody: Kerbin
[LOG 00:37:43.482] [TestCone] SelectedMAPobj: Kerbin
[LOG 00:37:43.483] [TestCone] position: (2680.5, -231.0, 830.6)
[LOG 00:37:43.484] [TestCone] localPosition: (2680.5, -231.0, 830.6)
[LOG 00:37:43.485] [TestCone] localScale: (0.1, 0.1, 0.1)
[LOG 00:37:43.486] [TestCone] 
[LOG 00:37:43.487] [TestCone] CONE: 
[LOG 00:37:43.488] [TestCone] position: (2681.0, -231.0, 832.0)
[LOG 00:37:43.489] [TestCone] localPosition: (-8693757.0, -1245.9, -15056520.0)
[LOG 00:37:43.490] [TestCone] localScale: (808.1, -231.1, 3042.3)
[LOG 00:37:43.491] [TestCone] x:2681
[LOG 00:37:43.492] [TestCone] y:-230.9753
[LOG 00:37:43.493] [TestCone] z:832
[LOG 00:37:43.494] [TestCone] 
[LOG 00:37:43.495] [TestCone] DirectRefKerbin: 
[LOG 00:37:43.496] [TestCone] position: [2680.55646281518, -230.975326534619, 830.54064281733]
[LOG 00:37:43.497] [TestCone] localPosition: [2680.55646281518, -230.975326534619, 830.54064281733]
[LOG 00:37:43.499] [TestCone] localScale: [808.114816202753, -231.144311528333, 3042.25711912938]

zyyl32Th.png

Here's the dll if someone wants to see the effect realtime (compiled under 1.3.1)

Throw it under a folder in the Gamedata folder, load a game and go into tracking center to see what I mean.

Edited by wile1411
Link to comment
Share on other sites

4 hours ago, Li0n said:

Instead of using "ScaledSpace.LocalToScaledSpace()" you can access the transform of the map object of the body/vessel you want :


CelestialBody.MapObject.trf
or
Vessel.mapObject.trf

And if you need your object to rotate with the body/vessel you can make it a child of the map object transform.

I've made something very similar to what your talking about for the last update of Antenna Helper where I display several circle in the map view representing the range of the DSN antenna. Check this file and this one (the "SetMapMarker" method).

Thanks for this suggestion! The line "marker.transform.Rotate (Vector3.right, 90f);" is what I was missing with being able to turn the cone on it's side but still rotate with the planet. :) 

Still have to work out the shaking bit now.

Link to comment
Share on other sites

26 minutes ago, wile1411 said:

When I time warp, it shakes around like mad to the point where there is 3-4 after image cones dancing about

I know what is going on and how you can fix it but you ll have to wait for me to get back home so I have my code around. It s a matter of timing.

Link to comment
Share on other sites

Just now, sarbian said:

I know what is going on and how you can fix it but you ll have to wait for me to get back home so I have my code around. It s a matter of timing.

Awesome - thanks for the help. I'm going to head to bed and get some sleep, but I'll bang against the keyboard again tomorrow. :) 

Link to comment
Share on other sites

So as I said earlier the problem is timming. Your code runs is most likely runs for an Update call so it runs each frame and since it s a mod code it runs a what Unity call priority 0. KSP code runs at various timing so some of KSP calls are always called before the mods and others are always called after. From memory one of the code that actually runs later is the movement of the ScaledSpace. So your mods move stuff related to the position of a planet in scaledSpace but  scaledSpace move stuff after your mods, so you are lagging behind.

For some code the answer is simple. Replace Update with LateUpdate. But here it won't help you because ScaledSpace already uses LateUpdate. So how do you make your code runs even later ? The "easy" solution is the TimmingManager that was added in 1.2. You can can ask it tu run your code at one of the pre set timing. If you look at the script order doc you will see that scaled space runs at timing 500 so you need something later. Luckily you can see Timing5 at the end of the list (Timing4 is at 19, too early for our needs). So how do you use that ? It requires a bit more code.

A basic template would be 

public override void OnStart(PartModule.StartState state) // OnStart for a PartModule. "void Start()" for a MonoBehaviour
{
	// Register our code with the timing manager and ask it to run at the last timing available (the order should be clear from the names)
	TimingManager.LateUpdateAdd(TimingManager.TimingStage.BetterLateThanNever, CodeWeWantToRunLate);
}

void OnDestroy()
{	
	// Removing the call when your object is gone is critial.
	TimingManager.LateUpdateRemove(TimingManager.TimingStage.BetterLateThanNever, CodeWeWantToRunLate);
}

// This replace our Update() or OnUpdate()
void CodeWeWantToRunLate() 
{
	// We need to check if the object we run on is actually active because the timing manager does not check.
	if (!this.isActiveAndEnabled)
		return;
	(do stuff)
}

 

Link to comment
Share on other sites

24 minutes ago, sarbian said:

So as I said earlier the problem is timming. Your code runs is most likely runs for an Update call so it runs each frame and since it s a mod code it runs a what Unity call priority 0. KSP code runs at various timing so some of KSP calls are always called before the mods and others are always called after. From memory one of the code that actually runs later is the movement of the ScaledSpace. So your mods move stuff related to the position of a planet in scaledSpace but  scaledSpace move stuff after your mods, so you are lagging behind.

For some code the answer is simple. Replace Update with LateUpdate. But here it won't help you because ScaledSpace already uses LateUpdate. So how do you make your code runs even later ? The "easy" solution is the TimmingManager that was added in 1.2. You can can ask it tu run your code at one of the pre set timing. If you look at the script order doc you will see that scaled space runs at timing 500 so you need something later. Luckily you can see Timing5 at the end of the list (Timing4 is at 19, too early for our needs). So how do you use that ? It requires a bit more code.

Gah! This modding rabbit hole is deeeeep! There is no way in a million years I'd find that out through the stumbling trial & error process I'm using to attempt to cobble this idea together.

Thanks so much @sarbian - works fantastic and the movement is now in sync with the camera. I'm able to lock the cone to the planet and there in no delay at all now. I even got the cone to rotate with the planet using @Rodhern code with a minor modification as I think we are talking in different langs (I'm using c#) and I couldn't find a op_Multiply function.

Start process
GameEvents.OnMapEntered.Add(MapEnter);

MapEnter process
q1 = myConObj.transform.localRotation;       

CodeWeWantToRunLate process
q2 = kerbin.transform.localRotation;
myConObj.transform.localRotation = q1 * q2;

 

here's the dll is you want to see how I've done so far.

Link to comment
Share on other sites

here's probably a math query (I think).

So I've got my cone pointing where I want to, how would I move the transform so the point of the cone is closer to the surface of Kerbin? I tried a straight change to x and or z and that just changes the central rotation point of the cone away from Kerbin. 

I'm looking to basically change the cones altitude relative to Kerbin.

Currently the cone assigning code looks like this. I wasn't able to get the parent method to work for me.

CelestialBody trackedcb = Planetarium.fetch.Home;
myConObj.transform.position = ScaledSpace.LocalToScaledSpace(trackedcb.transform.position);

//Set Scale
Vector3 scale = transform.localScale;
scale.Set(cone_multiplier, cone_multiplier, cone_multiplier);
myConObj.transform.localScale = scale;

//Set Rotation relations to CB Body
q2 = trackedcb.transform.localRotation;
myConObj.transform.localRotation = q1 * q2;

//Rotate down to Equator
myConObj.transform.Rotate(Vector3.right, 90f);

cone_renderer.enabled = true;

 

Link to comment
Share on other sites

Hah, I'm still proving I'm a dunce. On the drive into work musing about KSP things (as you do), I realised why "rotating around the planet with an altitude" sounded weird... 

Yeah, it's a long way of saying 'orbit'. Don't mind me, I'm now searching on issues with parenting an object. My cone disappears when I used the parent method @sarbian suggested earlier in the thread. I'm thinking I might need to check to scale gets set to zero or something which could make the cone be hidden inside kerbin. My debug info says it have no position though, so as far as I can tell, it's not rendered the scene that I can see.

Edited by wile1411
Link to comment
Share on other sites

8 hours ago, wile1411 said:

"rotating around the planet with an altitude"

Maybe with "Transform.RotateAround" ?

8 hours ago, wile1411 said:

I'm now searching on issues with parenting an object. My cone disappears when I used the parent method @sarbian suggested earlier in the thread. I'm thinking I might need to check to scale gets set to zero or something which could make the cone be hidden inside kerbin. My debug info says it have no position though, so as far as I can tell, it's not rendered the scene that I can see.

Check/reset position AND localPosition. Make sure your object is on the good layer, 10 for MapView.

Link to comment
Share on other sites

22 minutes ago, Li0n said:

Maybe with "Transform.RotateAround" ?

Check/reset position AND localPosition. Make sure your object is on the good layer, 10 for MapView.

Already had layer 10. I was thinking to use rotate around, but Visual Studio is telling that Transform.RotateAround" is deprecated and to use transform.rotate instead.

I tried the following to set the parent and thankfully the cone renders, but it's waaaaaay off in the distance and slipping away quickly.

                myConObj.transform.SetParent(trackedcb.transform);
                myConObj.transform.localPosition = trackedcb.transform.localPosition;

 

Link to comment
Share on other sites

5 hours ago, wile1411 said:

Already had layer 10. I was thinking to use rotate around, but Visual Studio is telling that Transform.RotateAround" is deprecated and to use transform.rotate instead.

I tried the following to set the parent and thankfully the cone renders, but it's waaaaaay off in the distance and slipping away quickly.

                myConObj.transform.SetParent(trackedcb.transform);
                myConObj.transform.localPosition = trackedcb.transform.localPosition;

 

trackedcb is the CelestialBody or the MapObject representing the CelestialBody ? It needs to be the MapObject.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...