Design More Physics

Anthodeus

Member
Contributor
Hey there guys,

While thinking of some ideas for implementing combat-related issues, I have come across numerous problems regarding collisions.

Initially discussed in this issue, I've been revolving around the idea of how to make collisions help development rather than limit it. Thus, I wanted some input and feedback on the ideas I presented there, which I'm also going to compress into a more readable structure here.

First of all, I wanted to talk about item collisions. There are no events sent when items interact with the world, making it pretty hard to implement stuff like StickyTorches, Arrows (that can embed into walls), certain types of interactions with certain blocks (like in the issue, any item and lava) or the general issue of tunneling.

A quick way of fixing this issue would be my option of adding a bit of code to the physics engine, and raytracing items that have certain components (so that we don't calculate raytraces for everything that dropped from... say... an explosion... or multiple of them *cough* railgun *cough*).

"HitResult hitResult = physics.rayTrace(location,comp.velocity.normalize(),comp.velocity.length()*delta, StandardCollisionGroup.LIQUID);
if (hitResult.isHit() == true) {
if (entity.hasComponent(SpecialComponent.class)) {
entity.send(new SpecialEvent());​
}​
}"

This of course manages collisions with the first item of the type it manages that it encounters in the direction of movement in the next frame. This of course is really specific, and we wouldn't want something that specific in a physics engine which should be capable of being used for pretty much any type of interaction we'd want.

As I've specified in the issue, I would like to know if it's possible for us to have a raytrace that is just distance based (instead of distance and collision group that is) that return all entities it encountered, so that we can interrogate that entity list for whatever items we are looking for at the moment. (For example, something falling straight down into water with a longer raytrace would return all the air blocks to the water, the water and the blocks beneath the water for as far as the raytrace goes).

As for the tunneling issue, we could stop really fast items from clipping through the ground by placing them just above (either stopping them or making them somehow get affected by the collision; whichever works best).

Item on item collisions I imagine would be a bit different from world collisions, as their rigidbodies would be the ones interacting rather than a directional velocity. I haven't gone deep into these but I'd love to hear some ideas on it :fluttersquee:

One more thing to add is that I found out raycast != raytrace != raymarch. From what sources I gathered raycasting would be the best use case for the issue at hand, while raymarching would prove inexact for several edge scenarios ( albeit most efficient! ), and raytracing sounded like the heaviest type by sending secondary rays with every hit (mostly used for rendering)

Pinging @Josharias and @Flo for some discussion on this subject.
 
Last edited:

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
I'd love to see some more engine support here since it seems a worthwhile thing to implement well in a central location probably with some extra power to optimize performance.

Am curious if @Immortius might weigh in with some thoughts on the very original physics implementation, or the first round after what @begla hooked us up with anyway. I am figuring we might just have had a limited implementation as it was all we needed at the time? Probably mixed in with some performance concerns since that has been tricky with physics over time. What would a more complete set of events or physics-related components look like?

One example I threw in the issue was what if you dropped a lava block on top of a loose TNT block? Or even a regular TNT block. We could deal with placing lava + TNT adjacent and reacting to it at present, but I suspect we need more engine support (or too technical stuff happening in a module) to make something like that work. Yet it seems like it could be used for all kinds of cool stuff :)

Also just to throw in another link https://github.com/MovingBlocks/Terasology/issues/2139 is the one that talks about easily being able to throw stuff through blocks.
 

Josharias

Conjurer of Grimoires
Contributor
World
SpecOps
Just a quick thought that the physics engine should already be seeing collisions for these entities in the world. I know for the world collisions, it is just missing firing events for those two different types of physics objects. I would imagine there is something simple to get entity-entity collision events happening correctly as well.

Sometime I will have to revive and finish off the initial research I did on this here (unless you want to run with it @Anthodeus)
 

Anthodeus

Member
Contributor
@Josharias I still have that initial research you did opened in a tab from last we spoke about the same type of subject ( at the time trying to implement sticky torches ).

If just the firing of events is missing for collisions, I'm thinking that these events can be the ones that return the object they collide with and all the neat info about the collision (like normal, material (for sound reasons; not sure if this exists yet), velocity) . As entities do not clip through each other, I think they should work with this as well. Of course, the addition of the "hasComponent" rule for it to send out events should still be in order in my opinion. Also, I'm not exactly sure if these events would be sent out while items are not moving or just when impacting with a certain speed, but I guess that would be adjustable by implementation.

Even so, a raycast returning all entities within its reach would be plenty helpful for the reasons stated above, even if not directly for item collisions.
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
Bullet (and thus jBullet) does have support for detecting collisions between non-kinematic physics bodies and other physics bodies by contact manifolds (basically collision points) as described here, which is a little convoluted to set up but I think would cover these use cases - you would send some sort of BumpEvent to each involved non-kinematic physics entity I think. You could then filter by component as per any event. Once arrows/etc are receiving bump events the rest should be easy.

"HitResult hitResult = physics.rayTrace(location,comp.velocity.normalize(),comp.velocity.length()*delta, StandardCollisionGroup.LIQUID);
if (hitResult.isHit() == true) {
if (entity.hasComponent(SpecialComponent.class)) {
entity.send(new SpecialEvent());​
}​
}"
You shouldn't check components before sending events. The event system already allows event receivers to filter by components. Then mods can add receivers on other components if desired.

As I've specified in the issue, I would like to know if it's possible for us to have a raytrace that is just distance based (instead of distance and collision group that is) that return all entities it encountered, so that we can interrogate that entity list for whatever items we are looking for at the moment. (For example, something falling straight down into water with a longer raytrace would return all the air blocks to the water, the water and the blocks beneath the water for as far as the raytrace goes).
I believe you just do a ray trace using the "all" group (I think that exists?). That aside, you can only ray trace things that have a physics presence.

For blocks you don't really need to use the collision system at all of course, just trace through the block grid (I recall there were some classes to aid with that).
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
Immortius said:
You shouldn't check components before sending events. The event system already allows event receivers to filter by components. Then mods can add receivers on other components if desired.
I think this was more a thought to help performance up front before sending excessive events that nobody may care to catch? Unless we want absolutely everything dropped to qualify. I'm not sure which would be a bigger hit to performance. I understood it as a sort of "If you want your object to have some extra physics interactions, attach the ExtraPhysicsComponent"

