Skip to content

Instantly share code, notes, and snippets.

@shspage
Last active December 31, 2020 08:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shspage/1b0d115b227c32ef8176e8572e805c30 to your computer and use it in GitHub Desktop.
Save shspage/1b0d115b227c32ef8176e8572e805c30 to your computer and use it in GitHub Desktop.
import bpy
import math
import numpy as np
from time import time
# 参考:
# https://blender.stackexchange.com/questions/190547/mesh-edges-foreach-set-doesnt-update
bpy.app.handlers.frame_change_pre.clear()
bpy.app.handlers.frame_change_post.clear()
bpy.context.scene.frame_set(0)
class Params:
freq = 5.0
speed = 0.4
amp = 0.18
radius = 7.0
class MySceneLoop:
def __init__(self):
self.fc = 0 # frame count
self.t = None # time
self.vs = None # vertices
self.d1s = None # distances 1
self.d2s = None # distandes 2
def initPlane(self):
# Plane : a grid
# dots : a polyline on the grid
self.vs = bpy.data.objects['Plane'].data.vertices
self.d1s = [0.0] * len(self.vs)
self.d2s = [0.0] * len(self.vs)
dots = bpy.data.objects['dots'].data.vertices
for v in self.vs:
v.co.z = 0.0
d1, d2 = self.minDist(v.co, dots)
self.d1s[v.index] = d1
self.d2s[v.index] = d2
def minDist(self, p, dots):
r = [(v.co - p).length for v in dots]
r.sort()
return r[0], r[1]
def my_handler(self, *args):
if self.t is None:
self.t = time()
scene = args[0]
self.fc = float(scene.frame_current)
pr = Params
for v in self.vs:
d1 = self.d1s[v.index]
d2 = self.d2s[v.index]
w1 = math.sin(d1 * pr.freq - (self.fc * pr.speed)) * pr.amp
w1 *= 1.0 - max(0, min(d1, pr.radius)) / pr.radius
w2 = math.sin(d2 * pr.freq - (self.fc * pr.speed)) * pr.amp
w2 *= 1.0 - max(0, min(d2, pr.radius)) / pr.radius
v.co.z = w1 + w2
# shows elapsed time
if self.fc == 100:
print(time() - self.t)
class MySceneNp:
def __init__(self):
self.fc = 0 # frame count
self.t = None # time
self.vs = None # vertices
self.vsw = None # vertices (working)
self.d1s = None # distances 1
self.d2s = None # distances 2
def initPlane(self):
self.vs = bpy.data.objects['Plane'].data.vertices
d1s = [0.0] * len(self.vs)
d2s = [0.0] * len(self.vs)
dots = bpy.data.objects['dots'].data.vertices
for v in self.vs:
v.co.z = 0.0
d1, d2 = self.minDist(v.co, dots)
d1s[v.index] = d1
d2s[v.index] = d2
self.d1s = np.array(d1s)
self.d2s = np.array(d2s)
vsw = np.zeros((len(self.vs) * 3), dtype=np.float)
self.vs.foreach_get("co", vsw)
self.vsw = np.reshape(vsw, (len(self.vs), 3))
def minDist(self, p, dots):
r = [(v.co - p).length for v in dots]
r.sort()
return r[0], r[1]
def my_handler(self, *args):
if self.t is None:
self.t = time()
scene = args[0]
self.fc = float(scene.frame_current)
pr = Params
w1 = np.sin(self.d1s * pr.freq - (self.fc * pr.speed)) * pr.amp
w1 *= 1.0 - np.clip(self.d1s, 0, pr.radius) / pr.radius
w2 = np.sin(self.d2s * pr.freq - (self.fc * pr.speed)) * pr.amp
w2 *= 1.0 - np.clip(self.d2s, 0, pr.radius) / pr.radius
self.vsw[:, -1] = w1 + w2
self.vs.foreach_set("co", self.vsw.ravel())
bpy.data.meshes['Plane'].update()
# shows elapsed time
if self.fc == 100:
print(time() - self.t)
# run script, then start animation manually
#myscene = MySceneLoop()
myscene = MySceneNp()
myscene.initPlane()
bpy.app.handlers.frame_change_pre.append(myscene.my_handler)
print("done")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment