1
$\begingroup$

I have this city from GIS, and they are individually separated objects.

enter image description here

and I do want to control their scales, position or rotation using a defined falloff, like shown below. I want to make the city appearing frame by frame, in short.

enter image description here

Additionally, I am planning to get the render at CyclesX, therefore, I must avoid to use animation nodes. It crushes consistently. I presume, it is the reason. Other than every suggestions are welcome.

$\endgroup$
8
  • $\begingroup$ Do you want them to come out of the ground, or scale up from a minuscule point? $\endgroup$
    – TheLabCat
    Commented Jun 21, 2021 at 18:48
  • $\begingroup$ Probably from the ground is better idea. $\endgroup$
    – merkwur
    Commented Jun 21, 2021 at 18:52
  • 1
    $\begingroup$ Try a displacement modifier on a grid underneath the city, and have the buildings with snap to constraints. $\endgroup$
    – TheLabCat
    Commented Jun 21, 2021 at 19:00
  • $\begingroup$ Quick, question tho! There are about thousand object, should I constrain them individually, or is there a better way to sort this issue out? $\endgroup$
    – merkwur
    Commented Jun 21, 2021 at 19:10
  • 1
    $\begingroup$ Sounds like a good candidate for the Vertex Weight Proximity Modifier and a Displace $\endgroup$ Commented Jun 21, 2021 at 19:19

1 Answer 1

1
$\begingroup$

I have solved my issue with a python script. It is a goofy but updated version. More importantly it works as well as I expected.

It can map the distance between falloff and object location to object z location as shown below

Animation duration, animation start frame, animation end frame, speed, elasticity, frequency, amplitude, initial and expected locations are adjustable.

You just need to have a collection of objects to being effected and an empty in the scene, change the name_collection="to_your_collection_name" and make sure there is an empty that named "Empty" or changefalloff="to_your_falloff_object_name" and it will run.

for changing the direction make falloff.location[along_axis] -= speed to falloff.location[along_axis] += speed

enter image description here enter image description here

import bpy
import numpy as np
 
name_collection="building" # desired effected objects collection name 

falloff_name = "Empty"
falloff_initial_loc = 8 # starting position of falloff use Vector() instead

obj_initial_scale = 1  # object initials use Vector() instead
obj_initial_z_loc = 0  # object initials use Vector() instead
expected_z_loc = 1

x, y, z = 0, 1, 2

# sets starting condition of effected object
# this two process reset the objects locations to testing different scenarios

for collection in bpy.data.collections:
    if collection.name == name_collection:
        buildings = collection
        for obj in buildings.all_objects:
            obj.location[z] = obj_initial_z_loc
            obj.scale[z] = obj_initial_scale

# sets starting condition of falloff 
for falloff in bpy.context.scene.objects:
    if falloff.name.startswith(falloff_name):
        falloff.location[x] = falloff_initial_loc
        
treshold = 3  # effect distance front of falloff

end_frame = bpy.data.scenes["Scene"].frame_end # get scene duration
current_frame = bpy.data.scenes["Scene"].frame_current
begin = 20 # animation start
end = 120  # animation end
duration = end - begin # animation duration
increment = 1 # frame_increment at each iteration

speed = 0.2 # changing falloff pos parameter by that meter during (#increment) frames
A = .007  # amplitude, scalar
frequency_scale = 1.520 # lesser the number wider the wavelength
elasticity = 6  # will be factored with threshold


def get_falloff():
    for falloff in bpy.context.scene.objects:
        if falloff.name.startswith(falloff_name):
            return falloff    

def damping(x, factor=1):
    return (np.exp(factor * -x) * np.cos(2 * np.pi * x))

def effector(collection, 
             frequency_scale, 
             elasticity, 
             obj_initial_z_loc, 
             expected_z_loc,  
             speed, x, y, z):
        
    for e, obj in enumerate(collection.all_objects): 
        distance = np.abs(obj.location[x] - falloff.location[x])
                 
        if obj.location[x] < falloff.location[x]:                    
            if distance < treshold:
                obj.location[z] = 1 / (1 + distance**2) + .05
        else:                 
            if distance < treshold * elasticity:
                obj.location[z] = (A * damping(distance * frequency_scale, factor=.9) + expected_z_loc) -.06                   
                
            else:
                obj.location[z] = expected_z_loc   
                                                                         
        obj.keyframe_insert(data_path="location")
        
if current_frame != begin:   
    
    bpy.data.scenes["Scene"].frame_set(begin)
    current_frame = bpy.data.scenes["Scene"].frame_current       
    falloff = get_falloff() 
       
    for j in range(duration//increment):
        bpy.data.scenes["Scene"].frame_set(current_frame)
        falloff.location[x] -= speed
        falloff.keyframe_insert(data_path = "location")
           
        effector(buildings, frequency_scale = frequency_scale, 
                            elasticity = elasticity,
                            obj_initial_z_loc = obj_initial_z_loc,
                            expected_z_loc = expected_z_loc,
                            speed=speed, x=x, y=y, z=z)  
                        
        current_frame += increment
      
# this is unnecessary step, this can be solve directly setting keyframe to animation_begin parameter                     
else: 

    current_frame = bpy.data.scenes["Scene"].frame_current
    falloff = get_falloff()
    
    for j in range(duration//increment):
        bpy.data.scenes["Scene"].frame_set(current_frame)
        falloff.location[x] -= speed
        falloff.keyframe_insert(data_path = "location")
        
        effector(buildings, frequency_scale = frequency_scale, 
                            elasticity = elasticity,
                            obj_initial_z_loc = obj_initial_z_loc,
                            expected_z_loc = expected_z_loc,
                            speed=speed, x=x, y=y, z=z)  
                        
        current_frame += increment
$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .