aboutsummaryrefslogtreecommitdiffstats
path: root/blender/diferencial.py
diff options
context:
space:
mode:
authorElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
committerElvis Claros Castro <elvis@claros.ar>2026-09-26 20:50:41 -0300
commitfafaebb051907a848a9406f9da19669c81a83a3b (patch)
treec30ea26e6b549e5523af2bae5c39569e9a946b12 /blender/diferencial.py
parent59355909f2de9236af8168a26c70bcf6caa3b285 (diff)
download100cia-videos-main.tar.gz
100cia-videos-main.zip
Translate code, comments and logs to English; English README; configurable paths and env varsHEADmain
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.
Diffstat (limited to 'blender/diferencial.py')
-rw-r--r--blender/diferencial.py388
1 files changed, 194 insertions, 194 deletions
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()