9
$\begingroup$

This question already has an answer here:

as everybody know, when you put two spheres close to each other they intersect other like this :

How do I flatten the spheres at the region where they intersect each, I tried to illustrate this with a quickdraw :enter image description here

I don't know if it's possible with physics like soft body or collision. does anyone know how to get this result, i need this for a still image not for animation.

I'm more looking for something like this:

enter image description here

$\endgroup$

marked as duplicate by Ray Mairlot, Denis, Community Oct 15 '17 at 21:14

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ This works but i want the effect even when i'm note playing the animation, i need this for a fix image not for animation, is there a way to get the physics result in one frame ? $\endgroup$ – amby Oct 14 '17 at 19:58
  • $\begingroup$ This is for a personal project and i have absolutely no dead line, so do it only if you got the time, thank you very much $\endgroup$ – amby Oct 14 '17 at 23:07
9
$\begingroup$

Bmesh script

Script to flatten spheres on their intersection plane. See intersection of two spheres on Paul Bourke's magnificent geometry site The code runs through each selected sphere, checks if they intersect, if they do clalculates the location of the circle of hit.

If there's a collision, for both spheres, selects all vertices that are within the conic angle of the collision and moves them to the point of intersection with the collision disc. NOTE: script relies on the origin of the spheres being the (default) centre of geometry.

Sphere example Test run on UV Spheres.

The script

Select all the spheres you want to modify and run script. Alter the scale to change the angle of effect of flattening vertices.

import bpy
import bmesh
from math import acos, degrees, radians
from mathutils import Vector
from mathutils.geometry import intersect_line_plane
context = bpy.context
scene = context.scene
spheres = [(o, max(axis for axis in o.dimensions) / 2) for o in context.selected_objects]
bmeshes = {}

scale = 1.0 # alter to widen bump angle.
def new_bmesh(me):
    bm = bmesh.new()
    bm.from_mesh(me)
    return bm

def squish(sphere, angle, global_plane_co, global_plane_no):
    mw = sphere.matrix_world
    mwi = mw.inverted()

    bm = bmeshes.setdefault(sphere.name, new_bmesh(sphere.data))
    local_p = mwi * global_plane_co
    local_norm = mwi * (global_plane_co + global_plane_no) - local_p
    # select all verts via angle
    proj = angle > radians(90)
    if proj:
        angle = radians(180) - angle
        verts = [v for v in bm.verts if v.co.angle(local_p) > angle]
    else:
        verts = [v for v in bm.verts if v.co.angle(local_p) < angle]
    for v in verts:
        v.select = True
        d = local_norm if proj else v.co
        o = v.co if proj else Vector()
        hit = intersect_line_plane(o, d, local_p, local_norm)
        if hit and hit.length < v.co.length:
            v.co = hit

while spheres:
    sphere, R = spheres.pop()
    P = sphere.matrix_world.translation    
    for s, r in spheres:        
        p = s.matrix_world.translation
        v = (p - P)
        d = v.length
        v.normalize()
        if d >= r + R:
            continue
        elif abs(r - R) > d:
            continue
        elif d < 0.0001:
            continue

        x = (d * d - r * r + R * R) / (2 * d)
        # define plane
        pt = P + x * v
        norm = v  
        angle1 = acos(x / R)
        angle2 = acos((d - x) / r)
        #print(R, r, x, degrees(angle1), degrees(angle2))
        squish(sphere, scale * angle1, pt, norm)
        squish(s, scale * angle2, pt, norm)

for name, bm in bmeshes.items():
    me = scene.objects[name].data
    bm.to_mesh(me)
    me.update()

scene.update()

Sample run icospheres Sample run on icosphere cluster on left, result on right

EDIT: fix for inside cases, now projects back onto plane if hit is inside (angle is greater than 90 degrees.

enter image description here

$\endgroup$
  • $\begingroup$ that's exactly what i was looking for, i try it as soon as possible, thank you for your answer batFINGER $\endgroup$ – amby Oct 15 '17 at 18:17
  • $\begingroup$ @amby given this comment, I've edited your question. Re-edit it if it's not your intention. $\endgroup$ – batFINGER Oct 15 '17 at 18:41
  • $\begingroup$ it was my intention, i just have some trouble to explain my idea in english (i'm french), so i make lots of mistakes in english.. $\endgroup$ – amby Oct 15 '17 at 21:15
  • 1
    $\begingroup$ @amby edited script to handle inside cases better. $\endgroup$ – batFINGER Oct 17 '17 at 16:44
3
$\begingroup$

If i understood the question maybe your looking for this

I have added 2 sphere and to 1 i have added the cast modifier

With the reference of pencil drawing sphere to deform when they touch each other.

In the cast modifier you can play with the settings and get the effect.

enter image description here

$\endgroup$

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