277 lines
6.8 KiB
Plaintext
277 lines
6.8 KiB
Plaintext
// Model Viewer for retro3d
|
|
// Usage: cell run examples/modelview.ce <model_path> [style]
|
|
// style: ps1, n64, or saturn (default: ps1)
|
|
// Controls: F1=PS1, F2=N64, F3=Saturn
|
|
|
|
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"
|
|
|
|
// Available styles for cycling
|
|
var styles = ["ps1", "n64", "saturn"]
|
|
var current_style_idx = styles.indexOf(style)
|
|
if (current_style_idx < 0) current_style_idx = 0
|
|
|
|
// 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(" F1 - PS1 style (128x128 tex, 2000 tris)")
|
|
log.console(" F2 - N64 style (32x32 tex, 3000 tris)")
|
|
log.console(" F3 - Saturn style (64x64 tex, 1500 tris)")
|
|
log.console(" ESC - Exit")
|
|
|
|
// Start the main loop
|
|
frame()
|
|
}
|
|
|
|
function _switch_to_style(idx) {
|
|
if (idx == current_style_idx) return
|
|
if (idx < 0 || idx >= styles.length) return
|
|
|
|
current_style_idx = idx
|
|
style = styles[idx]
|
|
|
|
if (retro3d.switch_style(style)) {
|
|
// Recalculate model textures for new platform
|
|
if (model) {
|
|
retro3d.recalc_model_textures(model)
|
|
}
|
|
log.console("Switched to " + style.toUpperCase() + " style")
|
|
}
|
|
}
|
|
|
|
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"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Switch platform style with F1-F3
|
|
if (retro3d._state.keys_pressed['f1']) {
|
|
_switch_to_style(0) // PS1
|
|
}
|
|
if (retro3d._state.keys_pressed['f2']) {
|
|
_switch_to_style(1) // N64
|
|
}
|
|
if (retro3d._state.keys_pressed['f3']) {
|
|
_switch_to_style(2) // Saturn
|
|
}
|
|
|
|
// 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()
|