244 lines
5.5 KiB
Plaintext
244 lines
5.5 KiB
Plaintext
// Model Viewer for lance3d
|
|
// Usage: cell run examples/modelview.ce <model_path>
|
|
// Controls: WASD orbit, Q/E zoom, R/F move target, SPACE toggle animation, 1-9 switch clip
|
|
// F1/F2/F3 - Switch style (PS1/N64/Saturn)
|
|
|
|
var io = use('fd')
|
|
var time_mod = use('time')
|
|
var lance3d = use('core')
|
|
var math = use('math/radians')
|
|
|
|
log.console(lance3d.key)
|
|
|
|
// Parse command line arguments
|
|
var model_path = args[0] || "Duck.glb"
|
|
|
|
// 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
|
|
var model = null
|
|
|
|
// Animation state
|
|
var animations = []
|
|
var current_anim = 0
|
|
var anim_time = 0
|
|
var anim_playing = true
|
|
var anim_speed = 1.0
|
|
|
|
// Current style
|
|
var style = "ps1"
|
|
|
|
// Timing
|
|
var last_time = 0
|
|
|
|
function _init() {
|
|
log.console("lance3d Model Viewer")
|
|
log.console("Loading: " + model_path)
|
|
|
|
// Initialize lance3d with PS1 style
|
|
lance3d.set_style(style)
|
|
|
|
// Load the model
|
|
model = lance3d.load_model(model_path)
|
|
if (!model) {
|
|
log.console("Error: Could not load model: " + model_path)
|
|
$_.stop()
|
|
return
|
|
}
|
|
|
|
log.console("Model loaded with " + text(model.length) + " mesh(es)")
|
|
|
|
// Get animation info
|
|
animations = lance3d.anim_info(model)
|
|
log.console(" Animations: " + text(animations.length))
|
|
for (var i = 0; i < animations.length; i++) {
|
|
log.console(" " + text(i) + ": " + animations[i].name + " (" + text(animations[i].duration) + "s)")
|
|
}
|
|
|
|
// Set up lighting
|
|
lance3d.set_lighting({
|
|
sun_dir: [0.5, 1.0, 0.3],
|
|
sun_color: [1.0, 0.95, 0.9],
|
|
ambient: [0.3, 0.3, 0.35]
|
|
})
|
|
|
|
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")
|
|
log.console(" F1 - PS1 style")
|
|
log.console(" F2 - N64 style")
|
|
log.console(" F3 - Saturn style")
|
|
|
|
// Start the main loop
|
|
frame()
|
|
}
|
|
|
|
function _update(dt) {
|
|
// Handle input for camera orbit
|
|
if (lance3d.key('a')) {
|
|
cam_yaw -= orbit_speed * dt
|
|
}
|
|
if (lance3d.key('d')) {
|
|
cam_yaw += orbit_speed * dt
|
|
}
|
|
if (lance3d.key('w')) {
|
|
cam_pitch += orbit_speed * dt
|
|
if (cam_pitch > 1.5) cam_pitch = 1.5
|
|
}
|
|
if (lance3d.key('s')) {
|
|
cam_pitch -= orbit_speed * dt
|
|
if (cam_pitch < -1.5) cam_pitch = -1.5
|
|
}
|
|
|
|
// Zoom
|
|
if (lance3d.key('q')) {
|
|
cam_distance -= zoom_speed * dt * cam_distance
|
|
if (cam_distance < 0.5) cam_distance = 0.5
|
|
}
|
|
if (lance3d.key('e')) {
|
|
cam_distance += zoom_speed * dt * cam_distance
|
|
if (cam_distance > 100) cam_distance = 100
|
|
}
|
|
|
|
// Move target up/down
|
|
if (lance3d.key('r')) {
|
|
cam_target_y += zoom_speed * dt
|
|
}
|
|
if (lance3d.key('f')) {
|
|
cam_target_y -= zoom_speed * dt
|
|
}
|
|
|
|
// Exit on escape
|
|
if (lance3d.key('escape')) {
|
|
$_.stop()
|
|
}
|
|
|
|
// Toggle animation with space
|
|
if (lance3d.keyp('space') && animations.length > 0) {
|
|
anim_playing = !anim_playing
|
|
log.console(anim_playing ? "Animation resumed" : "Animation paused")
|
|
}
|
|
|
|
// Switch animation clips with number keys
|
|
if (animations.length > 0) {
|
|
for (var i = 1; i <= 9; i++) {
|
|
if (lance3d.keyp(text(i))) {
|
|
var clip_idx = i - 1
|
|
if (clip_idx < animations.length) {
|
|
current_anim = clip_idx
|
|
anim_time = 0
|
|
log.console("Playing clip " + text(clip_idx) + ": " + animations[clip_idx].name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Switch platform style with F1-F3
|
|
if (lance3d.keyp('f1')) {
|
|
_switch_to_style("ps1")
|
|
}
|
|
if (lance3d.keyp('f2')) {
|
|
_switch_to_style("n64")
|
|
}
|
|
if (lance3d.keyp('f3')) {
|
|
_switch_to_style("saturn")
|
|
}
|
|
|
|
// Update animation time
|
|
if (anim_playing && animations.length > 0) {
|
|
anim_time += dt * anim_speed
|
|
var duration = animations[current_anim].duration
|
|
if (duration > 0) {
|
|
while (anim_time > duration) {
|
|
anim_time -= duration
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function _switch_to_style(new_style) {
|
|
if (style == new_style) return
|
|
style = new_style
|
|
lance3d.switch_style(style)
|
|
// Recalculate model textures for new style
|
|
if (model) {
|
|
lance3d.recalc_model_textures(model)
|
|
}
|
|
log.console("Switched to " + style + " style")
|
|
}
|
|
|
|
function _draw() {
|
|
// Clear with a nice color based on style
|
|
if (style == "ps1") {
|
|
lance3d.clear(0.1, 0.05, 0.15, 1.0)
|
|
} else if (style == "n64") {
|
|
lance3d.clear(0.0, 0.1, 0.2, 1.0)
|
|
} else {
|
|
lance3d.clear(0.05, 0.05, 0.1, 1.0)
|
|
}
|
|
|
|
// Set up camera
|
|
lance3d.camera_perspective(60, 0.1, 100)
|
|
|
|
// Calculate camera position from orbit
|
|
var cam_x = math.sine(cam_yaw) * math.cosine(cam_pitch) * cam_distance
|
|
var cam_y = math.sine(cam_pitch) * cam_distance + cam_target_y
|
|
var cam_z = math.cosine(cam_yaw) * math.cosine(cam_pitch) * cam_distance
|
|
|
|
lance3d.camera_look_at(cam_x, cam_y, cam_z, 0, cam_target_y, 0)
|
|
|
|
// Draw the model
|
|
if (model) {
|
|
var pose = null
|
|
if (animations.length > 0) {
|
|
pose = lance3d.sample_pose(model, current_anim, anim_time)
|
|
}
|
|
lance3d.draw_model(model, null, pose)
|
|
}
|
|
}
|
|
|
|
function frame() {
|
|
// Begin frame
|
|
lance3d._begin_frame()
|
|
|
|
// Process events
|
|
if (!lance3d._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
|
|
lance3d._end_frame()
|
|
|
|
// Schedule next frame
|
|
$_.delay(frame, 1/240)
|
|
}
|
|
|
|
// Start
|
|
_init()
|