Trophy ๐Ÿ†

April 23, 2026 ยท View on GitHub

Terminal 3D Model Viewer - View OBJ, GLB, and STL files directly in your terminal.

Trophy Demo

Features

  • OBJ, GLB & STL Support - Load standard 3D model formats
  • Embedded Textures - Automatically extracts and applies GLB textures
  • Interactive Controls - Rotate, zoom, and spin models with mouse/keyboard
  • Software Rendering - No GPU required, works over SSH
  • Springy Physics - Smooth, satisfying rotation with momentum

Installation

go install github.com/taigrr/trophy/cmd/trophy@latest

Usage

trophy model.glb              # View a GLB model
trophy model.obj              # View an OBJ model
trophy model.stl              # View an STL model
trophy info model.glb         # Show model stats without opening the viewer
trophy -texture tex.png model.obj  # Apply custom texture
trophy -bg 0,0,0 model.glb    # Black background
trophy -bg '#101820' model.glb # Hex background color
trophy -fps 60 model.glb      # Higher framerate

Controls

InputAction
Mouse dragRotate model
Scroll wheelZoom in/out
W/SPitch up/down
A/DYaw left/right
Q/ERoll
SpaceToggle spin mode
+/-Zoom
RReset view
TToggle texture
XToggle wireframe
BToggle backface cull
LPosition light
?Toggle HUD overlay
EscQuit

Lighting

Press L to enter lighting mode and drag to reposition the light source in real-time:

Lighting Demo

Library Usage

Trophy's rendering packages can be used as a library:

import (
    "github.com/taigrr/trophy/pkg/models"
    "github.com/taigrr/trophy/pkg/render"
    "github.com/taigrr/trophy/pkg/math3d"
)

// Load a model
mesh, texture, _ := models.LoadGLBWithTexture("model.glb")

// Create renderer
fb := render.NewFramebuffer(320, 200)
camera := render.NewCamera()
rasterizer := render.NewRasterizer(camera, fb)

// Render (uses optimized edge-function rasterizer)
rasterizer.DrawMeshTexturedOpt(mesh, transform, texture, lightDir)

Packages

  • pkg/math3d - 3D math (Vec2, Vec3, Vec4, Mat4)
  • pkg/models - Model loaders (OBJ, GLB/GLTF, STL)
  • pkg/render - Software rasterizer, camera, textures

Benchmarks

Run with go test -bench=. -benchmem ./...

Math (pkg/math3d)

Benchmarkns/opB/opallocs/op
Mat4Mul74.8600
Mat4MulVec46.8400
Mat4MulVec38.2400
Mat4Inverse62.1300
Vec3Normalize7.4100
Vec3Cross2.4700
Vec3Dot2.4800
Perspective24.1500
LookAt33.6600
ViewProjection71.3200

Rendering (pkg/render)

Benchmarkns/opB/opallocs/op
FrustumExtract37.0300
AABBIntersection (visible)9.9600
AABBIntersection (culled)7.7600
TransformAABB125.800
FrustumIntersectAABB7.3100
FrustumIntersectsSphere4.9100
DrawTriangleGouraud485800
DrawTriangleGouraudOpt398100
DrawMeshGouraud5574100
DrawMeshGouraudOpt2786800

Culling Performance

Benchmarkns/opB/opallocs/op
MeshRendering (with culling)11579300
MeshRendering (without culling)14176600

The optimized rasterizer (*Opt variants) uses incremental edge functions instead of per-pixel barycentric recomputation, yielding ~18% speedup on triangles and ~50% speedup on full mesh rendering.

Benchmarks run on AMD EPYC 7642 48-Core, linux/amd64

Credits

Built with Ultraviolet for terminal rendering.