mirror of
https://github.com/blender/blender-addons.git
synced 2025-07-25 16:05:20 +00:00
134 lines
5.1 KiB
Python
134 lines
5.1 KiB
Python
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
|
|
# -----------------------------------------------------------------------
|
|
#
|
|
import bpy
|
|
import bmesh
|
|
from math import sin, cos, tan, pi
|
|
from mathutils import Vector
|
|
from .pdt_functions import (
|
|
set_mode,
|
|
view_coords,
|
|
)
|
|
|
|
class PDT_OT_WaveGenerator(bpy.types.Operator):
|
|
"""Generate Trig Waves in Active Object"""
|
|
bl_idname = "pdt.wave_generator"
|
|
bl_label = "Generate Waves"
|
|
bl_options = {"REGISTER", "UNDO"}
|
|
|
|
@classmethod
|
|
def poll(cls, context):
|
|
pg = context.scene.pdt_pg
|
|
return pg.trig_obj is not None
|
|
|
|
def execute(self, context):
|
|
"""Generate Trig Waves in Active Object.
|
|
|
|
Note:
|
|
Uses all the PDT trig_* variables.
|
|
|
|
This function will draw a trigonometrical wave based upon cycle length
|
|
One cycle is assumed to be 180 degrees, so half a revolution of an imaginary
|
|
rotating object. If a full cycle from 0 to 360 degrees is required, the cycles
|
|
number should be set to 2.
|
|
|
|
Args:
|
|
context: Blender bpy.context instance.
|
|
|
|
Returns:
|
|
Nothing.
|
|
"""
|
|
|
|
pg = context.scene.pdt_pg
|
|
plane = pg.plane
|
|
# Find the horizontal, vertical and depth axes in the view from working plane.
|
|
# Order is: H, V, D.
|
|
#
|
|
a1, a2, a3 = set_mode(plane)
|
|
# Make sure object selected in the UI is the active object.
|
|
#
|
|
for obj in bpy.data.objects:
|
|
obj.select_set(state=False)
|
|
context.view_layer.objects.active = pg.trig_obj
|
|
# x_inc is the increase in X (Horiz axis) per unit of resolution of the wave, so if
|
|
# resolution is 9, nine points will be drawn in each cycle representing increases of
|
|
# 20 degrees and 1/9th of the cycle length.
|
|
#
|
|
x_inc = pg.trig_len / pg.trig_res
|
|
|
|
if pg.trig_del:
|
|
# Delete all existing vertices first.
|
|
#
|
|
bpy.ops.object.mode_set(mode='EDIT')
|
|
for v in pg.trig_obj.data.vertices:
|
|
v.select = True
|
|
bpy.ops.mesh.delete(type='VERT')
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
|
|
if pg.trig_obj.mode != "EDIT":
|
|
bpy.ops.object.mode_set(mode='EDIT')
|
|
bm = bmesh.from_edit_mesh(pg.trig_obj.data)
|
|
|
|
# Loop for each point in the number of cycles times the resolution value.
|
|
# Uses basic trigonomtry to calculate the wave locations.
|
|
# If Absolute has been set, all values are made positive.
|
|
# z_val is assumed to be the offset from the horizontal axis of the wave.
|
|
# These values will be offset by the Offset Vector given in the UI.
|
|
#
|
|
for i in range((pg.trig_res * pg.trig_cycles) + 1):
|
|
# Uses a calculation of trig function angle of imaginary object times maximum amplitude
|
|
# of wave. So with reolution at 9, angular increments are 20 degrees.
|
|
# Angles must be in Radians for this calcultion.
|
|
#
|
|
if pg.trig_type == "sin":
|
|
if pg.trig_abs:
|
|
z_val = abs(sin((i / pg.trig_res) * pi) * pg.trig_amp)
|
|
else:
|
|
z_val = sin((i / pg.trig_res) * pi) * pg.trig_amp
|
|
elif pg.trig_type == "cos":
|
|
if pg.trig_abs:
|
|
z_val = abs(cos((i / pg.trig_res) * pi) * pg.trig_amp)
|
|
else:
|
|
z_val = cos((i / pg.trig_res) * pi) * pg.trig_amp
|
|
else:
|
|
if pg.trig_abs:
|
|
z_val = abs(tan((i / pg.trig_res) * pi) * pg.trig_amp)
|
|
else:
|
|
z_val = tan((i / pg.trig_res) * pi) * pg.trig_amp
|
|
|
|
if abs(z_val) > pg.trig_tanmax:
|
|
if z_val >= 0:
|
|
z_val = pg.trig_tanmax
|
|
else:
|
|
if pg.trig_abs:
|
|
z_val = pg.trig_tanmax
|
|
else:
|
|
z_val = -pg.trig_tanmax
|
|
|
|
# Start with Offset Vector from UI and add wave offsets to it.
|
|
# Axis a3 (depth) is never changed from offset vector in UI.
|
|
#
|
|
vert_loc = Vector(pg.trig_off)
|
|
vert_loc[a1] = vert_loc[a1] + (i * x_inc)
|
|
vert_loc[a2] = vert_loc[a2] + z_val
|
|
if plane == "LO":
|
|
# Translate view local coordinates (horiz, vert, depth) into World XYZ
|
|
#
|
|
vert_loc = view_coords(vert_loc[a1], vert_loc[a2], vert_loc[a3])
|
|
vertex_new = bm.verts.new(vert_loc)
|
|
# Refresh Vertices list in object data.
|
|
#
|
|
bm.verts.ensure_lookup_table()
|
|
if i > 0:
|
|
# Make an edge from last two vertices in object data.
|
|
#
|
|
bm.edges.new([bm.verts[-2], vertex_new])
|
|
|
|
bmesh.update_edit_mesh(pg.trig_obj.data)
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
|
|
return {"FINISHED"}
|