Getting Started Pyglet - ZackWilde27/Z3dPy GitHub Wiki

I recommend PyGame since it's faster at drawing, but to use Pyglet:

Getting Started

I'll import the library and use Pyglet for the screen.

import pyglet
import z3dpy as zp

# Initialize Pyglet
screen = pyglet.window.Window()
myBatch = pyglet.graphics.Batch()

Set the render size to match the output screen

zp.screenSize = (screen.width, screen.height)

Pyglet's Y is the right-way-up, so the image will be upside down. To fix this:

# Negate both the FOV, and aspect ratio
zp.FindHowVars(-90, -(screen.height/screen.width))

Next create a camera, with the desired location.

# z3dpy.Cam(vPos)
myCamera = zp.Cam([0, 0, 0])
# Vectors are lists: [x, y, z]

Now load a mesh to draw, I'll use the built-in susanne.

# LoadMesh(filename, *vPos, *VScale)
myMesh = zp.LoadMesh("z3dpy/mesh/susanne.obj", [0, 0, 2])
# Z is forward in this case, so it's placed in front of the camera

Rendering 3D in Z3dPy takes 3 steps:

  • Set the internal camera
  • Rastering
  • Drawing Triangles
# Set the internal camera
zp.SetInternalCam(myCamera)

# Rastering
triangles = [pyglet.shapes.Triangle(tri[0][0], tri[0][1], tri[1][0], tri[1][1], tri[2][0], tri[2][1], color=zp.TriGetColour(tri), batch=myBatch) for tri in zp.RasterMeshList(myMesh)]

# Drawing Triangles
myBatch.draw()

In this case, I want the colour of the triangle to represent it's normal value:

  • Convert the normal to colour and flip it using a VectorMulF(, -255).

  • Pyglet only accepts integer colours, so a VectorFloor() is needed as well

  • Also, values below 0 are absolute'd, so a VectorMaxF(, 0) needs to wrap the whole thing.

color=zp.VectorMaxF(zp.VectorFloor(zp.VectorMulF(zp.TriGetNormal(tri), -255)), 0)

Lastly, chuck it in an on_draw and run it:

# Since the camera isn't going to move we can set the internal camera outside the loop
zp.SetInternalCam(myCamera)

@screen.event
def on_draw:
    # Clear the screen
    screen.clear()

    # Render 3D
    triangles = [pyglet.shapes.Triangle(tri[0][0], tri[0][1], tri[1][0], tri[1][1], tri[2][0], tri[2][1], color=zp.VectorMaxF(zp.VectorFloor(zp.VectorMulF(zp.TriGetNormal(tri), -255)), 0), batch=myBatch) for tri in zp.RasterMeshList(myMesh)]


    # Update display afterwards
    myBatch.draw()

    # Rotate Mesh
    # MeshAddRot(mesh, vector)
    zp.MeshAddRot(myMesh, [1, 4, 5])

pyglet.app.run()

Final script:

import pyglet
import z3dpy as zp

screen = pyglet.window.Window()
myBatch = pyglet.graphics.Batch()

# Set the render size to match the output screen
zp.screenSize(screen.width, screen.height)

# Negate both the FOV, and aspect ratio
zp.FindHowVars(-90, -(screen.height/screen.width))

# z3dpy.Cam(vPos)
myCamera = zp.Cam([0, 0, 0])

# Since the camera isn't going to move we can set the internal camera outside the loop
zp.SetInternalCam(myCamera)

# LoadMesh(filename, *vPos, *VScale)
myMesh = zp.LoadMesh("z3dpy/mesh/susanne.obj", [0, 0, 2])

@screen.event
def on_draw:
    # Clear the screen
    screen.clear()

    # Render 3D
    triangles = [pyglet.shapes.Triangle(tri[0][0], tri[0][1], tri[1][0], tri[1][1], tri[2][0], tri[2][1], color=zp.VectorMaxF(zp.VectorFloor(zp.VectorMulF(zp.TriGetNormal(tri), -255)), 0), batch=myBatch) for tri in zp.RasterMeshList(myMesh)]

    # Update display afterwards
    myBatch.draw()
    
    # Rotate Mesh
    zp.MeshAddRot(myMesh, [1, 4, 5])

pyglet.app.run()