PyBevy is in an early and experimental stage. The API is incomplete, subject to breaking changes without notice, and you should expect bugs. Many features are still under development.
Simple 3D Scene
A simple 3D scene with a light shining over a cube on a plane.
Introduction
This example demonstrates how to set up a basic 3D scene in PyBevy. It includes creating a ground plane, a cube, a light source, and a camera to view the scene. This is a great starting point for understanding the core concepts of creating 3D worlds.
Setup
First, we import the necessary components from the pybevy library and the math module for some calculations. The * import is used here for simplicity in this
small example.
from pybevy.prelude import *
from math import pi
FRAC_PI_2 = pi / 2.0Scene Creation Function
This is the main function where we define all the objects (or "entities") in our scene. It takes Commands, Meshes, and Materials as input, which are provided by
the PyBevy engine to allow us to create new objects and define their appearance.
# Set up a simple 3D scene
def setup(
commands: Commands,
meshes: ResMut[Assets[Mesh]],
materials: ResMut[Assets[StandardMaterial]],
) -> None:Spawning the Ground Plane
First, we create a ground plane for our objects to sit on.
- We use
commands.spawn()to create a new entity. Mesh3d(meshes.add(Circle(4.0)))defines its shape as a circle with a radius of 4.0.MeshMaterial3d(materials.add(Color.WHITE))gives it a simple white material.Transform.from_rotation(...)rotates the circle so it lies flat, forming our ground plane.
# circular base
commands.spawn(
Mesh3d(meshes.add(Circle(4.0))),
MeshMaterial3d(materials.add(Color.WHITE)),
Transform.from_rotation(Quat.from_rotation_x(-FRAC_PI_2)),
)Spawning the Cube
Next, we add a cube to the scene.
Mesh3d(meshes.add(Cuboid.from_length(1.0)))defines its shape as a cuboid with sides of length 1.0.MeshMaterial3d(materials.add(Color.srgb_u8(124, 144, 255)))gives it a nice blue color.Transform.from_xyz(0.0, 0.5, 0.0)positions the cube at the center of the scene, slightly elevated so it rests on top of the plane.
# cube
commands.spawn(
Mesh3d(meshes.add(Cuboid.from_length(1.0))),
MeshMaterial3d(materials.add(Color.srgb_u8(124, 144, 255))),
Transform.from_xyz(0.0, 0.5, 0.0),
)Adding a Light Source
A scene needs light to be visible. Here, we add a PointLight.
PointLight(shadows_enabled=True)creates a light source that emanates from a single point and is capable of casting shadows.Transform.from_xyz(4.0, 8.0, 4.0)positions the light up and to the side, so it casts interesting shadows across our objects.
# light
commands.spawn(
PointLight(shadows_enabled=True),
Transform.from_xyz(4.0, 8.0, 4.0),
)Positioning the Camera
Finally, we set up a camera so we can view the scene.
Camera3d()creates a standard 3D perspective camera.Transform.from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3.ZERO, Vec3.Y)positions the camera at a specific point in space and directs it to look at the origin (Vec3.ZERO), with its "up" direction aligned with the Y-axis.
# camera
commands.spawn(
Camera3d(),
Transform.from_xyz(-2.5, 4.5, 9.0).looking_at(Vec3.ZERO, Vec3.Y),
)Running the Application
This is the entry point of our script. We create a new App, add the default plugins (which handle things like windowing and rendering), register our setup
function to run at startup, and then start the application loop.
@entrypoint
def main(app: App) -> App:
return app.add_plugins(DefaultPlugins).add_systems(Startup, setup)
if __name__ == "__main__":
main().run()