Files
retro3d/examples/modelview.ce
2025-12-13 16:13:13 -06:00

241 lines
5.8 KiB
Plaintext

// Model Viewer for retro3d
// Usage: cell run examples/modelview.ce <model_path> [style]
// style: ps1, n64, or saturn (default: ps1)
var io = use('fd')
var time_mod = use('time')
var retro3d = use('core')
// Parse command line arguments
var model_path = args[0] || "Duck.glb"
var style = args[1] || "ps1"
// Camera orbit state
var cam_distance = 5
var cam_yaw = 0
var cam_pitch = 0.3
var cam_target_y = 0
var orbit_speed = 2.0
var zoom_speed = 0.5
// Model and transform
var model = null
var transform = null
// Animation state
var anim = null
var anim_playing = false
// Timing
var last_time = 0
function _init() {
log.console("retro3d Model Viewer")
log.console("Style: " + style)
log.console("Loading: " + model_path)
// Initialize retro3d with selected style
retro3d.set_style(style)
// Load the model
model = retro3d.load_model(model_path)
if (!model) {
log.console("Error: Could not load model: " + model_path)
$_.stop()
return
}
log.console("Model loaded with " + text(model.meshes.length) + " mesh(es)")
log.console(" Nodes: " + text(model.nodes.length))
log.console(" Textures: " + text(model.textures.length))
log.console(" Animations: " + text(model.animation_count))
log.console(" Skins: " + text(model.skins ? model.skins.length : 0))
// Create transform for the model (this will be an extra parent transform)
transform = retro3d.make_transform()
// Set up animation if model has animations
if (model.animation_count > 0) {
anim = retro3d.anim_instance(model)
retro3d.anim_play(anim, 0, true)
anim_playing = true
log.console(" Playing animation: " + (retro3d.anim_clip_name(anim, 0) || "clip 0"))
}
// Set up lighting
retro3d.set_ambient(0.3, 0.3, 0.35)
retro3d.set_light_dir(0.5, 1.0, 0.3, 1.0, 0.95, 0.9, 1.0)
last_time = time_mod.number()
log.console("")
log.console("Controls:")
log.console(" WASD - Orbit camera")
log.console(" Q/E - Zoom in/out")
log.console(" R/F - Move target up/down")
log.console(" SPACE - Toggle animation")
log.console(" 1-9 - Switch animation clip")
log.console(" ESC - Exit")
// Start the main loop
frame()
}
function _update(dt) {
// Handle input for camera orbit
if (retro3d._state.keys_held['a']) {
cam_yaw -= orbit_speed * dt
}
if (retro3d._state.keys_held['d']) {
cam_yaw += orbit_speed * dt
}
if (retro3d._state.keys_held['w']) {
cam_pitch += orbit_speed * dt
if (cam_pitch > 1.5) cam_pitch = 1.5
}
if (retro3d._state.keys_held['s']) {
cam_pitch -= orbit_speed * dt
if (cam_pitch < -1.5) cam_pitch = -1.5
}
// Zoom
if (retro3d._state.keys_held['q']) {
cam_distance -= zoom_speed * dt * cam_distance
if (cam_distance < 0.5) cam_distance = 0.5
}
if (retro3d._state.keys_held['e']) {
cam_distance += zoom_speed * dt * cam_distance
if (cam_distance > 100) cam_distance = 100
}
// Move target up/down
if (retro3d._state.keys_held['r']) {
cam_target_y += zoom_speed * dt
}
if (retro3d._state.keys_held['f']) {
cam_target_y -= zoom_speed * dt
}
// Exit on escape
if (retro3d._state.keys_held['escape']) {
$_.stop()
}
// Toggle animation with space
if (retro3d._state.keys_pressed['space'] && anim) {
if (anim_playing) {
retro3d.anim_stop(anim)
anim_playing = false
log.console("Animation paused")
} else {
anim.playing = true
anim_playing = true
log.console("Animation resumed")
}
}
// Switch animation clips with number keys
if (anim && model.animation_count > 0) {
for (var i = 1; i <= 9; i++) {
if (retro3d._state.keys_pressed[text(i)]) {
var clip_idx = i - 1
if (clip_idx < model.animation_count) {
retro3d.anim_play(anim, clip_idx, true)
anim_playing = true
log.console("Playing clip " + text(clip_idx) + ": " + (retro3d.anim_clip_name(anim, clip_idx) || "unnamed"))
}
}
}
}
// Update animation
if (anim && anim_playing) {
retro3d.anim_update(anim, dt)
retro3d.anim_apply(anim)
}
}
function _draw() {
// Clear with a nice gradient-ish color based on style
if (style == "ps1") {
retro3d.clear(0.1, 0.05, 0.15, 1.0)
} else if (style == "n64") {
retro3d.clear(0.0, 0.1, 0.2, 1.0)
} else {
retro3d.clear(0.05, 0.05, 0.1, 1.0)
}
// Set up camera
retro3d.camera_perspective(60, 0.1, 100)
// Calculate camera position from orbit
var cam_x = Math.sin(cam_yaw) * Math.cos(cam_pitch) * cam_distance
var cam_y = Math.sin(cam_pitch) * cam_distance + cam_target_y
var cam_z = Math.cos(cam_yaw) * Math.cos(cam_pitch) * cam_distance
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, cam_target_y, 0)
// Draw the model
if (model) {
retro3d.draw_model(model, transform)
}
return
// Draw a ground grid using immediate mode
retro3d.push_state()
var grid_mat = retro3d.make_material("unlit", {
color: [0.3, 0.3, 0.3, 1]
})
retro3d.set_material(grid_mat)
retro3d.begin_lines()
retro3d.color(0.3, 1, 0.3, 1)
var grid_size = 10
var grid_step = 1
for (var i = -grid_size; i <= grid_size; i += grid_step) {
// X lines
retro3d.vertex(i, 0, -grid_size)
retro3d.vertex(i, 0, grid_size)
// Z lines
retro3d.vertex(-grid_size, 0, i)
retro3d.vertex(grid_size, 0, i)
}
retro3d.end()
retro3d.pop_state()
}
function frame() {
// Begin frame
retro3d._begin_frame()
// Process events
if (!retro3d._process_events()) {
log.console("Exiting...")
$_.stop()
return
}
// Calculate delta time
var now = time_mod.number()
var dt = now - last_time
last_time = now
// Update
_update(dt)
// Draw
_draw()
// End frame (submit GPU commands)
retro3d._end_frame()
// Schedule next frame
$_.delay(frame, 1/240)
}
// Start
_init()