0
\$\begingroup\$

I have a central point, a planet is moving around it on the orbit A (a circle)

And the planet is rotating at a certain speed on its axis ( B )

Diagram of planet orbiting a star

I have a Data Structure representing the Base Mesh information that is static and calculated around the origin point that is static.

Think:

float3[] pointsList 

Where all the point are calculated around 0,0,0 instead of where the planet is ( it's easier to convert 1 point on a frame rather than a list with thousands of point each frame )

Around that planet, I have a collider to be able to catch raycasts on it. The sphere collider is roughly the size of the mesh so it matches well.

Here is what I need :

How can I convert the point from the raycast back to an "origin" state.

Here is an illustration :

Diagram of rotating planet

From My understanding I would need :

To Revert the rotation on the Axis (A) BUT following the (C) Line along the surface to find the base point as if the mesh did not rotate at all and then Translate the point so it is in the origin referential. (Around 0,0,0 , where the base mesh have been calculated)

Now...what are the maths that I need to do behind the scenes to do that?

TLDR: I am trying to convert a raycast point on the surface of a sphere back to an "origin" kind of point to do stuff behind with it with the base mesh coordinates.

Edit : Adding representation of the planet VS the stored point Array ( please note that A is at 0,0,0 ) :

Points Representation

Here : B is the representation of the points array and is STATIC & A Is the position of the planet with the collider & the mesh created from B's Points, all rotating on it's axis ( cf : Other screenshot )

So how do I "revert" a point from the collider around the mesh to get a point as if the raycast Happened on the A sphere ?

Edit 2 : Result with InvertTransform

        if (!Physics.Raycast(MainCamera.ScreenPointToRay(Input.mousePosition), out hit))
        {
            return;
        }
        RaycastHit hit;
        
        Vector3 localHit = TargetPlanet.transform.InverseTransformPoint(hit.point);
        GameObject rayCastHit = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        rayCastHit.name = "RayCastHit";
        rayCastHit.transform.position = hit.point;
        rayCastHit.transform.localScale = new Vector3(0.025f,0.025f,0.025f);

        GameObject targetLocal = GameObject.CreatePrimitive(PrimitiveType.Sphere);
        targetLocal.name = "TargetLocal";
        targetLocal.transform.position = localHit;
        targetLocal.transform.localScale = new Vector3(0.025f,0.025f,0.025f);
        
        Vector3 planetHit = TargetPlanet.transform.TransformPoint(targetLocal.transform.position);
        GameObject targetPlanet =GameObject.CreatePrimitive(PrimitiveType.Sphere);
        targetPlanet.name = "TargetPlanet";
        targetPlanet.transform.parent = TargetPlanet.transform;
        targetPlanet.transform.position = planetHit;
        targetPlanet.transform.localScale = new Vector3(0.025f,0.025f,0.025f);

Then Clicking on the same point again and again without mooving the mouse give me that :

For the raycast hit :

Raycast Hits

For The TargetLocal : ( On the reference Sphere at origin )

TargetLocal

For The TargetPlanet: ( On the Surface of the planet & the view of the collider )

Surface

Both the hit on the surface & on the reference seems OFF and never hit the same point

Edit 3 : Movement Code :

public float3 EvaluatePlanetOrbit(int planetID, float t)
{
  float angle = t * 360 * Mathf.Deg2Rad;
  float x = math.sin(angle) * Orbits[planetID].XAxis; // Orbits[planetID].XAxis -> Float
  float z = math.cos(angle) * Orbits[planetID].ZAxis; // same

  return new float3(x, 0, z);
}

//That is the code managing the movement of the planet

planetData.OrbitalProgress += time * (1 /planetData.CurrentOrbit) * planetData.OrbitalSpeed;
PlanetGridGameObject.transform.position = EvaluatePlanetOrbit(planetData.PlanetID, planetData.OrbitalProgress);
            
// Rotations
planetData.CurrentAngleRotation += time * GameSettings.RotationPlanetSpeed;
planetData.CurrentAngleRotation %= 360;
           
Quaternion rotationAboutAxis = Quaternion.Euler(0, planetData.CurrentAngleRotation, 0);
Quaternion tiltOfAxis = Quaternion.Euler(0, 0, GameSettings.RotationPlanetAxis);

PlanetGameObject.transform.rotation = (Quaternion) tiltOfAxis * rotationAboutAxis ;
\$\endgroup\$
7
  • \$\begingroup\$ Added the results for invert & all so you can visualise what's happening with it :) That's Why that solution is not working. the point that you get is not consistent even if it's is awfully close ^^ \$\endgroup\$
    – Slater
    Commented May 29, 2022 at 18:30
  • \$\begingroup\$ It's not clear to me what error those images are meant to illustrate. What makes the result "seem off"? \$\endgroup\$
    – DMGregory
    Commented May 29, 2022 at 19:06
  • \$\begingroup\$ Well the raycast hit is apparently not on the surface but offsetted from the surface. for whatever reason. My test show that if I remove the position update ( but keep the rotation ) I get the good point but when I update the poisiton, of the planet the raycast hit is offsetted \$\endgroup\$
    – Slater
    Commented May 29, 2022 at 19:36
  • 1
    \$\begingroup\$ Could this be due to a difference between the position of the Rigidbody as of the last physics step, and the Transform in the current frame? Does calling SyncTransforms before the raycast change anything? \$\endgroup\$
    – DMGregory
    Commented May 29, 2022 at 19:47
  • \$\begingroup\$ Shit , It actually fix the issue. But the thing is both actions take place at the same frame. The movement is done BEFORE any input check is done. Can you elaborate in what situation that can happen ? So I maybe be able to fix the issue at the source. \$\endgroup\$
    – Slater
    Commented May 29, 2022 at 20:08

1 Answer 1

1
\$\begingroup\$

You're moving your planet with its Transform component, but then detecting hits with its Collider component, which is part of the physics system. This separately tracks the position and orientation of colliders within the physics simulation space that's used for collisions and raycasts.

Data is only copied from the Transform into the physics simulation once per physics step. If you move the Transform in Update, the collider is still sitting in the position it was as of the last physics tick.

Calling Physics.SyncTransforms forces the latest Transform changes to be propagated to the physics simulation immediately. Now the collider is where you expect it to be, so the raycast hits the correct point.

After that, you just need Transform.InverseTransformPoint to convert the world space hit point into the planet's local coordinate system.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .