import bpy
import numpy as np
import math
[docs]
class LaserShotStep:
def __init__(self, initPosition=None) -> None:
if initPosition is not None:
self.dx = initPosition.dx
self.dy = initPosition.dy
self.dz = initPosition.dz
self.rx = initPosition.rx
self.ry = initPosition.ry
self.rz = initPosition.rz
else:
self.zero()
def __sub__(self, other):
answ = LaserShotStep()
answ.dx = self.dx - other.dx
answ.dy = self.dy - other.dy
answ.dz = self.dz - other.dz
answ.rx = self.rx - other.rx
answ.ry = self.ry - other.ry
answ.rz = self.rz - other.rz
return answ
[docs]
def add(self, other):
self.dx += other.dx
self.dy += other.dy
self.dz += other.dz
self.rx += other.rx
self.ry += other.ry
self.rz += other.rz
[docs]
def addIncrement(self, increment):
self.dx += increment.dx
self.dy += increment.dy
self.dz += increment.dz
self.rx += increment.rx
self.ry += increment.ry
self.rz += increment.rz
[docs]
def zero(self):
self.dx = 0.0
self.dy = 0.0
self.dz = 0.0
self.rx = 0.0
self.ry = 0.0
self.rz = 0.0
[docs]
class UserProcess:
def __init__(self, *, ilspDomain=None, processSteps=None):
self._ilspDomain = ilspDomain
self._processSteps = []
self._path2userProcess(processSteps)
self._processStepIdx = 0
self._coords = None
self._normals = None
self._ilspDomain.animation_data_create()
self._ilspDomain.animation_data.action = \
bpy.data.actions.new(name="LSP Processing")
self._fcurveRx = self._ilspDomain.animation_data.action.fcurves.new(
data_path='rotation_euler', index=0)
self._fcurveRy = self._ilspDomain.animation_data.action.fcurves.new(
data_path='rotation_euler', index=1)
self._fcurveRz = self._ilspDomain.animation_data.action.fcurves.new(
data_path='rotation_euler', index=2)
self._fcurveDx = self._ilspDomain.animation_data.action.fcurves.new(
data_path='location', index=0)
self._fcurveDy = self._ilspDomain.animation_data.action.fcurves.new(
data_path='location', index=1)
self._fcurveDz = self._ilspDomain.animation_data.action.fcurves.new(
data_path='location', index=2)
self._rx = 0
self._ry = 0
self._rz = 0
self._dx = bpy.context.scene.cursor.location[0]
self._dy = bpy.context.scene.cursor.location[1]
self._dz = bpy.context.scene.cursor.location[2]
def _path2userProcess(self, processPathSteps):
deltaPosition = LaserShotStep()
for pathStep in processPathSteps:
if pathStep.frequency > 0:
laserShotStep = LaserShotStep(deltaPosition)
self._processSteps.append(laserShotStep)
deltaPosition.zero()
pathStepVector = np.array([pathStep.dx,
pathStep.dy,
pathStep.dz])
pathStepLength = np.linalg.norm(pathStepVector)
if pathStepLength > 0.0:
endPathStepTime = pathStepLength / pathStep.velocity
shotPeriod = 1.0 / pathStep.frequency
delta = shotPeriod / endPathStepTime
ds = delta * pathStepVector
time = shotPeriod
while time <= endPathStepTime:
laserShotStep = LaserShotStep()
laserShotStep.dx = ds[0]
laserShotStep.dy = ds[1]
laserShotStep.dz = ds[2]
laserShotStep.rx = delta * pathStep.rx
laserShotStep.ry = delta * pathStep.ry
laserShotStep.rz = delta * pathStep.rz
self._processSteps.append(laserShotStep)
time += shotPeriod
else:
noShots = int(pathStep.frequency)
delta = 1.0 / pathStep.frequency
for _ in range(0, noShots):
laserShotStep = LaserShotStep()
laserShotStep.rx = delta * pathStep.rx
laserShotStep.ry = delta * pathStep.ry
laserShotStep.rz = delta * pathStep.rz
self._processSteps.append(laserShotStep)
else:
deltaPosition.add(pathStep)
[docs]
def update(self):
try:
processStep = self._processSteps[self._processStepIdx]
except Exception:
return False
self._rx += processStep.rx
self._ry += processStep.ry
self._rz += processStep.rz
self._dx += processStep.dx
self._dy += processStep.dy
self._dz += processStep.dz
k = self._fcurveRx.keyframe_points.insert(
frame=self._processStepIdx + 1, value=math.radians(self._rx))
k.interpolation = 'CONSTANT'
k = self._fcurveRy.keyframe_points.insert(
frame=self._processStepIdx + 1, value=math.radians(self._ry))
k.interpolation = 'CONSTANT'
k = self._fcurveRz.keyframe_points.insert(
frame=self._processStepIdx + 1, value=math.radians(self._rz))
k.interpolation = 'CONSTANT'
k = self._fcurveDx.keyframe_points.insert(
frame=self._processStepIdx + 1, value=self._dx)
k.interpolation = 'CONSTANT'
k = self._fcurveDy.keyframe_points.insert(
frame=self._processStepIdx + 1, value=self._dy)
k.interpolation = 'CONSTANT'
k = self._fcurveDz.keyframe_points.insert(
frame=self._processStepIdx + 1, value=self._dz)
k.interpolation = 'CONSTANT'
bpy.context.scene.frame_set(self._processStepIdx + 1)
self._coords = []
for vertice in self._ilspDomain.data.vertices:
self._coords.append(self._ilspDomain.matrix_world @ vertice.co)
self._normals = []
matrix_new = self._ilspDomain.matrix_world.to_3x3().inverted().transposed()
for polygon in self._ilspDomain.data.polygons:
unitNormal = matrix_new @ polygon.normal
unitNormal.normalize()
self._normals.append(unitNormal)
self._processStepIdx += 1
return True
@property
def ilspDomain(self):
return self._ilspDomain
@property
def processSteps(self):
return self._processSteps
@property
def stepIndex(self):
return self._processStepIdx
@property
def coords(self):
return self._coords
@property
def normals(self):
return self._normals