Jump to content

Determine collision at point


Recommended Posts

Hello. I'm developing a warp drive mod (thousands of them! :))

The general idea based on teleporting vessel very very very fast (once per frame) using vessel.SetPosition(Vector3d position) method which makes illusion that ship is really flying whenever you need.

Everything works great expect of "through planet warp" and i asking you for help. I have serious language(english) problems and i suck at explaining things (Just wanna say sorry).

As i said i'm teleporting vessel every frame in target direction:

jumpToPos = vessel.transform.position + (TS.TargetVector * destination); //jumpToPos, TargetVector are Vector3d variables, destination is increases and decreases.

then:

vessel.SetPosition(jumpToPos);

but if new vessel position will be under surface vessel will explode (ORLY? :) )

so i have to check jumpToPos before jumping on it.

i can simple determine collision:

(x-a)^2 + (y-B)^2 + (z-c)^2 Mustn't be less or equals to R^2,

where a, b, c, R - planet position and radius

and x, y, z are jumpToPos values.

or:

(Math.Pow((jumpToPos.x - vessel.mainBody.transform.position.x), 2) + Math.Pow((jumpToPos.y - vessel.mainBody.transform.position.y), 2) + Math.Pow((jumpToPos.z - vessel.mainBody.transform.position.z), 2)) <= Math.Pow(vessel.mainBody.Radius, 2)

So if this condition returns true i shouldn't jump because of explosion.

But this thing work only if planet is a perfect sphere without mountains, hils and etc (nothing above sea level)

so i have a second check using raycast:

if (Physics.Raycast(jumpToPos, TS.TargetVector, out headHit, (float)(destination), 1 << 15))

and if this condition is true i shouldn't jump too.

Now everything is simple:

every frame i'm calculate jumpToPos and when it's safe to jump on i'm jumping on it, if not(planet collision) i'm just standing and waiting when jumpToPos will became safe again (flew from planet)

here's example (Mad skillz included):

0gbu0C0el_E.jpg

where jumpToPos is A, then B, thec C....

When the vessel is at point C, next jumpToPos will be D and the raycast with length CD will say vessel to keep on C.

On the next step raycast from D to E won't find collision but E belongs to sphere and the vessel will keep on C too.

Same for the F point.

At the end vessel will jump to G and everything will be ok.

Just show a dark screen while vessel is holding on C :)

Zoomed:

lEeoxjlqoyI.jpg

But!!!

if more than one jumpToPos points will be below surface but above sea level there's will be a problem:

y6ELhGnPUAs.jpg

step 1: vessel on A, jumpToPos = B, B is safe(no collision) => jumping to B

step 2: vessel on B, jumpToPos = C, C isn't safe(raycast detected hit), keep vessel on B

step 3: vessel on B, JumpToPos = D, D is safe! No raycast hit, not belongs to sphere(red area), jumping to D and exploding!

So i need a 3rd check:

if(lastColAlt>vessel.altitude)
{
isSafeToJump = false;
}

where

lastColAlt = FlightGlobals.getAltitudeAtPos(headHit.barycentricCoordinate); //from last raycast hit with surface

to determine if the vessel is under surface

Full code:

private void Jump(double destination)
{
bool isSafeToJump = true;

if (Physics.Raycast(jumpToPos, TS.TargetVector, out headHit, (float)(destination + 50.0), 1 << 15)) //is any collision on the way to next jump point. Do it before calculating new jumpToPos value
{
lastColAlt = FlightGlobals.getAltitudeAtPos(headHit.barycentricCoordinate);
isSafeToJump = false;
}
if (lastColAlt > vessel.altitude) // if under surface
{
isSafeToJump = false;
}


jumpToPos = vessel.transform.position + (TS.TargetVector * destination); // calculate next jump point


if ((Math.Pow((jumpToPos.x - vessel.mainBody.transform.position.x), 2) + Math.Pow((jumpToPos.y - vessel.mainBody.transform.position.y), 2) + Math.Pow((jumpToPos.z - vessel.mainBody.transform.position.z), 2)) <= Math.Pow(vessel.mainBody.Radius + 5, 2)) // is next jump point belongs to planet(sphere only)
{
isSafeToJump = false;
lastColAlt = 0.0; //drop value
}

///Jump or not

if(isSafeToJump)
{
lastSafePos = vessel.transform.position;
lastColAlt = 0.0;

vessel.SetPosition(jumpToPos);
}
else
{
vessel.SetPosition(lastSafePos);
print("ABORT!");
}

Now i have brilliant monkey code which works every 2nd time.

So...

Is there any way to check collision at point (like i can check altitude FlightGlobals.getAltitudeAtPos())?

Or any ideas?!

Or how can i disable collision at all?

vessel.GoOnRails() can't solve this problem.

vessel.collider retutrns null ref exception, looping from every part of the vessel and disabling collider has no effect, Physics.IgnoreCollision - nothing too.

Thank you for your answers!

P.S.

bounus-proof of concept:

Laythe:

fXJFYej8JNw.jpg

Warping to Ike:

PuLh06mXfus.jpg

iKDjSq3pW5c.jpg

Link to comment
Share on other sites

Hello. I'm developing a warp drive mod (thousands of them! :))

The general idea based on teleporting vessel very very very fast (once per frame) using vessel.SetPosition(Vector3d position) method which makes illusion that ship is really flying whenever you need.

Everything works great expect of "through planet warp" and i asking you for help. I have serious language(english) problems and i suck at explaining things (Just wanna say sorry).

As i said i'm teleporting vessel every frame in target direction:

jumpToPos = vessel.transform.position + (TS.TargetVector * destination); //jumpToPos, TargetVector are Vector3d variables, destination is increases and decreases.

then:

vessel.SetPosition(jumpToPos);

but if new vessel position will be under surface vessel will explode (ORLY? :) )

so i have to check jumpToPos before jumping on it.

i can simple determine collision:

(x-a)^2 + (y-B)^2 + (z-c)^2 Mustn't be less or equals to R^2,

where a, b, c, R - planet position and radius

and x, y, z are jumpToPos values.

or:

(Math.Pow((jumpToPos.x - vessel.mainBody.transform.position.x), 2) + Math.Pow((jumpToPos.y - vessel.mainBody.transform.position.y), 2) + Math.Pow((jumpToPos.z - vessel.mainBody.transform.position.z), 2)) <= Math.Pow(vessel.mainBody.Radius, 2)

So if this condition returns true i shouldn't jump because of explosion.

But this thing work only if planet is a perfect sphere without mountains, hils and etc (nothing above sea level)

so i have a second check using raycast:

if (Physics.Raycast(jumpToPos, TS.TargetVector, out headHit, (float)(destination), 1 << 15))

and if this condition is true i shouldn't jump too.

Now everything is simple:

every frame i'm calculate jumpToPos and when it's safe to jump on i'm jumping on it, if not(planet collision) i'm just standing and waiting when jumpToPos will became safe again (flew from planet)

here's example (Mad skillz included):

http://cs606417.vk.me/v606417952/233/0gbu0C0el_E.jpg

where jumpToPos is A, then B, thec C....

When the vessel is at point C, next jumpToPos will be D and the raycast with length CD will say vessel to keep on C.

On the next step raycast from D to E won't find collision but E belongs to sphere and the vessel will keep on C too.

Same for the F point.

At the end vessel will jump to G and everything will be ok.

Just show a dark screen while vessel is holding on C :)

Zoomed:

http://cs606417.vk.me/v606417952/23a/lEeoxjlqoyI.jpg

But!!!

if more than one jumpToPos points will be below surface but above sea level there's will be a problem:

http://cs606417.vk.me/v606417952/241/y6ELhGnPUAs.jpg

step 1: vessel on A, jumpToPos = B, B is safe(no collision) => jumping to B

step 2: vessel on B, jumpToPos = C, C isn't safe(raycast detected hit), keep vessel on B

step 3: vessel on B, JumpToPos = D, D is safe! No raycast hit, not belongs to sphere(red area), jumping to D and exploding!

So i need a 3rd check:

if(lastColAlt>vessel.altitude)
{
isSafeToJump = false;
}

where

lastColAlt = FlightGlobals.getAltitudeAtPos(headHit.barycentricCoordinate); //from last raycast hit with surface

to determine if the vessel is under surface

Full code:

