3
$\begingroup$

Is it possible to make fluid rotate a rigid body, like in water wheel? I have a stick, which is constrained to rotate around one axis, but fluid, falling from pipe, doesn't affect it

screenshot

$\endgroup$
  • $\begingroup$ Nice question I will search it. $\endgroup$ – xlxs Oct 11 '16 at 23:47
5
$\begingroup$

As of now (v2.78) the various simulations engines inside Blender are not cross-connected enough to enable this.

Even if you manage to have rigid bodies be effected by the fluid mesh, the fluid mesh needs to react back to the motion of rigid bodies. So all the elements have to be simulated at the same time.

In volumetric fluid the cells don't move, it only appears the fluid does. The fluid motion is mesh animation with different mesh each animation frame. There is an option to generate flow particles inside the fluid volume, but the results are not accurate and they don't work very well.

If you need fluid physics I suggest look into SPH particles that you can mesh into fluid with CubeSurfer addon (video here).

You can have particles act like rigid bodies and have them effect other rigid bodies. Use this script from liero (source) to copy Particles to Rigid Bodies:

bl_info = {
    "name": "Copy Particles to Rigid Bodies",
    "version": (0, 0, 10),
    'location': 'Tool bar > Physics tab > Particles to Simulation',
    "description": "Transfers dupliobjects from a PS to a Rigid Bodies simulation",
    "category": "Animation",
}

import bpy, random


class Particles_to_Sim(bpy.types.Operator):
    bl_idname = 'object.particles_to_simulation'
    bl_label = 'Copy Particles'
    bl_description = 'Transfers dupliobjects from a PS to a Rigid Bodies simulation'
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        obj = bpy.context.object
        return(obj and obj.particle_systems)

    def execute(self, context):
        wm = bpy.context.window_manager
        scn = bpy.context.scene
        fps = scn.render.fps
        obj = bpy.context.object
        set = obj.particle_systems[0].settings
        par = obj.particle_systems[0].particles
        txt = 'Set Particle System dupliobject to a Rigid Body object / group'

        # disable simulation
        scn.rigidbody_world.enabled = False

        # to avoid PS cache troubles
        # obj.particle_systems[0].seed += 1

        # get dupliobject from particles system
        if set.render_type == 'OBJECT':
            duplist = [set.dupli_object]
        elif set.render_type == 'GROUP':
            duplist = set.dupli_group.objects[:]
        else:
            self.report({'ERROR'}, txt)
            return{'FINISHED'}

        # check if dupliobjects are valid
        for d in duplist:
            if not d.rigid_body:
                self.report({'ERROR'}, txt)
                return{'FINISHED'}

        # an Empty as parent allows to move / rotate later
        bpy.ops.object.add(type='EMPTY')
        bpy.context.object.name = 'Bullet Particles'
        bpy.ops.object.select_all(action='DESELECT')
        root = scn.objects.active
        delta = obj.location * wm.use_loc
        root.location = delta

        for p in par:
            dup = random.choice(duplist)
            btime = round(p.birth_time, 2)
            scn.frame_set(btime)
            phy = bpy.data.objects.new('particle.000', dup.data)
            scn.objects.link(phy)
            scn.objects.active = phy #..?
            phy.select = True
            phy.rotation_euler = p.rotation.to_euler()
            bpy.ops.rigidbody.objects_add(type='ACTIVE')
            scn.frame_set(scn.frame_current) #..?
            phy.parent = root
            phy.select = False
            sca = [p.size * s for s in dup.scale]

            # copy some rigid body settings
            phy.rigid_body.collision_shape = dup.rigid_body.collision_shape
            phy.rigid_body.restitution = dup.rigid_body.restitution
            phy.rigid_body.linear_damping = dup.rigid_body.linear_damping
            phy.rigid_body.angular_damping = dup.rigid_body.angular_damping
            phy.rigid_body.friction = dup.rigid_body.friction
            phy.rigid_body.mass = dup.rigid_body.mass

            # keyframe unborn particle
            phy.scale = sca
            phy.location = p.location - delta
            phy.rigid_body.kinematic = True
            phy.keyframe_insert('location', frame = btime)
            phy.rigid_body.keyframe_insert('kinematic', frame = btime)

            # keyframe particle pop up
            if not set.show_unborn:
                phy.scale = [0,0,0]
                phy.keyframe_insert('scale', frame = btime - wm.grow_frames)
                phy.scale = sca
                phy.keyframe_insert('scale', frame = btime)

            # keyframe alive particle
            phy.location += p.velocity / fps * wm.vel_mult
            phy.keyframe_insert('location', frame = btime + 1)
            phy.rigid_body.kinematic = False
            phy.rigid_body.keyframe_insert('kinematic', frame = btime + 2)

        # hide emmitter
        obj.hide = obj.hide_render = True
        scn.frame_set(scn.frame_start)
        bpy.ops.object.select_all(action='DESELECT')
        scn.objects.active = root
        root.select = True

        # enable simulation
        scn.rigidbody_world.enabled = True

        return{'FINISHED'}


class PanelP2RB(bpy.types.Panel):
    bl_label = 'Particles to Simulation'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'
    bl_category = "Physics"

    @classmethod
    def poll(cls, context):
        obj = bpy.context.object
        return(obj and obj.particle_systems)

    def draw(self, context):
        wm = bpy.context.window_manager
        scn = bpy.context.scene
        obj = bpy.context.object
        set = obj.particle_systems[0].settings
        layout = self.layout
        layout.operator('object.particles_to_simulation')
        layout.prop(wm, 'use_loc')
        column = layout.column(align=True)
        column.prop(wm, 'vel_mult')
        if not set.show_unborn:
            column.prop(wm, 'grow_frames')
        column.separator()
        column.prop(scn.rigidbody_world, "use_split_impulse")


bpy.types.WindowManager.vel_mult=bpy.props.FloatProperty(name='Speed',
        min=0.01, max=50, default=1, description='Particle speed multiplier')
bpy.types.WindowManager.use_loc=bpy.props.BoolProperty(name='Origin at emiter',
        default=True, description='Place simulation root object at emiter start position '
        ', maybe disable for animated emitters')
bpy.types.WindowManager.grow_frames=bpy.props.IntProperty(name='Grow time',
        min=1, max=50, default=1, description='Frames to scale particles before simulating')


def register():
    bpy.utils.register_class(Particles_to_Sim)
    bpy.utils.register_class(PanelP2RB)


def unregister():
    bpy.utils.unregister_class(Particles_to_Sim)
    bpy.utils.unregister_class(PanelP2RB)

if __name__ == '__main__':
    register()

enter image description here

But the problem remains the same. You can have either particles with rigid-body properties, or particles with fluid properties, but not both at same time and not simulated at same time. Same with volumetric mesh fluids. There is no way to have mesh deformation effect rigid body and at the same time be influenced back.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.