From fafaebb051907a848a9406f9da19669c81a83a3b Mon Sep 17 00:00:00 2001 From: Elvis Claros Castro Date: Sat, 26 Sep 2026 20:50:41 -0300 Subject: Translate code, comments and logs to English; English README; configurable paths and env vars Identifiers, docstrings, comments and console messages are now in English. Narration, subtitles and on-screen text stay in Spanish (they are the video content). The Blender <-> Godot physics protocol uses English keys and body prefixes chosen to keep the original creation order, so cached simulations and renders stay bit-identical. The old Spanish environment variable names are still accepted. --- blender/diferencial.py | 388 ++++++++++++++++++++++++------------------------- 1 file changed, 194 insertions(+), 194 deletions(-) (limited to 'blender/diferencial.py') diff --git a/blender/diferencial.py b/blender/diferencial.py index 015444a..9019e42 100644 --- a/blender/diferencial.py +++ b/blender/diferencial.py @@ -1,304 +1,304 @@ # -*- coding: utf-8 -*- -"""DIFERENCIAL - por que las dos ruedas pueden girar a distinta velocidad. +"""DIFERENCIAL - why the two wheels can turn at different speeds. -Todas las piezas se generan por codigo y se mueven con la cinematica exacta del -mecanismo: w_izq + w_der = 2 * w_jaula, y el satelite gira sobre su eje a -(w_der - w_izq)/2 respecto de la jaula. El pinon y la corona respetan su -relacion: 14 y 43 dientes, con semiangulos de cono que suman 90 grados. -""" +Every part is generated in code and moves with the exact kinematics of the +mechanism: w_left + w_right = 2 * w_carrier, and the spider gear spins about +its own axis at (w_right - w_left)/2 relative to the carrier. Pinion and ring +gear keep their ratio: 14 and 43 teeth, with cone half-angles adding up to 90 +degrees.""" import math, os, sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import bpy from mathutils import Vector from base import * -NOMBRE = "diferencial" -EJE_X = 1.32 # donde van las ruedas -R_RUEDA = 0.52 -OMEGA = 1.45 # rad/s de la jaula +NAME_KEY = "diferencial" +AXIS_X = 1.32 # where the wheels go +R_WHEEL = 0.52 +OMEGA = 1.45 # rad/s of the carrier RADIO_GIRO = 3.9 -TROCHA = 1.70 -INCL = -0.72 # bien diagonal: en 9:16 es lo que aprovecha el alto +TRACK_W = 1.70 +INCL = -0.72 # strongly diagonal: in 9:16 that is what uses the height -N_COR, N_PIN = 43, 14 # relacion 3,07:1, como un diferencial de calle -G_COR, G_PIN = 72.0, 18.0 # los semiangulos suman 90: es la condicion de engrane +N_COR, N_PIN = 43, 14 # 3.07:1 ratio, like a road differential +G_COR, G_PIN = 72.0, 18.0 # the half-angles add up to 90: that is the meshing condition N_LAT = 16 -X_COR = -0.50 # apice comun de corona y pinon: lejos de los satelites -D_I, D_O = 0.70, 1.00 # la cara dentada, igual en los dos -P_FASE = math.pi / 2 # para que el diente caiga en el hueco -P_ESP = -0.62 # mano contraria a la corona -P_SIG = 1.0 +X_COR = -0.50 # common apex of ring gear and pinion: far from the spider gears +D_I, D_O = 0.70, 1.00 # the toothed face, the same on both +P_PHASE = math.pi / 2 # so the tooth lands in the gap +P_ESP = -0.62 # opposite hand to the ring gear +P_NEXT = 1.0 -# el conjunto mide 3,68 de punta a punta; inclinado 41 grados eso son 2,77 de -# ancho y 2,41 de alto, que es lo que fija estos numeros -ENCUADRE = [(0, 6.2), (2, 5.0), (3, 4.2), (4, 5.6), (5, 4.6), +# the assembly is 3.68 from end to end; tilted 41 degrees that is 2.77 wide +# and 2.41 high, which is what sets these numbers +FRAMING = [(0, 6.2), (2, 5.0), (3, 4.2), (4, 5.6), (5, 4.6), (6, 5.0), (7, 5.6), (8, 5.6), (9, 5.8), (10, 5.2)] DIR_CAM = Vector((0.30, -0.93, 0.21)).normalized() def alto_en(T, f): - tabla, altos, v = dict(ENCUADRE), [], ENCUADRE[0][1] + tabla, altos, v = dict(FRAMING), [], FRAMING[0][1] for i in range(len(T.beats)): v = tabla.get(i, v) altos.append(v) i = 0 for k in range(len(T.beats)): - if f >= T.rango(k)[0]: + if f >= T.span(k)[0]: i = k - ini, fin = T.rango(i) - p = min(1.0, (f - ini) / max(1.0, (fin - ini) * 0.55)) - return mezcla(altos[i - 1] if i else altos[0], altos[i], p) + start, fin = T.span(i) + p = min(1.0, (f - start) / max(1.0, (fin - start) * 0.55)) + return mix_m(altos[i - 1] if i else altos[0], altos[i], p) -def construir(T): - sc = escena() - mundo_estudio(0.65) # lo que refleja el acero - cam = camara((0, -6, 0), (0, 0, 0), lente=50) +def build_scene(T): + sc = scene_setup() + studio_world(0.65) # what the steel reflects + cam = camera_obj((0, -6, 0), (0, 0, 0), lens=50) cam.data.sensor_fit = 'VERTICAL' cam.data.sensor_height = 36.0 - luz("key", 'AREA', (-3.4, -4.6, 4.4), 1400, "blanco", tam=6.0, mira=(0, 0, 0)) - luz("fill", 'AREA', (4.2, -3.2, -1.6), 420, "#BFD4FF", tam=5.0, mira=(0, 0, 0)) - luz("rim", 'AREA', (-0.8, 4.6, 2.8), 900, "blanco", tam=4.0, mira=(0, 0, 0)) + light_obj("key", 'AREA', (-3.4, -4.6, 4.4), 1400, "blanco", size_u=6.0, sight=(0, 0, 0)) + light_obj("fill", 'AREA', (4.2, -3.2, -1.6), 420, "#BFD4FF", size_u=5.0, sight=(0, 0, 0)) + light_obj("rim", 'AREA', (-0.8, 4.6, 2.8), 900, "blanco", size_u=4.0, sight=(0, 0, 0)) M = { - "acero": metal("acero", "#B7BEC9", rug=0.22), - "acero2": metal("acero2", "#9BA3B0", rug=0.30), - "fundido": metal("fundido", "#5E6774", rug=0.62, met=0.85), - "eje_i": metal("eje_i", "#C2C8D2", rug=0.24), - "eje_d": metal("eje_d", "#C2C8D2", rug=0.24), - "goma": material("goma", "#1E222C", rug=0.52), - "alu": metal("alu", "#CBD3DE", rug=0.15), - "freno": metal("freno", "#79818E", rug=0.45, met=0.9), + "acero": metal("acero", "#B7BEC9", rough=0.22), + "acero2": metal("acero2", "#9BA3B0", rough=0.30), + "fundido": metal("fundido", "#5E6774", rough=0.62, met=0.85), + "eje_i": metal("eje_i", "#C2C8D2", rough=0.24), + "eje_d": metal("eje_d", "#C2C8D2", rough=0.24), + "goma": material("goma", "#1E222C", rough=0.52), + "alu": metal("alu", "#CBD3DE", rough=0.15), + "freno": metal("freno", "#79818E", rough=0.45, met=0.9), } - # --- vista de arriba: el auto doblando -------------------------------- - piso = bpy.data.objects.new("suelo_g", None) - bpy.context.collection.objects.link(piso) - arcos, ruedas_a = [], [] - for k, (rr, c) in enumerate(((RADIO_GIRO - TROCHA / 2, "rosa"), - (RADIO_GIRO + TROCHA / 2, "verde"))): + # --- top view: the car turning -------------------------------------- + floor_obj = bpy.data.objects.new("suelo_g", None) + bpy.context.collection.objects.link(floor_obj) + arc_list, wheels_a = [], [] + for k, (rr, c) in enumerate(((RADIO_GIRO - TRACK_W / 2, "rosa"), + (RADIO_GIRO + TRACK_W / 2, "verde"))): pts = [] for i in range(120): th = -0.62 + 1.24 * i / 119.0 pts.append((-RADIO_GIRO + rr * math.cos(th), rr * math.sin(th), 0.0)) - cu = curva_poly(f"arco{k}", [pts], grosor=0.045, radios=[[0.0] * 120], - mat=material(f"m_arco{k}", c, emis=2.4, rug=0.5)) - cu.parent = piso - arcos.append((cu, pts)) - r = rueda_completa(f"ra{k}", M, R=R_RUEDA, r=0.185, ancho=0.28) - r.parent = piso - ruedas_a.append(r) - eje_a = cilindro("eje_a", 0.075, TROCHA, M["acero2"]) - eje_a.parent = piso - patina = curva_poly("patina", [[(0, 0, 0)] * 60], grosor=0.11, - radios=[[0.0] * 60], mat=material("m_pat", "blanco", emis=3.4)) - patina.parent = piso + cu = curve_poly(f"arco{k}", [pts], thickness_px=0.045, radios=[[0.0] * 120], + mat=material(f"m_arco{k}", c, emit=2.4, rough=0.5)) + cu.parent = floor_obj + arc_list.append((cu, pts)) + r = full_wheel(f"ra{k}", M, R=R_WHEEL, r=0.185, width_px=0.28) + r.parent = floor_obj + wheels_a.append(r) + axis_a = cylinder("eje_a", 0.075, TRACK_W, M["acero2"]) + axis_a.parent = floor_obj + patina = curve_poly("patina", [[(0, 0, 0)] * 60], thickness_px=0.11, + radios=[[0.0] * 60], mat=material("m_pat", "blanco", emit=3.4)) + patina.parent = floor_obj - # --- el diferencial ---------------------------------------------------- - dif = bpy.data.objects.new("dif", None) - bpy.context.collection.objects.link(dif) - dif.scale = (0, 0, 0) + # --- the differential -------------------------------------------------- + diff = bpy.data.objects.new("dif", None) + bpy.context.collection.objects.link(diff) + diff.scale = (0, 0, 0) - jaula = bpy.data.objects.new("jaula", None) - bpy.context.collection.objects.link(jaula) - jaula.parent = dif - # caja de la jaula: dos bridas anulares y dos paredes curvas sobre el eje del - # perno. Los lados +-Y quedan abiertos: por ahi se ven los engranajes, que es - # como se ve una caja de diferencial de verdad - # todo lo de la jaula queda por dentro de r=0.52: el pinon nunca baja de - # r=0.59, y asi la jaula puede girar sin pasarle por encima + cage = bpy.data.objects.new("jaula", None) + bpy.context.collection.objects.link(cage) + cage.parent = diff + # carrier housing: two annular flanges and two curved walls around the pin + # axis. The +-Y sides stay open: that is where the gears show, which is how a + # real differential housing looks + # everything in the carrier stays inside r=0.52: the pinion never goes below + # r=0.59, so the carrier can spin without running over it for sx in (0.58, -0.58): - br = anillo_plano(f"brida{sx}", 0.13, 0.52, 0.08, M["fundido"]) + br = flat_ring(f"brida{sx}", 0.13, 0.52, 0.08, M["fundido"]) br.rotation_euler = (0, math.pi / 2, 0) br.location = (sx, 0, 0) - br.parent = jaula - for k, centro in enumerate((math.pi / 2, -math.pi / 2)): - pared = sector_anillo(f"pared{k}", 0.43, 0.52, 1.16, - centro - 0.62, centro + 0.62, M["fundido"]) + br.parent = cage + for k, center_pt in enumerate((math.pi / 2, -math.pi / 2)): + pared = ring_sector(f"pared{k}", 0.43, 0.52, 1.16, + center_pt - 0.62, center_pt + 0.62, M["fundido"]) pared.rotation_euler = (0, math.pi / 2, 0) - pared.parent = jaula - perno = cilindro("perno", 0.062, 1.00, M["acero2"]) - perno.parent = jaula + pared.parent = cage + bolt = cylinder("perno", 0.062, 1.00, M["acero2"]) + bolt.parent = cage - corona = engranaje_conico("corona", (1, 0, 0), N=N_COR, gamma=G_COR, + corona = bevel_gear("corona", (1, 0, 0), N=N_COR, gamma=G_COR, d_i=D_I, d_o=D_O, alto=0.042, mat=M["acero"], - espiral=0.62, espesor=0.14, hueco=0.58, - por_diente=24) + spiral=0.62, thickness=0.14, gap_m=0.58, + per_tooth=24) corona.location = (X_COR, 0, 0) - corona.parent = jaula - tornillos("bulones", 10, 0.78, -0.11, largo=0.10, r_t=0.035, - mat=M["acero2"], padre=jaula) + corona.parent = cage + screws("bulones", 10, 0.78, -0.11, largo=0.10, r_t=0.035, + mat=M["acero2"], padre=cage) lat = {} - for nom, eje, sx in (("izq", (-1, 0, 0), -1), ("der", (1, 0, 0), 1)): - g = bpy.data.objects.new(f"lat_{nom}", None) + for nm_key, axis_obj, sx in (("izq", (-1, 0, 0), -1), ("der", (1, 0, 0), 1)): + g = bpy.data.objects.new(f"lat_{nm_key}", None) bpy.context.collection.objects.link(g) - g.parent = dif - eng = engranaje_conico(f"eng_{nom}", eje, N=N_LAT, gamma=45.0, + g.parent = diff + eng = bevel_gear(f"eng_{nm_key}", axis_obj, N=N_LAT, gamma=45.0, d_i=0.26, d_o=0.50, alto=0.042, mat=M["acero"], - espiral=0.30, espesor=0.12, hueco=0.09) + spiral=0.30, thickness=0.12, gap_m=0.09) eng.parent = g - # semieje escalonado + brida - for (largo, radio, x0) in ((0.48, 0.110, 0.50), (EJE_X - 0.82, 0.080, 0.95)): - se = cilindro(f"se_{nom}_{radio}", radio, largo, M[f"eje_{nom[0]}"]) + # stepped half-shaft + flange + for (largo, radio, x0) in ((0.48, 0.110, 0.50), (AXIS_X - 0.82, 0.080, 0.95)): + se = cylinder(f"se_{nm_key}_{radio}", radio, largo, M[f"eje_{nm_key[0]}"]) se.rotation_euler = (0, math.pi / 2, 0) se.location = (sx * x0, 0, 0) se.parent = g - brida = anillo_plano(f"bw_{nom}", 0.09, 0.22, 0.07, M["acero2"]) - brida.rotation_euler = (0, math.pi / 2, 0) - brida.location = (sx * (EJE_X - 0.20), 0, 0) - brida.parent = g - rue = rueda_completa(f"rue_{nom}", M, R=R_RUEDA, r=0.185, ancho=0.28) - rue.location = (sx * EJE_X, 0, 0) - rue.parent = g - lat[nom] = g + flange = flat_ring(f"bw_{nm_key}", 0.09, 0.22, 0.07, M["acero2"]) + flange.rotation_euler = (0, math.pi / 2, 0) + flange.location = (sx * (AXIS_X - 0.20), 0, 0) + flange.parent = g + wheel_obj = full_wheel(f"rue_{nm_key}", M, R=R_WHEEL, r=0.185, width_px=0.28) + wheel_obj.location = (sx * AXIS_X, 0, 0) + wheel_obj.parent = g + lat[nm_key] = g sat = [] - for k, eje in enumerate(((0, 0, 1), (0, 0, -1))): + for k, axis_obj in enumerate(((0, 0, 1), (0, 0, -1))): g = bpy.data.objects.new(f"sat{k}", None) bpy.context.collection.objects.link(g) - g.parent = jaula - eng = engranaje_conico(f"eng_s{k}", eje, N=N_LAT, gamma=45.0, + g.parent = cage + eng = bevel_gear(f"eng_s{k}", axis_obj, N=N_LAT, gamma=45.0, d_i=0.26, d_o=0.50, alto=0.042, mat=M["acero2"], - espiral=-0.30, espesor=0.12, hueco=0.09, fase=math.pi) + spiral=-0.30, thickness=0.12, gap_m=0.09, phase=math.pi) eng.parent = g if k == 0: - p = esfera(f"testigo{k}", 0.050, material("m_test", "ambar", emis=3.0)) + p = sphere(f"testigo{k}", 0.050, material("m_test", "ambar", emit=3.0)) p.location = (0.30, 0.0, 0.42) p.parent = g sat.append(g) - entrada = bpy.data.objects.new("entrada", None) - bpy.context.collection.objects.link(entrada) - entrada.parent = dif - # misma cara que la corona, espiral de mano contraria y fase para que el - # diente caiga en el hueco - pinon = engranaje_conico("pinon", (0, -1, 0), N=N_PIN, gamma=G_PIN, + input_shaft = bpy.data.objects.new("entrada", None) + bpy.context.collection.objects.link(input_shaft) + input_shaft.parent = diff + # same face as the ring gear, opposite-hand spiral and a phase so the + # tooth lands in the gap + pinion = bevel_gear("pinon", (0, -1, 0), N=N_PIN, gamma=G_PIN, d_i=D_I, d_o=D_O, alto=0.042, mat=M["acero"], - espiral=P_ESP, espesor=0.12, hueco=0.07, - fase=P_FASE, por_diente=24) - pinon.location = (X_COR, 0, 0) - pinon.parent = entrada - cardan = cilindro("cardan", 0.095, 1.30, M["acero2"]) - cardan.rotation_euler = (math.pi / 2, 0, 0) - cardan.location = (X_COR, -1.50, 0) - cardan.parent = entrada - horquilla = anillo_plano("horquilla", 0.10, 0.24, 0.10, M["acero2"]) - horquilla.location = (X_COR, -1.20, 0) - horquilla.rotation_euler = (math.pi / 2, 0, 0) - horquilla.parent = entrada + spiral=P_ESP, thickness=0.12, gap_m=0.07, + phase=P_PHASE, per_tooth=24) + pinion.location = (X_COR, 0, 0) + pinion.parent = input_shaft + cardan_joint = cylinder("cardan", 0.095, 1.30, M["acero2"]) + cardan_joint.rotation_euler = (math.pi / 2, 0, 0) + cardan_joint.location = (X_COR, -1.50, 0) + cardan_joint.parent = input_shaft + fork = flat_ring("horquilla", 0.10, 0.24, 0.10, M["acero2"]) + fork.location = (X_COR, -1.20, 0) + fork.rotation_euler = (math.pi / 2, 0, 0) + fork.parent = input_shaft - barras = {} - for nom, c, z in (("izq", "rosa", -0.92), ("der", "verde", -0.60)): - riel = cilindro(f"riel_{nom}", 0.038, 1.50, material(f"mr_{nom}", "riel", rug=0.6)) - riel.rotation_euler = (0, math.pi / 2, 0) - riel.location = (0.90, -0.6, z) - b = cilindro(f"bar_{nom}", 0.060, 1.0, material(f"mb_{nom}", c, emis=2.6)) + bar_list = {} + for nm_key, c, z in (("izq", "rosa", -0.92), ("der", "verde", -0.60)): + rail = cylinder(f"riel_{nm_key}", 0.038, 1.50, material(f"mr_{nm_key}", "riel", rough=0.6)) + rail.rotation_euler = (0, math.pi / 2, 0) + rail.location = (0.90, -0.6, z) + b = cylinder(f"bar_{nm_key}", 0.060, 1.0, material(f"mb_{nm_key}", c, emit=2.6)) b.rotation_euler = (0, math.pi / 2, 0) - barras[nom] = (riel, b, z) - riel.scale = b.scale = (0, 0, 0) - fecha = texto("1827", tam=0.44, color="ambar") - fecha.scale = (0, 0, 0) + bar_list[nm_key] = (rail, b, z) + rail.scale = b.scale = (0, 0, 0) + date = txt_m("1827", size_u=0.44, color="ambar") + date.scale = (0, 0, 0) - def emision(mat, v, col=None): + def emission(mat, v, col=None): n = mat.node_tree.nodes["Principled BSDF"] n.inputs["Emission Strength"].default_value = v if col is not None: n.inputs["Emission Color"].default_value = (*srgb(col), 1) - return dict(cam=cam, M=M, emision=emision, piso=piso, arcos=arcos, - ruedas_a=ruedas_a, eje_a=eje_a, patina=patina, dif=dif, lat=lat, - jaula=jaula, sat=sat, entrada=entrada, pinon=pinon, - barras=barras, fecha=fecha) + return dict(cam=cam, M=M, emission=emission, floor_obj=floor_obj, arc_list=arc_list, + wheels_a=wheels_a, axis_a=axis_a, patina=patina, diff=diff, lat=lat, + cage=cage, sat=sat, input_shaft=input_shaft, pinion=pinion, + bar_list=bar_list, date=date) def main(): - T = Tiempo(NOMBRE) - ob = construir(T) - M, barras = ob["M"], ob["barras"] + T = Timeline(NAME_KEY) + ob = build_scene(T) + M, bar_list = ob["M"], ob["bar_list"] - def actualizar(f): + def refresh(f): t = T.t(f) - baja = suave(T.p(f, 2) / 0.62) + drop_by = suave(T.p(f, 2) / 0.62) dist = 50.0 / 36.0 * alto_en(T, f) - apuntar(ob["cam"], Vector((0.0, -1.1, 8.6)).lerp(DIR_CAM * dist, baja), - Vector((0.0, 0.0, 0.0)).lerp(Vector((0.0, 0.0, -0.50)), baja)) + aim_at(ob["cam"], Vector((0.0, -1.1, 8.6)).lerp(DIR_CAM * dist, drop_by), + Vector((0.0, 0.0, 0.0)).lerp(Vector((0.0, 0.0, -0.50)), drop_by)) - # ---- vista de arriba - vis_g = 1.0 - suave(T.p(f, 2) / 0.45) - ob["piso"].scale = (vis_g, vis_g, vis_g) - if vis_g > 0.001: - av = suave(T.p(f, 0) * 0.62) if f < T.rango(1)[0] else \ - mezcla(0.62, 1.0, T.p(f, 1)) + # ---- top view + visible_g = 1.0 - suave(T.p(f, 2) / 0.45) + ob["floor_obj"].scale = (visible_g, visible_g, visible_g) + if visible_g > 0.001: + av = suave(T.p(f, 0) * 0.62) if f < T.span(1)[0] else \ + mix_m(0.62, 1.0, T.p(f, 1)) th = -0.60 + 1.20 * av - centros = [] - for k, (cu, pts) in enumerate(ob["arcos"]): - rr = RADIO_GIRO + (TROCHA / 2) * (1 if k else -1) - c = Vector((-RADIO_GIRO + rr * math.cos(th), rr * math.sin(th), R_RUEDA)) - centros.append(c) + centers = [] + for k, (cu, pts) in enumerate(ob["arc_list"]): + rr = RADIO_GIRO + (TRACK_W / 2) * (1 if k else -1) + c = Vector((-RADIO_GIRO + rr * math.cos(th), rr * math.sin(th), R_WHEEL)) + centers.append(c) n = max(2, int(120 * av)) - rehacer_curva(cu, [pts], [[1.0 if i <= n else 0.30 for i in range(120)]]) - giro = (rr * (th + 0.60)) / R_RUEDA - if f >= T.rango(1)[0]: - rig = (RADIO_GIRO + TROCHA / 2) * (th + 0.60) / R_RUEDA - giro = mezcla(giro, rig, suave(T.p(f, 1) / 0.35)) - r = ob["ruedas_a"][k] + rebuild_curve(cu, [pts], [[1.0 if i <= n else 0.30 for i in range(120)]]) + giro = (rr * (th + 0.60)) / R_WHEEL + if f >= T.span(1)[0]: + rig = (RADIO_GIRO + TRACK_W / 2) * (th + 0.60) / R_WHEEL + giro = mix_m(giro, rig, suave(T.p(f, 1) / 0.35)) + r = ob["wheels_a"][k] r.location = c - r.rotation_euler = (giro, 0, th) # rueda sobre su eje y apunta al centro - medio = (centros[0] + centros[1]) / 2 - ob["piso"].location = (-medio.x, -medio.y - 0.30, 0.0) - ob["eje_a"].location = medio - ob["eje_a"].rotation_euler = (0, math.pi / 2, th) + r.rotation_euler = (giro, 0, th) # wheel on its axle, pointing at the centre + middle = (centers[0] + centers[1]) / 2 + ob["floor_obj"].location = (-middle.x, -middle.y - 0.30, 0.0) + ob["axis_a"].location = middle + ob["axis_a"].rotation_euler = (0, math.pi / 2, th) pv = suave(T.p(f, 1) / 0.4) - rr = RADIO_GIRO - TROCHA / 2 + rr = RADIO_GIRO - TRACK_W / 2 pts, rad = [], [] for i in range(60): a2 = -0.60 + (th + 0.60) * i / 59.0 pts.append((-RADIO_GIRO + rr * math.cos(a2), rr * math.sin(a2), 0.04)) rad.append(pv * min(1.0, (i / 59.0) * 2.4)) - rehacer_curva(ob["patina"], [pts], [rad]) + rebuild_curve(ob["patina"], [pts], [rad]) - # ---- el diferencial + # ---- the differential ap = suave((T.p(f, 2) - 0.35) / 0.5) - ob["dif"].scale = (ap, ap, ap) - ob["dif"].rotation_euler = (0, INCL, 0) - arranca = T.rango(6)[0] - tt = max(0.0, t - T.t(arranca)) - k_giro = mezcla(0.0, 0.42, T.p(f, 8) / 0.7) - ang_j = OMEGA * tt if f >= arranca else 0.0 + ob["diff"].scale = (ap, ap, ap) + ob["diff"].rotation_euler = (0, INCL, 0) + starts_at = T.span(6)[0] + tt = max(0.0, t - T.t(starts_at)) + k_giro = mix_m(0.0, 0.42, T.p(f, 8) / 0.7) + ang_j = OMEGA * tt if f >= starts_at else 0.0 ang_i = ang_j * (1.0 - k_giro) ang_d = ang_j * (1.0 + k_giro) - ob["jaula"].rotation_euler = (ang_j, 0, 0) + ob["cage"].rotation_euler = (ang_j, 0, 0) ob["lat"]["izq"].rotation_euler = (ang_i, 0, 0) ob["lat"]["der"].rotation_euler = (ang_d, 0, 0) for k, g in enumerate(ob["sat"]): g.rotation_euler = (0, 0, (ang_i - ang_d) / 2 * (1 if k == 0 else -1)) - ob["pinon"].rotation_euler = (0, P_SIG * ang_j * N_COR / N_PIN, 0) + ob["pinion"].rotation_euler = (0, P_NEXT * ang_j * N_COR / N_PIN, 0) - # ---- resaltados en los colores del canal, sobre el acero - def pico(i): + # ---- highlights in the channel colors, over the steel + def peak_y(i): p = T.p(f, i) return 0.85 * math.sin(math.pi * p) ** 2 if 0.0 < p < 1.0 else 0.0 - ob["emision"](M["eje_i"], pico(4), "rosa") - ob["emision"](M["eje_d"], pico(4), "verde") - ob["emision"](M["acero2"], pico(5), "celeste") - ob["emision"](M["fundido"], pico(5), "ambar") - ob["emision"](M["acero"], pico(6), "ambar") + ob["emission"](M["eje_i"], peak_y(4), "rosa") + ob["emission"](M["eje_d"], peak_y(4), "verde") + ob["emission"](M["acero2"], peak_y(5), "celeste") + ob["emission"](M["fundido"], peak_y(5), "ambar") + ob["emission"](M["acero"], peak_y(6), "ambar") - # ---- barras de velocidad + # ---- speed bars bv = suave(T.p(f, 9) / 0.4) * (1.0 - suave(T.p(f, 10) / 0.3)) - for nom, (riel, bar, z) in barras.items(): - riel.scale = (bv, bv, bv) - rel = (1.0 - k_giro) if nom == "izq" else (1.0 + k_giro) + for nm_key, (rail, bar, z) in bar_list.items(): + rail.scale = (bv, bv, bv) + rel = (1.0 - k_giro) if nm_key == "izq" else (1.0 + k_giro) L = 1.50 * rel / 1.5 bar.scale = (bv, bv, bv * L) bar.location = (0.15 + L / 2, -0.6, z) fv = suave((T.p(f, 10) - 0.25) / 0.4) - ob["fecha"].location = (0.90, 0.0, -0.80) - ob["fecha"].scale = (fv, fv, fv) + ob["date"].location = (0.90, 0.0, -0.80) + ob["date"].scale = (fv, fv, fv) - render_secuencia(NOMBRE, T, actualizar) + render_sequence(NAME_KEY, T, refresh) main() -- cgit v1.2.3