A minimal Solar2D sample that renders a 3D OBJ mesh into a single
display.newSnapshot() using 2D meshes. The scene stays as one display
object while the renderer projects and shades faces each frame.
- OBJ loader (vertices + faces), triangulation, negative indices support
- Flat shaded faces with multiple lights
- Optional two-sided rendering
- Per-frame depth sorting (painter's algorithm)
- Background color inside the snapshot
- Separate orientation and animation control (local/global)
- Optional scale pulse
main.lua- demo scenerenderer/renderer.lua- renderer and OBJ loaderrenderer/transformations/rotation.lua- rotation helpersrenderer/transformations/scale.lua- scale pulse helpersobj/wrench.obj- sample model
local renderer = require("renderer.renderer")
local snap = renderer.newSnapshot{
width = 128,
height = 128,
modelScale = 0.9,
distance = 8.0,
fovScale = 110,
zoom = 0.8,
objPath = "obj/wrench.obj",
faceColor = { 0.20, 0.55, 1.00 },
backgroundColor = { 0.0, 0.0, 0.0, 1.0 },
useLighting = true,
lightDirs = {
{ x = -0.4, y = -0.7, z = -1.0 },
{ x = 0.6, y = -0.2, z = -0.5 },
{ x = 0.0, y = 0.8, z = -0.3 }
},
twoSided = true
}
snap:orientObject({ x = 1.7, y = 0.8, z = 0.5, space = "local" })
snap:applyAnimation({
spin = 0.5,
rotationAxis = "z",
scalePulse = { amplitude = 0.01, speed = 8.0 },
space = "global",
additive = true
})Core options:
width,height- snapshot size in pixelsmodelScale- base model scale (world units)distance- camera distance (world units)fovScale- projection scale in pixelszoom- projection multiplier (default 1)objPath- OBJ path (resource directory)faceColor-{r,g,b}for flat shadingbackgroundColor-{r,g,b[,a]}for snapshot backgroundoriginX,originY- shift projected coordinates inside snapshot
Lighting options:
useLighting- booleanlightDirs- array of{x,y,z}light directionsambient- minimum clamp (default 0.15)twoSided- render backfaces and light both sides
Normals/winding options:
autoOrient- auto-flip winding from signed volume (default true)invertWinding/flipNormals- force flip all facesinvertFirstFace/flipFirstFace- flip only first face
Animation/orientation options:
spin+rotationAxis- spin rate on axis preset (x,y,z,xy,xz,yz,xyz)spinX,spinY,spinZ- per-axis spin ratesscalePulse-{ amplitude, speed, phase }ortrueorientation-{ x, y, z, space="local|global" }animationSpace-"local"or"global"(defaults to orientation space)
Sets a base orientation, separate from animation.
Options:
x,y,z- radiansspace-"local"or"global"additive- if true, adds to the current orientation
Applies animation parameters.
Options:
spin+rotationAxis, orspinX/spinY/spinZscalePulsespace-"local"or"global"additive- if true, adds to existing spin rates
- OBJ parsing supports
vandflines. Texture/normal indices are ignored. - Faces are triangulated in fan order. Keep models triangulated for best results.
- No z-buffer; faces are sorted by depth each frame.
- Camera is at origin looking down +Z, so models must be in front (positive Z after translation).
