CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pywavefront

Python library for importing Wavefront .obj files and generating interleaved vertex data ready for rendering.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

visualization.mddocs/

Visualization and Rendering

Optional OpenGL-based visualization using pyglet for displaying loaded 3D models. Supports lighting, textures, and various rendering modes.

Installation Requirements

The visualization module requires pyglet:

pip install pyglet
# or install with visualization extras
pip install PyWavefront[visualization]

Capabilities

Drawing Functions

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
    """

Supported Vertex Formats

The visualization module supports the following vertex formats:

  • V3F - Positions only
  • C3F_V3F - Colors + positions
  • N3F_V3F - Normals + positions
  • T2F_V3F - Texture coordinates + positions
  • T2F_C3F_V3F - Texture coordinates + colors + positions
  • T2F_N3F_V3F - Texture coordinates + normals + positions

Note: Some formats like C3F_N3F_V3F and T2F_C3F_N3F_V3F are not supported by pyglet and will raise a ValueError.

Texture Management

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:

  • Automatic texture loading from file paths
  • Support for various image formats (PNG, JPEG, BMP, etc.)
  • Non-power-of-two (NPOT) texture support
  • Automatic texture coordinate application
  • Fallback to ambient textures when diffuse unavailable

Material Rendering

Material properties are automatically applied during rendering:

Lighting Properties:

  • Diffuse color (material.diffuse)
  • Ambient color (material.ambient)
  • Specular color (material.specular)
  • Emissive color (material.emissive)
  • Shininess (material.shininess)

Transparency:

  • Alpha blending based on material.transparency
  • Proper depth sorting for transparent objects

Complete Rendering Example

import 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()

Selective Material Rendering

# 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)

Rendering Control

# 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)

OpenGL State Management

The visualization module automatically manages OpenGL state:

Enabled States:

  • GL_CULL_FACE - Back-face culling
  • GL_DEPTH_TEST - Depth buffer testing
  • GL_LIGHTING - When lighting_enabled=True
  • GL_TEXTURE_2D - When textures are available

Automatic Cleanup:

  • Client vertex array state (GL_CLIENT_VERTEX_ARRAY_BIT)
  • Current OpenGL state (GL_CURRENT_BIT, GL_ENABLE_BIT, GL_LIGHTING_BIT)

Error Handling

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:
        raise

Common issues:

  • Unsupported vertex formats (e.g., C3F_N3F_V3F)
  • Missing pyglet installation
  • Texture loading failures
  • OpenGL context issues

Performance Considerations

Optimization Tips:

  • Use vertex buffer objects (VBOs) for large models
  • Batch materials with similar properties
  • Minimize texture binding changes
  • Use appropriate level-of-detail (LOD) for distant objects
  • Consider frustum culling for complex scenes

Memory Management:

  • Materials automatically cache OpenGL float arrays (material.gl_floats)
  • Textures are loaded once and reused
  • Vertex data is shared between materials when possible

Install with Tessl CLI

npx tessl i tessl/pypi-pywavefront

docs

configuration.md

file-loading.md

index.md

materials.md

mesh-operations.md

visualization.md

tile.json