I'm not sure if we'd need such considerations though, if we can survive just enabling everything (maybe with some throttling so two objects stuck rubbing up against each other wouldn't send a hundred events per second)
 

Anthodeus

Member
Contributor
Immortius said:
Bullet (and thus jBullet) does have support for detecting collisions between non-kinematic physics bodies and other physics bodies by contact manifolds (basically collision points) as described here, which is a little convoluted to set up but I think would cover these use cases - you would send some sort of BumpEvent to each involved non-kinematic physics entity I think. You could then filter by component as per any event. Once arrows/etc are receiving bump events the rest should be easy.
@Immortius I will look through the article you linked to see how to do these bump events.

As @Cervator said, the checking of components is done to save us from a flood of events, and if put before the raytrace could even save some calculation time (which it certainly should be now that I think about it)

Immortius said:
I believe you just do a ray trace using the "all" group (I think that exists?). That aside, you can only ray trace things that have a physics presence.
The way I remember it the "all" collision group does indeed exist and you're right, we could just use a raytrace with it, but the issue still would be returning all the entities (a whole list of stuff encountered). There's the option of raytracing up to an entity, then adding a new raytrace from that point and adding that entity to the ignore list. I'm not exactly sure I understand what "a physical presence" means. Don't all loaded blocks have that? (they might not have their sides rendered is all I can think about regarding that)

Immortius said:
For blocks you don't really need to use the collision system at all of course, just trace through the block grid (I recall there were some classes to aid with that).
I'm not exactly sure what the block grid is; deducing would make me think that just running a 3D line from 1 point to another could determine what position blocks it passes through, so I can just return all of them directly. I'll be looking into this and also searching for these possible classes.

Another thing I thought about in the meantime, if checking the existance of the component before the raytrace is in order, to put up a "collision timer" of sort, so events don't fire off every moment between two items with this component that touch (sort of what @Cervator mentioned, again)
 

Immortius

Lead Software Architect
Contributor
Architecture
GUI
I'm not exactly sure what the block grid is; deducing would make me think that just running a 3D line from 1 point to another could determine what position blocks it passes through, so I can just return all of them directly. I'll be looking into this and also searching for these possible classes.
That is what I had in mind. The math to do that is reasonably simple - just need to worry about the (literal) edge cases, such as a trace going along the grid itself.
 

Michael

Moderator
Contributor
Architecture
I've been reworking the rails module to take advantage of a Bezier curve. My main problem is that I treat the position of the cart as a function of t and update the position accordingly. This does not quite translate well to bullet in the sense that I can't quite update the velocity to fit the curve and at some point due to how much it starts to deviate from the curve. What i want to do instead is respond to CollideEvents, but that only works as far as returning the other entity. Bullet lets you collect the contact points of the two objects and the associated impulses that are imparted. Not sure what could be worked out, but re-wrapping everything into the event seems expensive. I'm a bit stumped with how to proceed with this module at this point.


https://github.com/Terasology/Rails/tree/reworking-tracks

Not sure what could be worked out in terms of opening up more features for physics. Could a Road map be worked out in terms of what features would be of interest and how this would work into the physics system.
 

Anthodeus

Member
Contributor
Heyo,

I'll be looking into the rails module shortly, but I do have to ask what types of collisions you have in mind? Would they be the rigidbody types where it returns a point on the mesh with a normal or just a raytrace from a central point of the object that does somewhat of the same thing without the mesh implications (would be less accurate visually, less detection area but essentially the same functionality).

From what I remember bullet is used to manage high velocity impacts where items or objects could avoid collisions altogether by going to fast to detect each other. I'm not sure if we specifically need an implementation from there, but it's a possibility.

As for types of collisions, what do you have in mind? There are quite a few ways to define the interactions like:
  • plastic / elastic collisions -> issues what happens to each of the items that participate in the collision after the matter. Plastic = all momentum is tranferred, elastic = both items will keep moving after said collision (this could depend on the material the item is made of [I forgot if we have materials for blocks/items] and the mass [which, again...] )
  • impacts -> collisions between items could cause damage to the health components, depending on the mass/materials
  • limitations -> you select what types of entities you can collide with; maybe you want players to take damage from being hit by carts? you want blocks to maybe be destroyed if the cart smashed into it with enough speed if it's not a soft material?
 

Michael

Moderator
Contributor
Architecture
I think it just returns the impulses required to separate two bodies. Not sure exactly what i'm going to do but i need to figure out something to deal with carts colliding. From my understanding it returns a manifold with the points of contact and an impulse vector. I would need to do more research to understand this, since I only have a basic understanding of bullet.
 

Anthodeus

Member
Contributor
Well, conceptually speaking for now, what would be the preferred way a collision would happen in your eyes? Add any ideas, we're not talking code for the moment, just whatever goes through your head regarding the outcome of a collision. From there we can do a MoSCoW assessment of the issue and see where we can go from there :D
 

Michael

Moderator
Contributor
Architecture
Code:
   @ReceiveEvent(components = {RailVehicleComponent.class, LocationComponent.class,RigidBodyComponent.class}, priority = EventPriority.PRIORITY_HIGH)
    public void onBump(CollideEvent event, EntityRef entity) {
        RailVehicleComponent railVehicle = entity.getComponent(RailVehicleComponent.class);
        RailVehicleComponent otherRailVehicle = event.getOtherEntity().getComponent(RailVehicleComponent.class);

        RigidBodyComponent cartRigidBody = entity.getComponent(RigidBodyComponent.class);
        RigidBodyComponent otherCartRigidBody = event.getOtherEntity().getComponent(RigidBodyComponent.class);

        if (railVehicle == null) {
            return;
        }

        if (railVehicle.characterInsideCart != null && railVehicle.characterInsideCart.equals(event.getOtherEntity())) {
            return;
        }

//add correct collision code here

        entity.saveComponent(railVehicle);
        event.getOtherEntity().saveComponent(otherRailVehicle);
    }
The idea is the collideEvent should modify the velocity of the cart and prevent them from passing through each other. CollideEvent only returns the other entity that the object is colliding with. It would be of more use if it could also provide the impulses that separate the two bodies.
 

Anthodeus

Member
Contributor
Ok, so you want only rail entities (for now only carts) to collide in a plastic way by means of rigidbody from the way I get it. No health would be affected anywhere. We could use a fix that @Josharias had done and I saved somewhere (where collisions between entities would return an event (instead of only entities with world). From there, the movement could be affected in the onBump method you have here.

For the sake of trying it out, without implementing collisions, do you think you can add a commandline activated event where you bring all carts to a standstill? Afterwards, maybe reversing the current movement direction could do, and then just adding these to another event should be fairly easy
 
Last edited:

Michael

Moderator
Contributor
Architecture
So I've got the carts to both stop when they collide but i'm not sure what you mean by commandline activate. I'm assuming there is some event for the commandline but you can just place the cart on an incline and it will roll down.
 

Cervator

Org Co-Founder & Project Lead
Contributor
Design
Logistics
SpecOps
By command line activate I suspect is meant to build a command you can run in the game console that'll reset or otherwise interact with impulses and such. May help with debugging.
 

Anthodeus

Member
Contributor
@Michael Is there anything else needed then? It seems like you have things covered as is, without need for other implementation. I'm curious how you got them to detect each-other though :rainbowhuh:
 

Michael

Moderator
Contributor
Architecture
The carts just stop when the collide. I've been stuck trying to get them to rebound off of each other. I was curious if more could be exposed for the onbump function to work with. The onbump event is called any beyond that I don't really have anything to handle the response when they collide. You might have a better idea then me. I have a link to what i have so far in terms of the CartMotionSystem.

https://github.com/Terasology/Rails/blob/reworking-tracks/src/main/java/org/terasology/rails/minecarts/controllers/CartMotionSystem.java
 

Anthodeus

Member
Contributor
From what I could see here, on the moment of collision you carts do have a velocity that's tangent to the rails, so you could just normalize that and use it however you'd like in the onBump instead of replacing with a new Vector3f (like, multiplying the current one with any factor between {-1,0} to have a reduced speed backward movement on the moment of collision, or lower than -1 for quite an improved recoil (although I'm not certain what limitation the speed of the cart could have; I do imagine it's limited to something.

What I mean is something along the lines of replacing

if(otherRailVehicle != null) {
railVehicle.velocity = new Vector3f();
otherRailVehicle.velocity = new Vector3f();
event.getOtherEntity().saveComponent(otherRailVehicle);
entity.saveComponent(railVehicle);
}

with

//float factor = {0,1};
if(otherRailVehicle != null) {
railVehicle.velocity = railVehicle.velocity.normalize() * factor;
otherRailVehicle.velocity = otherRailVehicle.velocity.normalize() * factor;
event.getOtherEntity().saveComponent(otherRailVehicle);
entity.saveComponent(railVehicle);
}

The factor calculation would be the only thing that's relevant anymore, and that's done by the stuff that i asked earlier ( materials, percentage of max speed, ect. ). This would be the equivalent of an impulse seeing as onBumb is only activated once and when the velocities are towards one-other (at least I assume that part)

Would any of what I said be relevant/helpful? I'm all ears for either case :flutteryay:
 

Skaldarnar

Development Lead
Contributor
Art
World
SpecOps
I've got one question about the way systems should modify entities. In the code snippet above you save the component for both entities, the one the event is sent to and the one it collides with. In theory, I think only one entity shuld be changed by the event - I guess the event is sent twice, once for "A collides with B" and "B collides with A"? What are possible drawbacks of such "synchronized events" and how can conflicts be solved?

The code proposed by @Anthodeus seems very reasonable to me, although again both cart's velocities are updated at the same time...
 
Top