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
    Jun 21 at 18:48
  • $\begingroup$ Probably from the ground is better idea. $\endgroup$
    – merkwur
    Jun 21 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
    Jun 21 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
    Jun 21 at 19:10
  • 1
    $\begingroup$ Sounds like a good candidate for the Vertex Weight Proximity Modifier and a Displace $\endgroup$ Jun 21 at 19:19
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
                            
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$

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.