parent
ec8d800e7d
commit
91fba0a3ad
6 changed files with 201 additions and 55 deletions
Binary file not shown.
|
|
|
Binary file not shown.
@ -0,0 +1,146 @@ |
||||
import math |
||||
# me - this DAT |
||||
# scriptOp - the OP which is cooking |
||||
# |
||||
# press 'Setup Parameters' in the OP to call this function to re-create the parameters. |
||||
def onSetupParameters(scriptOp): |
||||
page = scriptOp.appendCustomPage('Custom') |
||||
page.appendFloat('Valuea', label='Value A') |
||||
page.appendFloat('Valueb', label='Value B') |
||||
return |
||||
def onCook(scriptOp): |
||||
scriptOp.clear() |
||||
# Define Table Header with position and rotation columns |
||||
scriptOp.appendRow(['text', 'P(X)', 'P(Y)', 'P(Z)', 'R(X)', 'R(Y)', 'R(Z)']) |
||||
|
||||
# --- Fetch External Parameters --- |
||||
const_op = op('constant1') |
||||
if not const_op: |
||||
return |
||||
|
||||
radius_scale = const_op['ring_scale'] |
||||
rotate_speed = const_op['rotate_speed'] |
||||
# text_space: used to define the angular gap between characters |
||||
text_space = const_op['text_space'] |
||||
arc_table = op('arc_table') |
||||
|
||||
if arc_table: |
||||
arc_table.clear() |
||||
arc_table.appendRow(['tx', 'ty', 'tz','rx', 'ry', 'rz','scale']) |
||||
|
||||
for source in scriptOp.inputs: |
||||
# Safety check: Input must exist and have at least a header and one data row |
||||
if not source or source.numRows < 2: |
||||
continue |
||||
|
||||
# Iterate through the rows of the source DAT |
||||
for i, row in enumerate(source.rows()[1:]): |
||||
|
||||
full_string = row[0].val |
||||
|
||||
if not full_string: |
||||
continue |
||||
|
||||
str_len = len(full_string) |
||||
|
||||
# Fetch speed variation from the speed_variation CHOP |
||||
speed_op = op('speed_variation') |
||||
speed_variation = speed_op[0][i] if speed_op and i < speed_op.numSamples else 0 |
||||
|
||||
# Calculate time-based rotation offset (in radians) |
||||
time_offset = absTime.seconds * rotate_speed *(1.0+ abs(speed_variation))/10.0 |
||||
|
||||
try: |
||||
center = [op('scaled_positions')[0][i], op('scaled_positions')[1][i], op('scaled_positions')[2][i]] |
||||
axis = [float(row[5]), float(row[6]), float(row[7])] |
||||
radius = float(row[8]) * radius_scale |
||||
except (ValueError, TypeError, IndexError): |
||||
continue |
||||
# --- Calculate Orthogonal Basis for the Ring Plane --- |
||||
ax, ay, az = axis |
||||
mag = math.sqrt(ax*ax + ay*ay + az*az) |
||||
if mag == 0: |
||||
ax, ay, az = 0, 1, 0 |
||||
else: |
||||
ax, ay, az = ax/mag, ay/mag, az/mag |
||||
if abs(ax) < 0.9: |
||||
tx, ty, tz = 1, 0, 0 |
||||
else: |
||||
tx, ty, tz = 0, 1, 0 |
||||
|
||||
ux = ay*tz - az*ty |
||||
uy = az*tx - ax*tz |
||||
uz = ax*ty - ay*tx |
||||
umag = math.sqrt(ux*ux + uy*uy + uz*uz) |
||||
ux, uy, uz = ux/umag, uy/umag, uz/umag |
||||
|
||||
vx = ay*uz - az*uy |
||||
vy = az*ux - ax*uz |
||||
vz = ax*uy - ay*ux |
||||
# --- Calculate Arc Logic --- |
||||
# Instead of forcing (i/str_len)*2*pi, we use text_space to determine the gap. |
||||
# If the total arc (gap * characters) < 2*pi, it remains an arc. |
||||
angular_step = text_space / (radius if radius > 0 else 1) |
||||
# angular_step = radius*math.pi*2.0/text_space if radius>0 else math.pi*2.0/str_len |
||||
total= math.floor(math.pi*2.0/(angular_step)) |
||||
count=0 |
||||
print(f"Processing string with length {str_len}, total positions: {total}") |
||||
# Build the table character by character |
||||
while count<total: |
||||
# for j in range(str_len): |
||||
|
||||
|
||||
# angle = (index * step) + time_offset |
||||
angle = ((count) * angular_step) + time_offset |
||||
|
||||
cos_a = math.cos(angle) * radius |
||||
sin_a = math.sin(angle) * radius |
||||
|
||||
# Outward vector relative to center |
||||
off_x = (ux * cos_a) + (vx * sin_a) |
||||
off_y = (uy * cos_a) + (vy * sin_a) |
||||
off_z = (uz * cos_a) + (vz * sin_a) |
||||
|
||||
# Final World Position |
||||
px = center[0] + off_x + parent().par.Keywordpositionx |
||||
py = center[1] + off_y + parent().par.Keywordpositiony |
||||
pz = center[2] + off_z + parent().par.Keywordpositionz |
||||
|
||||
# --- Calculate Rotations to face outside --- |
||||
dist = math.sqrt(off_x**2 + off_y**2 + off_z**2) |
||||
if dist > 0: |
||||
nx, ny, nz = off_x/dist, off_y/dist, off_z/dist |
||||
else: |
||||
nx, ny, nz = 0, 0, 1 |
||||
|
||||
char_ry = math.degrees(math.atan2(nx, nz)) |
||||
char_rx = math.degrees(math.asin(-ny)) + 90 |
||||
char_rz = 0 |
||||
|
||||
tan_x = (ux * -math.sin(angle)) + (vx * math.cos(angle)) |
||||
tan_y = (uy * -math.sin(angle)) + (vy * math.cos(angle)) |
||||
tan_z = (uz * -math.sin(angle)) + (vz * math.cos(angle)) |
||||
|
||||
line_ry = math.degrees(math.atan2(tan_x, tan_z)) - 90 |
||||
line_rx = math.degrees(math.asin(-tan_y)) |
||||
|
||||
# ry = math.degrees(math.atan2(nx, nz)) |
||||
# rx = math.degrees(math.asin(-ny))-90 |
||||
# rz = 0 |
||||
|
||||
if count>=str_len: |
||||
scale= radius*angular_step if radius>0 else 1 |
||||
arc_table.appendRow([px, py, pz, line_rx, line_ry, 0, scale/2]) |
||||
# scriptOp.appendRow(['-', px, py, pz, char_rx, char_ry, 0]) |
||||
else: |
||||
char = full_string[count] |
||||
scriptOp.appendRow([char, px, py, pz, char_rx, char_ry, 0]) |
||||
# arc_table.appendRow([px, py, pz, rx, ry, rz, 1.0]) |
||||
|
||||
count+=1 |
||||
|
||||
|
||||
|
||||
return |
||||
def onGetCookLevel(scriptOp): |
||||
return CookLevel.ALWAYS |
||||
Loading…
Reference in new issue