Real time Physics based mesh deformation

Hi!
I wanna deform my car when it crashes in wall, falls from sky or gets hit by another car in BGE, but I don’t have any idea how to do it(OK, replace mesh on high impact, but it will not be as accurate as I want it to be). What I wanna get is something similar to Next Car Game(maybe not so crazy effect, but still accurate). I want it to test collision point and impact and than deform basing on it. Replace mesh would just not be accurate or would destroy the FPS/load time as it would require to have a lot of objects holding meshes in other layers. Is there a way to deform car surface with python/shaders? And, even more - is it possible to paint textures(paint scrathces, dirt etc.) real time on surface?

With python you can and even with logic bricks! It depends on how you build your car and it’s deformation system.
If you build your car’s body parts separately, you can make 4 meshes to replace them, 2 for frontal impact and another for side impact. Now make sure the car has collision zones and the car speed is calculated and added to the collider’s speed, to determine if its a strong impact or a weak (e.i.: If too strong make that part be reaped from the car, by replicng the object with a rigid one.)

Dnt’ know if it’s understandable. But you might be able to do a lot as long as you can design systems.

I more mean like vertex manipulations - if car collides something with high impact, it’s vertices gets moved oppositly to it’s movement direction and only the vertices that are located in the collision point.

Hey, check out my artillery duel game here, it contains some (very simple) ground deformation in case a cannon ball falls onto the ground… http://www.blenderartists.org/forum/showthread.php?287899-WIP-Small-Artillery-Duel-game

Well, my CPU is 4x stronger than GPU, tested in rendering. So, I guess, for me the real time mesh deformation would be faster with CPU.
However, what method do you use, scorpion - could you post a tutorial?

what about manipulating bones in a armature on impact?

like a grid of bones?

Well, you could just check “groundimpact.py” inside the blend i linked over there in my thread…

Edit: added link here too

Thats the snippet basically, i just detect which vertex is closest to the impact location and move it down (in negative Z direction) by 0.1 blender units, so to say just in fixed steps.


for m_index in range(len(mesh.materials)):
    for v_index in range(mesh.getVertexArrayLength(m_index)):
         vertex = mesh.getVertex(m_index, v_index)
         pos = Vector(vertex.XYZ) * cont.owner.worldTransform
         if coll == None:
             break
        # print(pos, coll.worldPosition)
         if (abs(coll.worldPosition[0] - pos[0]) < 1):
             vertex.z -= 0.1
         #    print(vertex.z)

I took the material / vertexarray iteration scheme from here…
http://www.blender.org/api/blender_python_api_2_75_1/bge.types.KX_MeshProxy.html?highlight=bge%20mesh#bge.types.KX_MeshProxy

That’s for cycles rendering, not open gl. They’re different algorithms, not really comparable.

Also, if your CPU is 100X “better”, but doing all the work, offloading to the GPU will make the application faster.

How “accurate” can such a deformation be? I think you can’t even tell how a real car deforms (unless you are a crash test engineer).

So I think it is very valid to detect areas where a collision happened and do some preset object/mesh replacements there. The advantage is that you get the according materials with it.

To increase the variations you could move the vertices too. Shape keys might do the trick in a more artistic way.

Technically you can surround the car with sensor objects to detect where the collision is.

I am more looking for most efficient way in FPS. I have a low GPU, as you know, and the scene currently runs 20 FPS in 720p when car is close to camera and 30 FPS(for some reason - constant and locked FPS) when car is far from camera. I need to keep the stable framerate, but have the destruction effect. Also, I would like to use particles, but the addon doesn’t work on 2.75 as the frequency of ‘Always’ sensors was replaced to skippedTicks and changing the wrong value in addon script that pops in error doesn’t fix anything(using skippedTicks attribute doesn’t work in the addon anyway).

Hmmmm… my post was about KX_MeshProxy material / vertex iteration scheme… whats the relation to cycles ? Or did you maybe just quote the wrong post ? :slight_smile:

scorpion81, could you explain step by step:

  • How to test if vertex is colliding object or how to get vertex distance to the closest vertice of any other object(the closest vertice that is not in the same object/mesh). I need just one of theese methods, best - the one with highes performance. Note that I use triangle mesh collision for my car.
  • I already am getting car speed so vertex movement will be multiplied by car speed / car max speed or something like that.
  • How do I get car movement direction?
  • How do I move a vertice of car in inverted car direction by this value: 1.0 * carSpeed / carMaxSpeed(both are properties of car).

Thanks for advice! :slight_smile:

Hmm, do you have maybe a blend of your planned car game ? I could take a look in it… Its a bit hard (for me) to give good advice off-hand… and you could come back to #bgecoders maybe, its faster to help / communicate via IRC…

  1. you can get the position of the colliding object like this…


# get current controller and collision sensor as well as the object hit by the object with the collision sensor
# (might be None as well, need to test later)
cont = bge.logic.getCurrentController()
coll = cont.sensors['Collision'].hitObject

# get the mesh (first one should be the correct one)
mesh = cont.owner.meshes[0]

# iterate over the vertex array of each material of the mesh...
# so with material index and vertex index you can grab the vertex (its a KX_VertexProxy)
# from the mesh (which is a KX_MeshProxy)
# note, for large meshes as we iterate over all verts, this might become slow :( But we need to find the closest ones
 # somehow

for m_index in range(len(mesh.materials)):
    for v_index in range(mesh.getVertexArrayLength(m_index)):
         vertex = mesh.getVertex(m_index, v_index)

         # multiply the vertex coords with the world matrix
         pos = Vector(vertex.XYZ) * cont.owner.worldTransform

         # just test for existence of collision object, note, this can be done even before the loop
         # to avoid unnecessary computation, here we just break from the loop 
         if coll == None:
             break
        # print(pos, coll.worldPosition)

         # here the important step:
         # if world position of vertex and world position of collision object is closer than a distance, move 
         # the vertex
         # note, here we use 1 as distance and just look at the x coordinates of the positions because we are interested in    
         # the distance in x direction only, for a more general case you might use getDistanceTo() method from  
         # KX_GameObject with a position vector as argument, abs is the absolute value
         if (abs(coll.worldPosition[0] - pos[0]) < 1):
  
             #then the closest vertex is moved by -0.1 in z direction
             vertex.z -= 0.1
         #    print(vertex.z)

For the car game specific questions i think i would need to look into your blend first :slight_smile:

Edit: 2) for car movement direction you could use worldLinearVelocity (or localLinearVelocity, not sure)
as this is a vector, its not just the speed but the direction of movement also.
http://www.blender.org/api/blender_python_api_2_75_1/bge.types.KX_GameObject.html?highlight=linear#bge.types.KX_GameObject.localLinearVelocity

  1. inverting the vector is easy, just negate the component values.

You must multiply the transforms the other way around

At the moment you can’t really get this information from the collision sensor API.

But, with Blender 2.74 the collision callbacks provide the first contact point (http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.74/BGE)

I see a lot of problems doing it the “hard” way!

  1. You’ll have to calculate material resistance and elasticity. This will make the car behave less like a sheet of air.
  2. You’ll have to add impact absortion throught the entire car. That will make the other parts being affected by the impact and stop/deviate the car instead of completely destroying it. Chassis tension, elasticity and resistance must be included too.
  3. The car will be colliding with another car, which might have the same or different properties. And if it’s a wall, or road guard or any other obstacle, it might have to deform as well.
  4. Visually, the vertices will have to account for colliding vertices position changes. As the car collides with a surface, it deforms the colliding surface as well, the deformation algorithm will have to be fetching the new positions, and or anticipate new positions. The mesh is built in a way that it has more chances of deforming a certain way.
  5. Normals will have to be recalculated as well or the deformation wont be visible!
  6. Then add the effect of the deformation on the car, you’ll just have to recalculate the physics mesh.

The easy way:
Fake it: A car part can deform a very few ways : bends from the side or front. Some parts can only bend in front.
As you can have many parts on the car, multiple levels of easy deformation on the car might even look better than hard way ones.
Besides, it could run in various environments without too many errors,or unrealistic end results!

If realtime physical maerials are created for the BGE, then we’ll all be happy. Try playing with soft bodies to have an idea of the framerates you get with physical calculations.

I don’t know if I am being ignored or why this is a bad idea:

It uses two instances, meaning two cores and no ms lost in game.
You can use any bpy modelling tools. Instead of cutting , deform.
If I can create a whole 646464 cube world with shading (and physics) during game play, a car shouldnt be that hard.

Downsides are a little delay for libload and replace mesh
and that blender would have to be installed.