Jump to content

Vector3.up doesn't point up, and other Vector3 questions


Recommended Posts

I'm having some issues with the Vector3 class as it pertains to drawing lines and triangles relative to a part. I started with the template provided by http://wiki.kerbalspaceprogram.com/wiki/Module_code_examples

Starting with that sample code, my current code block looks like this:


// Create a triangle and give it a shape
GameObject obj3 = new GameObject( "Line" );
greenline = obj3.AddComponent< LineRenderer >();
greenline.transform.parent = transform;
greenline.useWorldSpace = true; // true = Stay static on the ground. false = Move with part
greenline.material = new Material( Shader.Find("Particles/Additive") );
greenline.SetColors( Color.green, Color.green ); // Make it green
greenline.SetWidth(0, 2); // Make it width 0 at point 0, width 2 at point 1
greenline.SetVertexCount(2); // Haven't toyed with this yet

// Place triangle in the world relative to part that created it (a Kerbal)
greenline.SetPosition(0, Vector3.zero); // Point 0 is located at Kerbal's location, Vector3.zero
greenline.SetPosition(1, 5 * Vector3.left); // Point 1 is located 5 meters "left" of the Kerbal

Similar code for the rest of the lines:


redline.SetPosition(0, Vector3.zero);
redline.SetPosition(1, 5 * Vector3.up);

blueline.SetPosition(0, Vector3.zero);
blueline.SetPosition(1, 5 * Vector3.down);

yellowline.SetPosition(0, Vector3.zero);
yellowline.SetPosition(1, 5 * Vector3.right);

whiteline.SetPosition(0, Vector3.zero);
whiteline.SetPosition(1, 5 * Vector3.forward);

blackline.SetPosition(0, Vector3.zero);
blackline.SetPosition(1, 5 * Vector3.back); // You can't see it. Changing it to something other than black makes it visible opposite of white

I end up with this:

2jQq9UI.png

NxJAH6h.png

imDSDnm.png

kqS7t0m.png

No matter which way the Kerbal is pointing, Vector3.up (red) points North, Vector3.down (blue) points South, and the rest are a mix of Up/Down and East/West. I've also tried Vector3d with the same results.

If I set greenline.useWorldSpace = false; then I see the lines move with the Kerbal, but it looks like this:

QlZRt3E.png

So Vector3.up (red) is left relative to the Kerbal? Vector3.right (yellow) is down and behind the Kerbal?

Ultimately I'd really like a way to create a line directly up from the Kerbal, but I feel like there's an easier way than doing some funny algebra. And given the weirdness I'm seeing here I feel like I'm missing something. Any ideas?

Potentially useful links:

Code example: http://wiki.kerbalspaceprogram.com/wiki/Module_code_examples

Community API Documentation: http://wiki.kerbalspaceprogram.com/wiki/Community_API_Documentation

KSP Documentation: http://anatid.github.io/XML-Documentation-for-the-KSP-API/struct_vector3d.html

Unity Documentation: http://docs.unity3d.com/ScriptReference/Vector3.html

Link to comment
Share on other sites

The Vector3 constants are based on the world space, and the KSP coordinate system has a number of layers between the world space and where you are to account for all the planet stuff. It's quite complex.

That being said, if you do want to get surface relative directions, one method is via:


Vector3 gee = FlightGlobals.getGeeForceAtPosition( transform.position );

There's also (potentially):


Vector3d Vessel.upAxis;
//Which can be accessed via
FlightGlobals.ActiveVessel.upAxis;

As well as a number of other things in the Vessel class that may help you, depending on what you need.

Edited by Xaiier
Link to comment
Share on other sites

Alright, two things I'm going to comment on. (I'm not sure either of these qualify as answers.)

First, this setting the transform here:

greenline.transform.parent = transform; 

What is the transform you are setting the parent as? Are you running this 'inside' the Kerbal so it is grabbing the Kerbal's transform?

Second, while correct, the following has some wrong assumptions that are not helping.

No matter which way the Kerbal is pointing, Vector3.up (red) points North, Vector3.down (blue) points South, and the rest are a mix of Up/Down and East/West. I've also tried Vector3d with the same results.

