Python library for importing Wavefront .obj files and generating interleaved vertex data ready for rendering.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Optional OpenGL-based visualization using pyglet for displaying loaded 3D models. Supports lighting, textures, and various rendering modes.
The visualization module requires pyglet:
pip install pyglet
# or install with visualization extras
pip install PyWavefront[visualization]High-level drawing functions for rendering Wavefront objects, materials, and material collections.
def draw(
instance,
lighting_enabled: bool = True,
textures_enabled: bool = True
) -> None:
"""
Generic draw function for various PyWavefront objects.
Parameters:
- instance: Wavefront, Material, or dict of materials to draw
- lighting_enabled: Enable OpenGL lighting calculations
- textures_enabled: Enable texture mapping
Supports:
- Wavefront objects (draws all materials)
- Individual Material objects
- Dictionary of materials {name: material}
"""
def draw_materials(
materials: Dict[str, Material],
lighting_enabled: bool = True,
textures_enabled: bool = True
) -> None:
"""
Draw a dictionary of materials.
Parameters:
- materials: Dictionary mapping material names to Material objects
- lighting_enabled: Enable lighting
- textures_enabled: Enable textures
"""
def draw_material(
material: Material,
face = GL_FRONT_AND_BACK,
lighting_enabled: bool = True,
textures_enabled: bool = True
) -> None:
"""
Draw a single material with OpenGL.
Parameters:
- material: Material object to render
- face: OpenGL face culling mode (GL_FRONT, GL_BACK, GL_FRONT_AND_BACK)
- lighting_enabled: Enable lighting calculations
- textures_enabled: Enable texture mapping
Automatically handles:
- Vertex format interpretation
- Texture binding and application
- Material property setup (diffuse, ambient, specular)
- OpenGL state management
"""The visualization module supports the following vertex formats:
V3F - Positions onlyC3F_V3F - Colors + positionsN3F_V3F - Normals + positionsT2F_V3F - Texture coordinates + positionsT2F_C3F_V3F - Texture coordinates + colors + positionsT2F_N3F_V3F - Texture coordinates + normals + positionsNote: Some formats like C3F_N3F_V3F and T2F_C3F_N3F_V3F are not supported by pyglet and will raise a ValueError.
The visualization system automatically handles texture loading and binding:
def bind_texture(texture: Texture) -> None:
"""
Bind a texture for OpenGL rendering.
Automatically loads texture from file if not already loaded.
"""Texture Features:
Material properties are automatically applied during rendering:
Lighting Properties:
material.diffuse)material.ambient)material.specular)material.emissive)material.shininess)Transparency:
material.transparencyimport pyglet
from pyglet.gl import *
import pywavefront
from pywavefront import visualization
# Load a 3D model
model_path = 'path/to/model.obj'
scene = pywavefront.Wavefront(model_path)
# Create a pyglet window
window = pyglet.window.Window(width=800, height=600, resizable=True)
# Setup OpenGL lighting
def setup_lighting():
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
# Light position
light_pos = (GLfloat * 4)(1.0, 1.0, 1.0, 0.0)
glLightfv(GL_LIGHT0, GL_POSITION, light_pos)
# Light colors
white_light = (GLfloat * 4)(1.0, 1.0, 1.0, 1.0)
glLightfv(GL_LIGHT0, GL_DIFFUSE, white_light)
glLightfv(GL_LIGHT0, GL_SPECULAR, white_light)
@window.event
def on_resize(width, height):
"""Handle window resize."""
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, width / height, 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
return True
@window.event
def on_draw():
"""Render the scene."""
window.clear()
glLoadIdentity()
# Setup camera
glTranslatef(0.0, 0.0, -5.0)
glRotatef(rotation_x, 1.0, 0.0, 0.0)
glRotatef(rotation_y, 0.0, 1.0, 0.0)
# Setup lighting
setup_lighting()
# Enable depth testing
glEnable(GL_DEPTH_TEST)
# Draw the model
visualization.draw(scene, lighting_enabled=True, textures_enabled=True)
# Animation variables
rotation_x = 0
rotation_y = 0
def update(dt):
"""Update animation."""
global rotation_y
rotation_y += 30 * dt # Rotate 30 degrees per second
# Start the rendering loop
pyglet.clock.schedule(update)
pyglet.app.run()# Draw only specific materials
materials_to_draw = {
'metal': scene.materials['metal_material'],
'glass': scene.materials['glass_material']
}
visualization.draw_materials(materials_to_draw)
# Draw individual materials with custom settings
for name, material in scene.materials.items():
if 'transparent' in name:
# Disable lighting for transparent materials
visualization.draw_material(material, lighting_enabled=False)
else:
visualization.draw_material(material)# Disable textures for wireframe-like rendering
visualization.draw(scene, textures_enabled=False)
# Disable lighting for unlit rendering
visualization.draw(scene, lighting_enabled=False)
# Draw with back-face culling
for material in scene.materials.values():
visualization.draw_material(material, face=GL_FRONT)The visualization module automatically manages OpenGL state:
Enabled States:
GL_CULL_FACE - Back-face cullingGL_DEPTH_TEST - Depth buffer testingGL_LIGHTING - When lighting_enabled=TrueGL_TEXTURE_2D - When textures are availableAutomatic Cleanup:
GL_CLIENT_VERTEX_ARRAY_BIT)GL_CURRENT_BIT, GL_ENABLE_BIT, GL_LIGHTING_BIT)try:
visualization.draw(scene)
except ValueError as e:
if "not supported by pyglet" in str(e):
print(f"Unsupported vertex format: {e}")
# Handle unsupported vertex format
else:
raiseCommon issues:
C3F_N3F_V3F)Optimization Tips:
Memory Management:
material.gl_floats)Install with Tessl CLI
npx tessl i tessl/pypi-pywavefront