How to animate a sphere surface with random mesh deformation ?

Hello,

(If my problem does not fit with this sub forum, feel free to move it to the right one)

I would like to randomly deform an icosphere surface and animate it. So I will have a “moving surface” sush as a biological cell membrane (which I am trying to model).

I don’t know how to do it. I read som stuff about softbodies but I am not sure it can solve my problem.

One important thing, it’s I dont care about having a real physic simulations, only an “artisitc view” of a biological cell menbrane deformation.

So I tried something with shape keys. I wrote a small python script which create a shape keys every x frame and apply small random vertices translation.

The result is pretty nice but I have two problems with my script:

  1. this solution (one shape key for one frame) seems pretty heavy I think. I am a blender beginner so maybe shape keys are totally shaped to do this…
  2. after many frames, my original cell is totally deformed and it is worst with the time… this is because when I apply small random translation in my script, I apply it (I guess) on the previous shape key and I should apply this random translation on my original non deformed icosphere, but I didnt success to do it.

Here you have my code: (to run it, you have to create an icosphere called ‘cell’ before):


import bpy
import random


cell = bpy.data.objects['cell']
bpy.context.scene.objects.active = cell


# Clear old shape key
# Dont work: why ?
if cell.data.shape_keys:
    for i, key in enumerate(cell.data.shape_keys.key_blocks):
        cell.active_shape_key_index = i
        bpy.ops.object.shape_key_remove()
    bpy.ops.object.shape_key_remove()


# Create new shape key
basis_key = cell.shape_key_add('basis')
basis_key.keyframe_insert('value', frame=0)


dt = 30


for i, t in enumerate(range(0, 1000, dt)):


    deform_key = cell.shape_key_add()
    cell.active_shape_key_index = i + 1


    start_dyn = 0.8
    end_dyn = 1.2
    for basis_vertex, vertex in zip(basis_key.data, deform_key.data):
        vertex.co.x = basis_vertex.co.x * random.uniform(start_dyn, end_dyn)
        vertex.co.y = basis_vertex.co.y * random.uniform(start_dyn, end_dyn)
        vertex.co.z = basis_vertex.co.z * random.uniform(start_dyn, end_dyn)


    deform_key.value = random.uniform(0, 0.2)
    deform_key.keyframe_insert('value', frame=t)
    deform_key.value = random.uniform(0.8, 1)
    deform_key.keyframe_insert('value', frame=t + dt * 2)


bpy.ops.object.shape_key_clear()

Thank you for your help !

PS: I am discovering Blender for few days now, and it is just awesome what you can do with !!!
PS2: I am a biologist, trying to make nice biological visualization :smiley:

Hi Hadim, that’s really advanced stuff, what you are trying to do. A python-scripted animation with randomly created shape keys. Respect! Indeed your approach of setting random vertex coordinates is promising.

But how really random should it be? Perhaps rigging your biological sphere with some bones, posing it by hand and setting keyframes will do the job also?

Another alternative could be to define a couple of shape keys by modelling them and then randomly pick them with a python script.

Hi and thanks for your answer.

Rigging the sphere with bones seems strange to me but it could work. On the other side, I like your other suggestion. Instead of creating a tons of shape keys (one every 30 frames can be heavy for long animation I guess). I could create some of them (lets say between 10 and 50) and randomly pick a couple of shape keys every 30 frames.

I will try that and I let you know.

The thing I am still stick with, it’s this permanent deformation along the time I already explain in my first post. In my code, when I apply the translation with:

vertex.co.x = basis_vertex.co.x * random.uniform(start_dyn, end_dyn)

basis_vertex comes from basis_key which comes from cell.shape_key_add(‘basis’) (the first shape key I added). So theorically, it should apply the translation on original vertices and with the time my sphere shouldnt be so deformed… but it acts like every translations is applied on previous set of vertices, so my sphere is too much deformed after some time.

Here two screenshots which explains my problem, the first one is at frame 0 and the last one is the sphere after 1000 frames. The last one should looks like the first one.



Depending on what you are trying to do exactly it might be worth considering the use of an animated texture. For example, add an Empty to control the texture, then add a texture to your sphere, choose clouds and then in the mapping panel change the coordinates to Object and select the empty as the object. In the Influence panel deselect Color and select either Normal or Displace.


Now you can animate the shape of the sphere by moving, scaling and/or rotating the empty.

Here are examples with animation of the Displacement and Normal




Hello Hadim, so now that we got plenty of alternative possible and reasonable approaches, let’s com back to your script. :yes:

I think there have been two main problems. First of all, imho shape keys are stacked. The 10th shape key is derived from the base shape, but if the shapes 1 to 9 have a value > 0 they affect the actual morph too. That explains the weird deformations at frame 1000. All shape keys had a value > 0 and therefore they all influenced your mesh.

Second problem was, that each of your shape keys changed its value at every key frame. That made it somewhat “jumpy” in my opinion.

I rewrote your script. It first defines about 30 shapes. In an additional loop it changes the shapes by repositioning the vertices (as you already did). And it sets key frames. Main difference in my approach is, that each shape key except the current is set to a value of 0 and that there are also key frames created for the currently not used shapes.

I also changed the interval to 100 frames to give it a natural smooth transforming look as if it would float in some liqour of a certain density.

Oh, and I named my icosphere “Icosphere” :slight_smile:

BTW: just the fact that these things don’t have bones in reality doesn’t mean they are not useful when creating an animation :eyebrowlift:

Now the code:


import bpy
import random


cell = bpy.data.objects['Icosphere']
bpy.context.scene.objects.active = cell

if cell.data.shape_keys:
    cell.active_shape_key_index = 0

# Delete old shape keys but keep the base shape
if cell.data.shape_keys:
    for i, key in enumerate(cell.data.shape_keys.key_blocks):
        cell.active_shape_key_index = i+1
        bpy.ops.object.shape_key_remove()

#create base key
basis_key = cell.shape_key_add('basis')

# Set base to active
cell.active_shape_key_index = 0
    
# Create 30 new additional shape keys
for x in range(1, 30):
    deform_key = cell.shape_key_add()

    start_dyn = 0.8
    end_dyn = 2.5
    
    for basis_vertex, vertex in zip(basis_key.data, deform_key.data):
        vertex.co.x = basis_vertex.co.x * random.uniform(start_dyn, end_dyn)
        vertex.co.y = basis_vertex.co.y * random.uniform(start_dyn, end_dyn)
        vertex.co.z = basis_vertex.co.z * random.uniform(start_dyn, end_dyn)    

    deform_key.value = random.uniform(0, 0.2)

# Create animation shapes and key frames
dt = 100

for i, t in enumerate(range(0, 1000, dt)):

    sk = cell.data.shape_keys
    skNamesArr = sk.key_blocks

    for key in skNamesArr:
        key.value = 0
        key.keyframe_insert('value', frame=t)

    deform_key_number = random.uniform(1, 31)
    cell.active_shape_key_index = deform_key_number
    cell.active_shape_key.value = random.uniform(0, 1)
    cell.active_shape_key.keyframe_insert('value', frame=t)

@AlanK: thanks for your answer but I prefer to directly deform my mesh instead of using “texture deformation”.

@minoribus: I didnt realize that other shape keys with value > 0 had an effect on my mesh. It’s now much more clear and I understand why my code didnt work. Your code seems cool. I will post my final code soon.

Thanks guys !

I would also suggest using an animated displacement texture. It seems like the easiest solution anyway.