private void Jump(double destination)
{
bool isSafeToJump = true;

if (Physics.Raycast(jumpToPos, TS.TargetVector, out headHit, (float)(destination + 50.0), 1 << 15)) //is any collision on the way to next jump point. Do it before calculating new jumpToPos value
{
lastColAlt = FlightGlobals.getAltitudeAtPos(headHit.barycentricCoordinate);
isSafeToJump = false;
}
if (lastColAlt > vessel.altitude) // if under surface
{
isSafeToJump = false;
}


jumpToPos = vessel.transform.position + (TS.TargetVector * destination); // calculate next jump point


if ((Math.Pow((jumpToPos.x - vessel.mainBody.transform.position.x), 2) + Math.Pow((jumpToPos.y - vessel.mainBody.transform.position.y), 2) + Math.Pow((jumpToPos.z - vessel.mainBody.transform.position.z), 2)) <= Math.Pow(vessel.mainBody.Radius + 5, 2)) // is next jump point belongs to planet(sphere only)
{
isSafeToJump = false;
lastColAlt = 0.0; //drop value
}

///Jump or not

if(isSafeToJump)
{
lastSafePos = vessel.transform.position;
lastColAlt = 0.0;

vessel.SetPosition(jumpToPos);
}
else
{
vessel.SetPosition(lastSafePos);
print("ABORT!");
}

Now i have brilliant monkey code which works every 2nd time.

So...

Is there any way to check collision at point (like i can check altitude FlightGlobals.getAltitudeAtPos())?

Or any ideas?!

Or how can i disable collision at all?

vessel.GoOnRails() can't solve this problem.

vessel.collider retutrns null ref exception, looping from every part of the vessel and disabling collider has no effect, Physics.IgnoreCollision - nothing too.

Thank you for your answers!

P.S.

bounus-proof of concept:

Laythe:

http://cs606417.vk.me/v606417952/25e/fXJFYej8JNw.jpg

Warping to Ike:

http://cs606417.vk.me/v606417952/267/PuLh06mXfus.jpg

http://cs606417.vk.me/v606417952/270/iKDjSq3pW5c.jpg

You could solve this by adding "fudge physics" with something along the lines of "gravitational effects cause warp to slow down or malfunction" so that once you have x ammount of gravity, warp stops. Much like how timewarp currently works.

Link to comment
Share on other sites

You could solve this by adding "fudge physics" with something along the lines of "gravitational effects cause warp to slow down or malfunction" so that once you have x ammount of gravity, warp stops. Much like how timewarp currently works.

Thank you, but if i understood you right this solution will be equals to "stop warp if vessel below constant altitude at sea level". I can just increase "sphere" where warp stops like: vessel.mainBody.Radius + 10000, so warp will brake under 10km (altitude at sea level).

And are you shure that time warp works simmilar to your answer?

I see in documentation that every CelestialBodiy object has their own set of altitude limits for maximum time warp multiper.

This is not actually i'm looking for.

For example - i wanna warp from KSC's runway to the Mun which is behind those mountains on the west side, so minimum warp altitude at KSC will be ~100 meters and in mountains it should be several thousands. I can't set constant "x" for all planet.

Edited by EvilKot
Link to comment
Share on other sites

At this moment i'll use temporary solution - simply force to sleep all Rigidbodys:

Rigidbody[] rbs = (Rigidbody[])FindObjectsOfType(typeof(Rigidbody));

and OnFixedUpdate() :

foreach (var rb in rbs)
{
rb.Sleep();
}

This completely disables physics and collisions, so it may be helpful to anyone who looking for this.

I just not sure if this is a best way...

----------

Finally slove this problem, so how to "Determine collision at point":

CelestialBody.pqsController.GetSurfaceHeight(Vector3d radialVector) gives us a terrain altitude at some point.

According to mechJeb & HyperEdit:

Vector3d radialVector =  ( QuaternionD.AngleAxis(Longitude, Vector3d.down) *
QuaternionD.AngleAxis(Latitude, Vector3d.forward) * Vector3d.right),

where:

double Longitude = vessel.mainBody.GetLongitude(point);
double Latitude = vessel.mainBody.GetLatitude(point);

and:

Vector3d point - some coords in world coord system.

Finally:

Vector3d point;  //coords (vessel or anything else)
double Longitude = vessel.mainBody.GetLongitude(point);
double Latitude = vessel.mainBody.GetLatitude(point);

double srfHeight = vessel.mainBody.pqsController.GetSurfaceHeight(
QuaternionD.AngleAxis(Longitude, Vector3d.down) *
QuaternionD.AngleAxis(Latitude, Vector3d.forward) * Vector3d.right) -
vessel.mainBody.pqsController.radius; //surface height, shows negative values if under sea level

double alt = (Vector3d.Distance(vessel.mainBody.transform.position, point) - vessel.mainBody.Radius); //altitude, shows negative values if under sea level too

and if

srfHeight > alt

anything located on "point" will explode.

Just note that pqsController of Sun = null!

Edited by EvilKot
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...