The co-ordinate system used by KSP is a standard box system with X being Left/Right, Y being Up/Down, Z being Forward/Back. X and Z are pretty arbitrary depending on where a planet is in it's orbit and spin, but Y is always in the same direction in that going from a planets south pole to north pole through it's center is Up movement in the Y direction.

So with worldspace=true, the red arrow is pointing up, which happens to be north as the KSP Complex is on kerbin's equator. If you ran this code at Kerbin's North Pole, the red Up arrow would be pointing straight into the sky. This is because the worldspace=true is telling KSP to use the world co-ordinates for reference.

With worldspace=false, the Vector3 directions are now relative to the kerbal's facing. On parts these are pretty straight forward but it looks like something funny is happening to directions relative to the kerbal model. (I'm pretty sure Vector3.Fwd would always be the direction of travel on an SRB but double check that.)

To get an arrow drawn from the Kerbal straight "up" into the sky needs something like this:

Vector3 SkywardsDir = FlightGlobals.ActiveVessel.body.position - Kerbal.transform.position; //get vector from world CoM to Kerbal's CoM
redline.SetPosition(0, Vector3.zero); //assuming redline.transform.position has been set to the Kerbal's CoM.
redline.SetPosition(1, 5 * SkywardsDir.normalized);

I actually do a lot of this in my Vertical Velocity mod to allow players to set the Up direction.

 theLine.transform.parent = TWR1Vessel.rootPart.transform; //set my line transform's parent to the transform of the rootPart of the current vessel.
theLine.transform.localPosition = Vector3.zero; //reset location of transform
theLine.transform.rotation = Quaternion.identity; //reset rotation of transform
theLine.SetPosition(0, new Vector3(0, 0, 0)); //line starts at the CoM of my root part of vessel
theLine.SetPosition(1, TWR1ControlUp * 50); //Extend line 50 meters in the ControlUp direction determined previously in code.

Hope that helps,

D.

Link to comment
Share on other sites

Thanks for the ideas, but nothing seems to have worked so far. Here's what I've tried and found:


blueline.SetPosition(1, 5 * FlightGlobals.ActiveVessel.rootPart.transform.up); // Short forward-left triangle
blueline.SetPosition(1, 5 * FlightGlobals.getUpAxis(Vector3d.zero)); // Short forward-left triangle
blueline.SetPosition(1, 5 * FlightGlobals.getUpAxis()); // Short forward-left triangle
blueline.SetPosition(1, 5 * FlightGlobals.ship_upAxis); // Short forward-left triangle
blueline.SetPosition(1, 5 * FlightGlobals.getGeeForceAtPosition (Vector3d.zero)); // Long back-right triangle
blueline.SetPosition(1, 5 * FlightGlobals.ActiveVessel.upAxis); // Long back-right or Short forward-left triangle
blueline.SetPosition(1, 5 * FlightGlobals.getGeeForceAtPosition( transform.position )); // Long back-right or Short forward-left triangle

I checked the code for your Vertical Velocity mod and it looks like TWR1ControlUp gets set by the SetDirection() function which looks like this:


public Vector3 SetDirection()
{
if (ControlDirection == 0)
{
return (TWR1Vessel.rootPart.transform.up);
}
if (ControlDirection == 1)
{
return (TWR1Vessel.rootPart.transform.forward);
}
if (ControlDirection == 2)
{
return (-TWR1Vessel.rootPart.transform.up);
}
if (ControlDirection == 3)
{
return (-TWR1Vessel.rootPart.transform.forward);
}
if (ControlDirection == 4)
{
return (TWR1Vessel.rootPart.transform.right);
}
if (ControlDirection == 5)
{
return (-TWR1Vessel.rootPart.transform.right);
}
else
{
return (TWR1Vessel.rootPart.transform.up);
}
}

That looks a lot like my "blueline.SetPosition(1, 5 * FlightGlobals.ActiveVessel.rootPart.transform.up);" attempt. So it works for you, but not me. Surely there's something else I'm missing here?

Edited by SuperSeniorComicGuy
Link to comment
Share on other sites

