Created
September 1, 2023 22:19
-
-
Save pukpr/df719e2c7176b7a4d4466e01edb6d3d9 to your computer and use it in GitHub Desktop.
Blender orbits
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| https://chat.openai.com/share/7555f139-f9dc-4788-abbd-6e4b57b86a46 |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
import bpy
import math
Clear existing mesh objects
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
Create Earth, Moon, and Sun spheres
bpy.ops.mesh.primitive_uv_sphere_add(location=(0, 0, 0))
earth = bpy.context.active_object
earth.name = "Earth"
earth.scale = (1, 1, 1)
bpy.ops.mesh.primitive_uv_sphere_add(location=(10, 0, 0))
moon = bpy.context.active_object
moon.name = "Moon"
moon.scale = (0.25, 0.25, 0.25)
bpy.ops.mesh.primitive_uv_sphere_add(location=(-20, 0, 0))
sun = bpy.context.active_object
sun.name = "Sun"
sun.scale = (5, 5, 5)
Time parameters
seconds_per_year = 2 * 60 # 2 minutes in seconds
frames_per_second = 24 # Blender default
frames_per_year = seconds_per_year * frames_per_second
total_animation_frames = 10 * 60 * frames_per_second # 10 minutes
Set the end frame for the animation
bpy.context.scene.frame_end = total_animation_frames
Earth rotation and wobble
rotation_speed = 360 / frames_per_year # Degrees per frame
for frame in range(0, total_animation_frames + 1):
earth.rotation_euler[2] = rotation_speed * frame
# Add Chandler and annual wobble (simplified for visualization)
wobble_angle = math.sin(frame * 2 * math.pi / frames_per_year)
earth.rotation_euler[1] = 0.5 * wobble_angle # Adjust as needed
earth.keyframe_insert(data_path="rotation_euler", frame=frame)
moon_orbit_radius = 10 # Not to scale, for visualization
moon_orbit_speed = 2 * math.pi / (27.3 * frames_per_second) # Tropical orbit
for frame in range(0, total_animation_frames + 1):
moon_angle = moon_orbit_speed * frame
moon.location = (moon_orbit_radius * math.cos(moon_angle), moon_orbit_radius * math.sin(moon_angle), 0.5 * moon_orbit_radius * math.sin(moon_angle))
moon.keyframe_insert(data_path="location", frame=frame)
# Assuming the moon object is named 'Moon'
Assuming the moon object is named 'Moon'
moon = bpy.data.objects["Moon"]
Create or get a material for the moon
mat_name = "MoonIlluminatedMaterial"
if mat_name not in bpy.data.materials:
mat = bpy.data.materials.new(name=mat_name)
moon.data.materials.append(mat)
else:
mat = bpy.data.materials[mat_name]
Use nodes for the material
mat.use_nodes = True
nodes = mat.node_tree.nodes
Clear default nodes
for node in nodes:
nodes.remove(node)
Add a Principled BSDF shader and connect it to the Material Output
shader = nodes.new(type='ShaderNodeBsdfPrincipled')
shader.location = (0, 0)
shader.inputs["Alpha"].default_value = 0.5 # Set transparency
shader.inputs["Emission"].default_value = (1, 1, 1, 1) # Set emission color
material_output = nodes.new(type='ShaderNodeOutputMaterial')
material_output.location = (400, 0)
noodle = mat.node_tree.links.new
noodle(shader.outputs["BSDF"], material_output.inputs["Surface"])
Add a point light inside the moon for internal illumination
if "MoonInternalLight" not in bpy.data.objects:
bpy.ops.object.light_add(type='POINT', location=moon.location)
light = bpy.context.active_object
light.name = "MoonInternalLight"
light.data.energy = 500 # Adjust as necessary
light.parent = moon # Parent the light to the moon so it moves with it
sun_orbit_radius = 50 # Not to scale, for visualization
sun_orbit_speed = 2 * math.pi / frames_per_year
for frame in range(0, total_animation_frames + 1):
sun_angle = sun_orbit_speed * frame
sun.location = (sun_orbit_radius * math.cos(sun_angle), sun_orbit_radius * math.sin(sun_angle), 0.1 * sun_orbit_radius * math.sin(sun_angle))
sun.keyframe_insert(data_path="location", frame=frame)
Assuming the sphere is named 'Sphere'
sphere = bpy.data.objects["Earth"]
Create arrow shaft (cylinder)
bpy.ops.mesh.primitive_cylinder_add(location=(0, 0, 1.5))
arrow_shaft = bpy.context.active_object
arrow_shaft.name = "ArrowShaft"
arrow_shaft.scale = (0.1, 0.1, 1)
Create arrowhead (cone)
bpy.ops.mesh.primitive_cone_add(vertices=32, radius1=0.3, depth=0.6, location=(0, 0, 2.5))
arrowhead = bpy.context.active_object
arrowhead.name = "Arrowhead"
Join arrow shaft and arrowhead to make a single arrow object
bpy.ops.object.select_all(action='DESELECT')
arrow_shaft.select_set(True)
arrowhead.select_set(True)
bpy.context.view_layer.objects.active = arrow_shaft
bpy.ops.object.join()
Rename the joined arrow object
arrow = bpy.context.active_object
arrow.name = "Arrow"
Position the arrow at the sphere's north pole
arrow.location = sphere.location
arrow.location[2] += sphere.dimensions[2] / 2 + arrow.dimensions[2] / 2
Parent the arrow to the sphere so that it moves with the sphere
arrow.parent = sphere
Assuming the sphere is named 'Earth'
earth = bpy.data.objects["Earth"]
Create the ecliptic plane
bpy.ops.mesh.primitive_plane_add(size=earth.dimensions[0]*2.5, location=earth.location)
ecliptic_plane = bpy.context.active_object
ecliptic_plane.name = "EclipticPlane"
Rotate the plane to represent the inclination of the ecliptic (approximately 23.5 degrees)
bpy.ops.transform.rotate(value=-0.409, orient_axis='Y')
Assign a semi-transparent material to the plane
if "EclipticMaterial" not in bpy.data.materials:
mat = bpy.data.materials.new(name="EclipticMaterial")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Alpha"].default_value = 0.5 # 50% transparency
bsdf.inputs["Base Color"].default_value = (0.5, 0.5, 1, 1) # Blue color
else:
mat = bpy.data.materials["EclipticMaterial"]
ecliptic_plane.data.materials.append(mat)
Parent the ecliptic plane to the sphere so that it moves with the sphere
ecliptic_plane.parent = earth
Create and position the text object
bpy.ops.object.text_add(location=(0, 0, 5))
text_object = bpy.context.active_object
text_object.name = "TimeText"
text_object.data.body = "Day: 0"
Scale and adjust the text for better visibility
text_object.scale = (0.5, 0.5, 0.5)
def create_vertical_line_for_object(obj_name):
obj = bpy.data.objects[obj_name]
Create the line segment (using a cylinder)
Create vertical lines for the Moon and Sun
create_vertical_line_for_object("Moon")
create_vertical_line_for_object("Sun")
Assuming the sun object is named 'Sun'
sun = bpy.data.objects["Sun"]
Compute the radius of the sun's pseudo-orbit (distance from the origin)
radius = sun.location.length
Create the circular sheet
bpy.ops.mesh.primitive_circle_add(radius=radius, location=(0, 0, 0))
circle_sheet = bpy.context.active_object
circle_sheet.name = "CircularSheet"
Convert the circle to a mesh (fill it)
bpy.ops.object.editmode_toggle()
bpy.ops.mesh.fill()
bpy.ops.object.editmode_toggle()
Create or get a semi-transparent material for the circular sheet
mat_name = "TransparentMaterial"
if mat_name not in bpy.data.materials:
mat = bpy.data.materials.new(name=mat_name)
mat.use_nodes = True
nodes = mat.node_tree.nodes
# Clear default nodes
for node in nodes:
nodes.remove(node)
# Add a Principled BSDF shader and connect it to the Material Output
shader = nodes.new(type='ShaderNodeBsdfPrincipled')
shader.location = (0, 0)
shader.inputs["Alpha"].default_value = 0.8 # 50% transparency
material_output = nodes.new(type='ShaderNodeOutputMaterial')
material_output.location = (400, 0)
noodle = mat.node_tree.links.new
noodle(shader.outputs["BSDF"], material_output.inputs["Surface"])
else:
mat = bpy.data.materials[mat_name]
circle_sheet.data.materials.append(mat)