Announcement

Collapse
No announcement yet.

[PHYSICS] Center of mass needs a rework

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [BLUEPRINT] [PHYSICS] Center of mass needs a rework

    I have two major criticisms to say : Why do we set an offset to the calculated center of mass and not directly the center of mass ?
    Why is GetCenterOfMass relative to the parent component ? In my opinion, it should be relative to the origin of the component.

    Please change it, it's counter intuitive and written nowhere.

    EDIT : GetCenterOfMass is in world space.
    Last edited by Moddingear; 08-23-2017, 09:04 AM.

    #2
    GetCenterOfMass is in world space as far as I know.
    Youtube Channel

    Comment


      #3
      Originally posted by BoredEngineer View Post
      GetCenterOfMass is in world space as far as I know.
      It's still a weird choice.
      Last edited by Moddingear; 08-21-2017, 07:19 AM.

      Comment


        #4
        Not sure what you mean by "I tried with World Space" - there is no choice. Component needs to simulate physics to return non-zero COM and if it's a part of welded body then COM of a complete welded body is returned.
        Youtube Channel

        Comment


          #5
          Components physics are not even replicated, only the parent actor can be replicated so, not sure what are you doing but probably its another note to take in account.
          Hevedy - Instance Tools: https://hevedy.itch.io/hevedyinstances
          Hevedy - Image Tools: https://hevedy.itch.io/imagetools

          Comment


            #6
            Originally posted by Hevedy View Post
            Components physics are not even replicated, only the parent actor can be replicated so, not sure what are you doing but probably its another note to take in account.
            That's another problem, but that is feasible.

            Originally posted by BoredEngineer View Post
            Not sure what you mean by "I tried with World Space" - there is no choice. Component needs to simulate physics to return non-zero COM and if it's a part of welded body then COM of a complete welded body is returned.
            In my testings, the center of mass is not relative to the origin of the component which is being simulated, and don't worry, I am simulating it.

            The point is that we need to get the COM that is in world space (as you say), then transform it in local space, then use your wanted COM - that to set the wanted center of mass that is in local space.
            Last edited by Moddingear; 08-21-2017, 10:28 AM.

            Comment


              #7
              Originally posted by Moddingear View Post

              In my testings, the center of mass is not relative to the origin of the component which is being simulated, and don't worry, I am simulating it.

              The point is that we need to get the COM that is in world space (as you say), then transform it in local space, then use your wanted COM - that to set the wanted center of mass that is in local space.
              As you keep mentioning relative vs local coordinate I assume that you are trying to set center of mass on a child component. But the thing is, if you are simulating it then it's not connected to its parent and there is no reason for COM to be relative to anything. If you are not simulating it then child component is welded to its parent and the top of the hierarchy defines the origin in basis of which COM is set. Technically its not even like that as there are separate "physics bodies" created and components have pointers to them. So multiple welded components are in fact a single physics body (afaik).
              Another thing is that there is no way to set center of mass without making a custom c++ function that changes it on physics body level. Default nodes/functions set only an offset of COM, which is calculated when you add collision body to the object.

              Anyway, there might be a bug in the code introduced by one of the engine updates. Can you list steps to re-produce this issue?
              Youtube Channel

              Comment


                #8
                Originally posted by BoredEngineer View Post
                As you keep mentioning relative vs local coordinate I assume that you are trying to set center of mass on a child component. But the thing is, if you are simulating it then it's not connected to its parent and there is no reason for COM to be relative to anything. If you are not simulating it then child component is welded to its parent and the top of the hierarchy defines the origin in basis of which COM is set. Technically its not even like that as there are separate "physics bodies" created and components have pointers to them. So multiple welded components are in fact a single physics body (afaik).
                Another thing is that there is no way to set center of mass without making a custom c++ function that changes it on physics body level. Default nodes/functions set only an offset of COM, which is calculated when you add collision body to the object.

                Anyway, there might be a bug in the code introduced by one of the engine updates. Can you list steps to re-produce this issue?
                I don't think there is a bug, I might just be confused by my actor between World Transform and Relative Transform. I actually just tested that, and it is indeed world space.
                I am indeed trying to set the center of mass on a child RuntimeMeshComponent being simulated.
                The COM could be relative to the origin of the component, such as if the component was a mesh, setting the COM somewhere would use the same coordinate system as the mesh's. Since all welded components are child of this component, they would only have to get the center of mass relative to the simulating component, so I see why the COM is returned in world space.

                BUT, and that is why I'm complaining, the COM is only being set using an offset as you mentioned, and doesn't override the default COM, meaning that at any change of the geometry, the COM is being recalculated which adds a lot of overhead for nothing.

                The solution that I am proposing is that GetCenterOfMass stays the same, but that SetCenterOfMass gets a OverrideCOM just like Mass does, in such that it doesn't rely on the calculated PhysX COM.

                And, I really appreciate you responding to my criticisms.

                Comment


                  #9
                  Originally posted by Moddingear View Post
                  I don't think there is a bug, I might just be confused by my actor between World Transform and Relative Transform. I actually just tested that, and it is indeed world space.
                  I am indeed trying to set the center of mass on a child RuntimeMeshComponent being simulated.
                  The COM could be relative to the origin of the component, such as if the component was a mesh, setting the COM somewhere would use the same coordinate system as the mesh's. Since all welded components are child of this component, they would only have to get the center of mass relative to the simulating component, so I see why the COM is returned in world space.

                  BUT, and that is why I'm complaining, the COM is only being set using an offset as you mentioned, and doesn't override the default COM, meaning that at any change of the geometry, the COM is being recalculated which adds a lot of overhead for nothing.

                  The solution that I am proposing is that GetCenterOfMass stays the same, but that SetCenterOfMass gets a OverrideCOM just like Mass does, in such that it doesn't rely on the calculated PhysX COM.

                  And, I really appreciate you responding to my criticisms.
                  I hear you. Yeah, agree with that, would be very useful option to set COM directly. I'm not sure why devs added offset instead of override, perhaps something related to how code is structured or how it's fed to PhysX. Don't know exactly.

                  If you are in dire need of such change, this is the code for c++ function to set InertiaTensor:
                  Code:
                  void UMMTBPFunctionLibrary::MMTSetInertiaTensor(UPrimitiveComponent * Target, const FVector& InertiaTensor)
                  {
                  	FBodyInstance* BodyInstance = GetBodyInstance(Target);
                  	if (BodyInstance != NULL) {
                  
                  		PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked();
                  
                  		if (PRigidBody != NULL) {
                  
                  			PRigidBody->setMassSpaceInertiaTensor(U2PVector(InertiaTensor));
                  		}
                  	}
                  }
                  For center of mass you can replace "PRigidBody->setMassSpaceInertiaTensor(U2PVector(InertiaTensor));" with this line:
                  PRigidBody->setCMassLocalPose( [NewCenterOfMassTransform] );

                  Transform here is not FTransform but PxTransform of Physx. Haven't tested it but should work.
                  Youtube Channel

                  Comment


                    #10
                    Originally posted by BoredEngineer View Post
                    I hear you. Yeah, agree with that, would be very useful option to set COM directly. I'm not sure why devs added offset instead of override, perhaps something related to how code is structured or how it's fed to PhysX. Don't know exactly.

                    If you are in dire need of such change, this is the code for c++ function to set InertiaTensor:
                    Code:
                    void UMMTBPFunctionLibrary::MMTSetInertiaTensor(UPrimitiveComponent * Target, const FVector& InertiaTensor)
                    {
                    	FBodyInstance* BodyInstance = GetBodyInstance(Target);
                    	if (BodyInstance != NULL) {
                    
                    		PxRigidBody* PRigidBody = BodyInstance->GetPxRigidBody_AssumesLocked();
                    
                    		if (PRigidBody != NULL) {
                    
                    			PRigidBody->setMassSpaceInertiaTensor(U2PVector(InertiaTensor));
                    		}
                    	}
                    }
                    For center of mass you can replace "PRigidBody->setMassSpaceInertiaTensor(U2PVector(InertiaTensor));" with this line:
                    PRigidBody->setCMassLocalPose( [NewCenterOfMassTransform] );

                    Transform here is not FTransform but PxTransform of Physx. Haven't tested it but should work.
                    Can't I just disable PhysX-calculated COM to make it so that the offset is always what I want ? If it's always disabled, it should do just fine.

                    Comment


                      #11
                      Actually, I know why I was getting weird results : You can't get the center of mass of an object for which you just set the collision, it returns (0;0;0). So, the physics engine just comes after you set you collision offset and screws it up by setting the PhysX offset.

                      Comment

                      Working...
                      X