The scene is often rotated and the camera moved to make it look like "up" is up when the reality is you're perched like a fly on the side of a ball at KSP. Here's an example that captures what you're trying to do (if I read the intent correctly):

[KSPAddon(KSPAddon.Startup.Flight, false)]
class LineDrawer : MonoBehaviour
{
LineRenderer up, right, forward, sky;
Transform owner;

private System.Collections.IEnumerator Start()
{
while (!FlightGlobals.ready) yield return 0;

var rt = FlightGlobals.ActiveVessel.rootPart.transform;

forward = MakeLine(rt, Color.blue);
right = MakeLine(rt, Color.red);
up = MakeLine(rt, Color.green);
sky = MakeLine(rt, Color.yellow);

sky.SetWidth(0.2f, 0.1f);

owner = rt;
}

private LineRenderer MakeLine(Transform parent, Color color)
{
GameObject line = new GameObject();
line.transform.parent = parent;

var r = line.AddComponent<LineRenderer>();

r.useWorldSpace = true; // ignores own position, just use coordinates in worldspace as given
r.SetWidth(1f, 0.01f);
r.SetVertexCount(2);

r.material = new Material(Shader.Find("Particles/Additive"));
r.SetColors(color, color);

return r;
}

private void Update()
{
if (!FlightGlobals.ready) return;

up.SetPosition(0, owner.position);
up.SetPosition(1, owner.position + owner.up * 5f);

right.SetPosition(0, owner.position);
right.SetPosition(1, owner.position + owner.right * 5f);

forward.SetPosition(0, owner.position);
forward.SetPosition(1, owner.position + owner.forward * 5f);

sky.SetPosition(0, owner.position);
sky.SetPosition(1, owner.position + FlightGlobals.upAxis * 10f);

}
}

Edited by xEvilReeperx
Link to comment
Share on other sites

First, looking at my VertVel mod, I should not have linked that as I have worldCoordinates=false, you are going to have to set worldCoordiantes=true for what you are trying to do.

You are still simply looking to draw a line from the center of the Kerbal upwards into the sky correct?

Second, we are tripping over the fact that in unity, the Vector3.up is simply shorthand for Vector3(0,1,0), it is not actually "up". Also, the fact that each object in the game has local-space and world-space coordinates is just making things even more confusing.

So, an expanded example I hope will work for you (modifying the example from your opening post, changes in red-bold):

// Create a triangle and give it a shape
GameObject obj3 = new GameObject( "Line" );
greenline = obj3.AddComponent< LineRenderer >();
greenline.transform.parent = transform; [B][COLOR="#FF0000"]//double check that 'transform' is in fact the Kerbal's transform. It seems to be based on your next posts, but the code itself is not clear.[/COLOR][/B]
greenline.useWorldSpace = true; // true = Stay static on the ground. false = Move with part [b][COLOR="#FF0000"]Worldspace is needed as the line we are drawing will be relative to two separate objects[/COLOR][/b]
greenline.material = new Material( Shader.Find("Particles/Additive") );
greenline.SetColors( Color.green, Color.green ); // Make it green
greenline.SetWidth(0, 2); // Make it width 0 at point 0, width 2 at point 1
greenline.SetVertexCount(2); // Haven't toyed with this yet [b][COLOR="#FF0000"]this is the number of Vertex's on the line. A straight line will always have 2[/COLOR][/b]

// Place triangle in the world relative to part that created it (a Kerbal)
[b][COLOR="#FF0000"]Vector3 skywardsDirection = Kerbal.body.position - Kerbal.transform.position; //get our vector from the center of the planet we are standing on to the center of our kerbal. Refresh this every frame since it changes when the kerbal moves[/COLOR][/b]
greenline.SetPosition(0, Vector3.zero); // Point 0 is located at Kerbal's location, Vector3.zero
greenline.SetPosition(1, 5 * [b][COLOR="#FF0000"]skywardsDirection.normalize); //Point 1 is located 5 meters away in the direction calculated from the center of the planet to our kerbal. Vector3.normalize takes any vector and makes it 1 meter long.[/COLOR][/b]

Hopefully that is clear enough now that you can get things working.

D.

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...