Basic Usage¶
The following code will load a 3D mesh and display it.
import pygame
from ntracer import NTracer
from ntracer.pygame_render import PygameRenderer
from ntracer import wavefront_obj
ntracer = NTracer(3)
data = wavefront_obj.load_obj('monkey.obj')
scene = ntracer.build_composite_scene(data)
camera = ntracer.Camera()
camera.translate(ntracer.Vector.axis(2,-5))
scene.set_camera(camera)
pygame.display.init()
screen = pygame.display.set_mode((800,600))
render = PygameRenderer()
render.begin_render(screen,scene)
while True:
e = pygame.event.wait()
if e.type == PygameRenderer.ON_COMPLETE:
pygame.display.flip()
if e.type == pygame.QUIT:
render.abort_render()
break
Here is a breakdown of the code:
import pygame
from ntracer import NTracer, build_composite_scene
from ntracer.pygame_render import PygameRenderer
from ntracer import wavefront_obj
First we import what we need.
ntracer = NTracer(3)
Next we create an NTracer
object. This is a helper class for
creating multiple objects with the same dimension. It provides the same
interface as the tracern
module except all methods and functions
that have a dimension parameter are wrapped so that the number passed to
NTracer’s constructor is automatically used for that parameter.
data = wavefront_obj.load_obj('monkey.obj')
We then load a mesh called monkey.obj
. The data returned is a list of
PrimitivePrototype
objects. Note that the Wavefront OBJ loader only
loads 3D meshes. It’s not very useful in the context of hyperspace, but it’s a
very simple format and is included for testing and as an example for creating
geometry.
data = ntracer.build_composite_scene(data)
We create a Scene
object from it.
camera = ntracer.Camera()
We create a new camera which will be the view-port of our scene.
camera.translate(ntracer.Vector.axis(2,-5))
We move the camera back 5 units. The vector by which to move the camera is
created using the static method axis
, which takes an axis index (0-based)
and a magnitude to create a vector parallel to the given axis with the given
magnitude. We could have used camera.translate(ntracer.Vector(0,0,-5))
or even camera.translate((0,0,-5))
instead, but doing it this way makes
the code dimension-agnostic.
scene.set_camera(camera)
We then set the scene’s camera to a copy of camera
. Note that a scene cannot
be modified while it is being drawn. Attempting to do so will raise an
exception.
pygame.display.init()
screen = pygame.display.set_mode((800,600))
We initialize Pygame and create our window.
render = PygameRenderer()
render.begin_render(screen,scene)
Then a renderer is created and the drawing is started. By default, the renderer will use as many threads as there are processing cores, but you can specify a different number of threads in its constructor.
while True:
e = pygame.event.wait()
if e.type == PygameRenderer.ON_COMPLETE:
pygame.display.flip()
elif e.type == pygame.QUIT:
render.abort_render()
break
Finally, we have a basic event loop. When the renderer is finished, it sends an
event of type PygameRenderer.ON_COMPLETE
(which is equal to
pygame.USEREVENT by default). The event will have a source
attribute
containing the associated renderer. Having only one renderer, we don’t use it
here. We flip the display buffer to make our image appear.
abort_render()
is called to stop drawing early.