Three meshing gears turning at their gear ratios, 48 frames on EEVEE (MP4). A real render from the production GPU, the bpy script that produced it, the settings and the GPU seconds. Pass the script's URL as scene_url to get the same result.
| Prompt | Render frames 1-48 of https://render.janction.jp/samples/ex24_gear_train.py at 1280x720 on EEVEE as an MP4, studio preset (edit TEETH for other ratios). |
|---|---|
| MCP call | render_final(scene_url="https://render.janction.jp/samples/ex24_gear_train.py", frame_start=1, frame_end=48, width=1280, height=720, samples=64, engine="eevee", output="mp4", fps=24, environment="studio") |
| GPU s / round trip | 54.8 s / 22 s |
| Price at 0.1 JPY per GPU-second | 5.5 JPY (0 while the free time covers it) |
| Rendered on | 2026-10-22 |
| Blender | 5.0 |
ChatGPT · Claude · Grok · Perplexity
Use JANCTION Render (MCP server https://render.janction.jp/mcp) to render this example: render_preview(scene_url="https://render.janction.jp/samples/ex24_gear_train.py"). Then suggest how to change the colors, shapes and camera for my own subject. Ask me before the final render.
Each link opens the app with the text below filled in (if it is not, copy and paste it). If JANCTION Render is not connected in that app yet, add https://render.janction.jp/mcp as a connector first.
| frame_start | 1 |
|---|---|
| frame_end | 48 |
| width | 1280 |
| height | 720 |
| samples | 64 |
| denoise | True |
| engine | eevee |
| output | mp4 |
| fps | 24 |
| environment | studio |
ex24_gear_train.py. It builds the scene, the camera and the frame range; resolution, samples, denoising and the GPU are set by the service.
"""JANCTION Render example 24: three meshing gears turning at their gear ratios (48 frames, EEVEE, MP4).
Reproduce: render_final(scene_url="https://render.janction.jp/samples/ex24_gear_train.py",
frame_start=1, frame_end=48, width=1280, height=720, engine="eevee", output="mp4",
environment="studio")
Gears are built from a disc plus box teeth; each gear turns at -teeth_driver/teeth so the teeth stay
meshed (change TEETH to try other ratios). Linear keyframes, so the loop is seamless.
"""
import math
import bpy
for ob in list(bpy.data.objects):
bpy.data.objects.remove(ob, do_unlink=True)
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 48
scene.render.fps = 24
bpy.context.preferences.edit.keyframe_new_interpolation_type = "LINEAR"
MODULE = 0.12 # 歯の大きさ(ピッチ円の半径 = MODULE * 歯数 / 2)
TEETH = [24, 12, 18] # 左から: 駆動・小・中
def material(name, color, metallic=0.9, roughness=0.3):
mat = bpy.data.materials.new(name)
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (*color, 1.0)
bsdf.inputs["Metallic"].default_value = metallic
bsdf.inputs["Roughness"].default_value = roughness
return mat
def gear(name, teeth, location, mat):
r = MODULE * teeth / 2
bpy.ops.mesh.primitive_cylinder_add(vertices=max(32, teeth * 4), radius=r - MODULE * 0.4, depth=0.25, location=location)
body = bpy.context.active_object
body.name = name
parts = [body]
for i in range(teeth):
a = 2 * math.pi * i / teeth
bpy.ops.mesh.primitive_cube_add(size=1, location=(location[0] + r * math.cos(a), location[1] + r * math.sin(a), location[2]))
t = bpy.context.active_object
t.scale = (MODULE * 1.1, MODULE * 0.75, 0.25)
t.rotation_euler = (0, 0, a)
parts.append(t)
bpy.ops.object.select_all(action="DESELECT")
for p in parts:
p.select_set(True)
bpy.context.view_layer.objects.active = body
bpy.ops.object.join()
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
body.data.materials.append(mat)
bevel = body.modifiers.new("Bevel", "BEVEL")
bevel.width = 0.015
bevel.segments = 2
bpy.ops.object.shade_auto_smooth()
# 軸は黒い別の部品(歯車の子にして一緒に回す)
bpy.ops.mesh.primitive_cylinder_add(vertices=32, radius=r * 0.16, depth=0.36, location=location)
axle = bpy.context.active_object
axle.name = name + "Axle"
axle.data.materials.append(AXLE)
axle.parent = body
axle.matrix_parent_inverse = body.matrix_world.inverted()
return body
AXLE = material("Axle", (0.02, 0.02, 0.025), metallic=0.6, roughness=0.4)
mats = [material("Brass", (0.85, 0.62, 0.25)), material("Steel", (0.75, 0.77, 0.8)), material("Copper", (0.85, 0.42, 0.28))]
radii = [MODULE * t / 2 for t in TEETH]
x = [0.0]
x.append(x[0] + radii[0] + radii[1])
x.append(x[1] + radii[1] + radii[2])
center = (x[0] + x[2]) / 2
gears = []
for i, (t, xi) in enumerate(zip(TEETH, x)):
g = gear(f"Gear{i + 1}", t, (xi - center, 0, 0), mats[i])
gears.append(g)
# 噛み合わせ: 隣の歯車は逆回り、角速度は歯数に反比例。2 枚目は半歯ずらして歯と溝を合わせる
turn = 2 * math.pi / 4 # 駆動の歯車が 48 コマで 1/4 回転
phase = [0.0, math.pi / TEETH[1], 0.0]
for i, g in enumerate(gears):
speed = (TEETH[0] / TEETH[i]) * (-1) ** i
g.rotation_euler = (0, 0, phase[i])
g.keyframe_insert("rotation_euler", frame=1)
g.rotation_euler = (0, 0, phase[i] + turn * speed * 48 / 47)
g.keyframe_insert("rotation_euler", frame=48)
bpy.ops.mesh.primitive_plane_add(size=30, location=(0, 0, -0.14))
floor = bpy.context.active_object
floor.data.materials.append(material("Floor", (0.08, 0.085, 0.1), metallic=0.0, roughness=0.6))
bpy.ops.object.light_add(type="AREA", location=(2, -3, 5))
key = bpy.context.active_object
key.data.energy = 900
key.data.size = 4
bpy.ops.object.camera_add(location=(0.6, -11.0, 8.6))
cam = bpy.context.active_object
cam.data.lens = 50
target = bpy.data.objects.new("Target", None)
scene.collection.objects.link(target)
target.location = (0, 0, 0)
track = cam.constraints.new("TRACK_TO")
track.target = target
scene.camera = cam
JANCTION Render v0.4.209 · JasmyLab Inc. · Updated 2026-10-26 · Tested with Blender 3.6 / 4.2 / 4.5 / 5.0 / 5.2, JANCTION Render 0.4.209 · 日本語