split apart modules
This commit is contained in:
@@ -1,156 +0,0 @@
|
||||
// Billboard Test for retro3d
|
||||
// Usage: cell run examples/billboard_test.ce <sprite_path>
|
||||
// sprite_path should be without extension, e.g. "assets/goblin"
|
||||
// Creates two rows of billboards going off into the distance like alongside a road
|
||||
// Colors shift through hues as they get further away
|
||||
|
||||
var time_mod = use('time')
|
||||
var retro3d = use('core')
|
||||
|
||||
var sprite_path = args[0]
|
||||
if (!sprite_path) {
|
||||
log.console("Usage: cell run examples/billboard_test.ce <sprite_path>")
|
||||
log.console(" sprite_path: path without extension (e.g. 'assets/goblin')")
|
||||
$_.stop()
|
||||
}
|
||||
|
||||
var sprite = null
|
||||
var last_time = 0
|
||||
var cam_angle = 0
|
||||
|
||||
function hsv_to_rgb(h, s, v) {
|
||||
var c = v * s
|
||||
var x = c * (1 - Math.abs((h / 60) % 2 - 1))
|
||||
var m = v - c
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (h < 60) { r = c; g = x; b = 0 }
|
||||
else if (h < 120) { r = x; g = c; b = 0 }
|
||||
else if (h < 180) { r = 0; g = c; b = x }
|
||||
else if (h < 240) { r = 0; g = x; b = c }
|
||||
else if (h < 300) { r = x; g = 0; b = c }
|
||||
else { r = c; g = 0; b = x }
|
||||
|
||||
return [r + m, g + m, b + m, 1]
|
||||
}
|
||||
|
||||
function _init() {
|
||||
log.console("retro3d Billboard Test")
|
||||
log.console("Loading sprite: " + sprite_path)
|
||||
|
||||
retro3d.set_style("ps1")
|
||||
|
||||
sprite = retro3d.load_sprite(sprite_path)
|
||||
if (!sprite) {
|
||||
log.console("Error: Could not load sprite: " + sprite_path)
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
log.console("Sprite loaded: " + text(sprite.width) + "x" + text(sprite.height))
|
||||
log.console("Controls:")
|
||||
log.console(" A/D - Rotate camera")
|
||||
log.console(" ESC - Exit")
|
||||
|
||||
retro3d.set_ambient(0.4, 0.4, 0.5)
|
||||
retro3d.set_light_dir(0.5, 1.0, 0.3, 1.0, 0.95, 0.9, 1.0)
|
||||
|
||||
last_time = time_mod.number()
|
||||
frame()
|
||||
}
|
||||
|
||||
function _update(dt) {
|
||||
if (retro3d._state.keys_held['escape']) {
|
||||
$_.stop()
|
||||
}
|
||||
|
||||
if (retro3d._state.keys_held['a']) {
|
||||
cam_angle = cam_angle - 1.5 * dt
|
||||
}
|
||||
if (retro3d._state.keys_held['d']) {
|
||||
cam_angle = cam_angle + 1.5 * dt
|
||||
}
|
||||
}
|
||||
|
||||
function _draw() {
|
||||
retro3d.clear(0.2, 0.3, 0.4, 1.0)
|
||||
|
||||
if (!sprite) return
|
||||
|
||||
// Set up perspective camera
|
||||
retro3d.camera_perspective(60, 0.1, 100)
|
||||
|
||||
// Camera orbits around origin
|
||||
var cam_dist = 8
|
||||
var cam_x = Math.sin(cam_angle) * cam_dist
|
||||
var cam_z = Math.cos(cam_angle) * cam_dist
|
||||
var cam_y = 2
|
||||
|
||||
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, 1, 0)
|
||||
|
||||
// Draw ground plane
|
||||
retro3d.push_state()
|
||||
var ground_mat = retro3d.make_material("lit", {
|
||||
color: [0.3, 0.4, 0.3, 1]
|
||||
})
|
||||
retro3d.set_material(ground_mat)
|
||||
var ground = retro3d.make_plane(20, 20)
|
||||
var ground_transform = retro3d.make_transform()
|
||||
retro3d.draw_model(ground, ground_transform)
|
||||
retro3d.pop_state()
|
||||
|
||||
// Draw two rows of billboards going into the distance
|
||||
// Left row at x = -2, right row at x = 2
|
||||
var num_billboards = 10
|
||||
var spacing = 2.0
|
||||
var start_z = -2
|
||||
|
||||
for (var i = 0; i < num_billboards; i++) {
|
||||
var z = start_z - i * spacing
|
||||
var distance_norm = i / (num_billboards - 1) // 0 to 1
|
||||
|
||||
// Hue shifts from 0 (red) to 270 (purple) as distance increases
|
||||
var hue = distance_norm * 270
|
||||
var color = hsv_to_rgb(hue, 0.9, 1.0)
|
||||
|
||||
// Left row
|
||||
retro3d.draw_billboard(sprite, -2, 0, z, {
|
||||
color: color,
|
||||
mode: "cutout",
|
||||
face: "y"
|
||||
})
|
||||
|
||||
// Right row (slightly different hue offset)
|
||||
var hue_right = (hue + 30) % 360
|
||||
var color_right = hsv_to_rgb(hue_right, 0.9, 1.0)
|
||||
|
||||
retro3d.draw_billboard(sprite, 2, 0, z, {
|
||||
color: color_right,
|
||||
mode: "cutout",
|
||||
face: "y"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function frame() {
|
||||
retro3d._begin_frame()
|
||||
|
||||
if (!retro3d._process_events()) {
|
||||
log.console("Exiting...")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var now = time_mod.number()
|
||||
var dt = now - last_time
|
||||
last_time = now
|
||||
|
||||
_update(dt)
|
||||
_draw()
|
||||
|
||||
retro3d._end_frame()
|
||||
|
||||
$_.delay(frame, 1/60)
|
||||
}
|
||||
|
||||
_init()
|
||||
109
examples/cube.ce
109
examples/cube.ce
@@ -1,13 +1,8 @@
|
||||
// Simple Cube Demo for retro3d
|
||||
// Usage: cell run examples/cube.ce [style]
|
||||
// style: ps1, n64, or saturn (default: ps1)
|
||||
// Simple Cube Demo for lance3d
|
||||
// Usage: cell run examples/cube.ce
|
||||
|
||||
var time_mod = use('time')
|
||||
var retro3d = use('core')
|
||||
|
||||
// Parse command line arguments
|
||||
var args = $_.args || []
|
||||
var style = args[0] || "ps1"
|
||||
var lance3d = use('core')
|
||||
|
||||
// Camera orbit state
|
||||
var cam_distance = 5
|
||||
@@ -15,36 +10,47 @@ var cam_yaw = 0
|
||||
var cam_pitch = 0.4
|
||||
var auto_rotate = true
|
||||
|
||||
// Model and transform
|
||||
// Models and materials
|
||||
var cube = null
|
||||
var transform = null
|
||||
var cube_mat = null
|
||||
var ground = null
|
||||
var ground_mat = null
|
||||
|
||||
// Timing
|
||||
var last_time = 0
|
||||
|
||||
function _init() {
|
||||
log.console("retro3d Cube Demo")
|
||||
log.console("Style: " + style)
|
||||
log.console("lance3d Cube Demo")
|
||||
|
||||
// Initialize retro3d with selected style
|
||||
retro3d.set_style(style)
|
||||
// Initialize lance3d with PS1 style
|
||||
lance3d.set_style("ps1")
|
||||
|
||||
// Create a cube
|
||||
cube = retro3d.make_cube(1, 1, 1)
|
||||
// Create a cube mesh
|
||||
cube = lance3d.make_cube(1, 1, 1)
|
||||
cube_mat = {
|
||||
color_map: null,
|
||||
paint: [0.8, 0.3, 0.2, 1],
|
||||
coverage: "opaque",
|
||||
face: "single",
|
||||
lamp: "lit"
|
||||
}
|
||||
|
||||
// Create transform for the cube
|
||||
transform = retro3d.make_transform()
|
||||
transform.y = 0.5
|
||||
// Create ground plane
|
||||
ground = lance3d.make_plane(10, 10)
|
||||
ground_mat = {
|
||||
color_map: null,
|
||||
paint: [0.3, 0.5, 0.3, 1],
|
||||
coverage: "opaque",
|
||||
face: "single",
|
||||
lamp: "lit"
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
||||
// Set up a default material
|
||||
var mat = retro3d.make_material("lit", {
|
||||
color: [0.8, 0.3, 0.2, 1]
|
||||
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]
|
||||
})
|
||||
retro3d.set_material(mat)
|
||||
|
||||
last_time = time_mod.number()
|
||||
|
||||
@@ -65,77 +71,62 @@ function _update(dt) {
|
||||
}
|
||||
|
||||
// Handle input for camera orbit
|
||||
if (retro3d._state.keys_held['a']) {
|
||||
if (lance3d._state.keys_held['a']) {
|
||||
cam_yaw -= 2.0 * dt
|
||||
auto_rotate = false
|
||||
}
|
||||
if (retro3d._state.keys_held['d']) {
|
||||
if (lance3d._state.keys_held['d']) {
|
||||
cam_yaw += 2.0 * dt
|
||||
auto_rotate = false
|
||||
}
|
||||
if (retro3d._state.keys_held['w']) {
|
||||
if (lance3d._state.keys_held['w']) {
|
||||
cam_pitch += 2.0 * dt
|
||||
if (cam_pitch > 1.5) cam_pitch = 1.5
|
||||
}
|
||||
if (retro3d._state.keys_held['s']) {
|
||||
if (lance3d._state.keys_held['s']) {
|
||||
cam_pitch -= 2.0 * dt
|
||||
if (cam_pitch < -1.5) cam_pitch = -1.5
|
||||
}
|
||||
|
||||
// Toggle auto-rotate
|
||||
if (retro3d._state.keys_pressed[' ']) {
|
||||
if (lance3d._state.keys_pressed['space']) {
|
||||
auto_rotate = !auto_rotate
|
||||
}
|
||||
|
||||
// Exit on escape
|
||||
if (retro3d._state.keys_held['escape']) {
|
||||
if (lance3d._state.keys_held['escape']) {
|
||||
$_.stop()
|
||||
}
|
||||
}
|
||||
|
||||
function _draw() {
|
||||
// Clear with style-appropriate color
|
||||
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)
|
||||
}
|
||||
// Clear
|
||||
lance3d.clear(0.1, 0.05, 0.15, 1.0)
|
||||
|
||||
// Set up camera
|
||||
retro3d.camera_perspective(60, 0.1, 100)
|
||||
lance3d.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 + 0.5
|
||||
var cam_z = Math.cos(cam_yaw) * Math.cos(cam_pitch) * cam_distance
|
||||
|
||||
retro3d.camera_look_at(cam_x, cam_y, cam_z, 0, 0.5, 0)
|
||||
lance3d.camera_look_at(cam_x, cam_y, cam_z, 0, 0.5, 0)
|
||||
|
||||
// Draw the cube
|
||||
retro3d.draw_model(cube, transform)
|
||||
// Draw the cube with transform
|
||||
var cube_transform = lance3d.translation_matrix(0, 0.5, 0)
|
||||
lance3d.draw_mesh(cube, cube_transform, cube_mat)
|
||||
|
||||
// Draw ground plane
|
||||
retro3d.push_state()
|
||||
var ground_mat = retro3d.make_material("lit", {
|
||||
color: [0.3, 0.5, 0.3, 1]
|
||||
})
|
||||
retro3d.set_material(ground_mat)
|
||||
|
||||
var ground = retro3d.make_plane(10, 10)
|
||||
var ground_transform = retro3d.make_transform()
|
||||
retro3d.draw_model(ground, ground_transform)
|
||||
|
||||
retro3d.pop_state()
|
||||
lance3d.draw_mesh(ground, null, ground_mat)
|
||||
}
|
||||
|
||||
function frame() {
|
||||
// Begin frame
|
||||
retro3d._begin_frame()
|
||||
lance3d._begin_frame()
|
||||
|
||||
// Process events
|
||||
if (!retro3d._process_events()) {
|
||||
if (!lance3d._process_events()) {
|
||||
log.console("Exiting...")
|
||||
$_.stop()
|
||||
return
|
||||
@@ -152,8 +143,8 @@ function frame() {
|
||||
// Draw
|
||||
_draw()
|
||||
|
||||
// End frame (submit GPU commands)
|
||||
retro3d._end_frame()
|
||||
// End frame
|
||||
lance3d._end_frame()
|
||||
|
||||
// Schedule next frame
|
||||
$_.delay(frame, 1/60)
|
||||
|
||||
@@ -1,117 +1,86 @@
|
||||
// Forest example (Diablo-style camera) for retro3d
|
||||
// Fixed 3/4 camera, WASD movement, player faces the mouse using a ground screen-cast.
|
||||
// Forest example (Diablo-style camera) for lance3d
|
||||
// Fixed 3/4 camera, WASD movement
|
||||
// Press ESC to exit.
|
||||
|
||||
var time_mod = use('time')
|
||||
var retro3d = use('core')
|
||||
var lance3d = use('core')
|
||||
|
||||
var ground_model = null
|
||||
var ground_transform = null
|
||||
// Meshes
|
||||
var ground_mesh = null
|
||||
var trunk_mesh = null
|
||||
var canopy_mesh = null
|
||||
var player_mesh = null
|
||||
|
||||
// Materials
|
||||
var ground_mat = null
|
||||
|
||||
var trunk_model = null
|
||||
var trunk_mat = null
|
||||
var canopy_model = null
|
||||
var canopy_mat_a = null
|
||||
var canopy_mat_b = null
|
||||
|
||||
var player_model = null
|
||||
var player_mat = null
|
||||
|
||||
var marker_model = null
|
||||
var marker_transform = null
|
||||
var marker_mat = null
|
||||
|
||||
// Player state
|
||||
var player = {
|
||||
transform: null,
|
||||
speed: 6.0,
|
||||
yaw: 0
|
||||
x: 0,
|
||||
y: 0.5,
|
||||
z: 0,
|
||||
yaw: 0,
|
||||
speed: 6.0
|
||||
}
|
||||
|
||||
// Trees: array of {x, z, trunk_h, trunk_r, canopy_s, canopy_mat}
|
||||
var trees = []
|
||||
var num_trees = 80
|
||||
|
||||
var cam_offset = { x: 10, y: 12, z: 10 }
|
||||
|
||||
var last_time = 0
|
||||
var last_hit = null
|
||||
|
||||
function _set_camera() {
|
||||
var px = player.transform.x
|
||||
var pz = player.transform.z
|
||||
|
||||
retro3d.camera_perspective(55, 0.1, 300)
|
||||
retro3d.camera_look_at(
|
||||
px + cam_offset.x,
|
||||
cam_offset.y,
|
||||
pz + cam_offset.z,
|
||||
px, 0, pz
|
||||
)
|
||||
}
|
||||
|
||||
function _set_yaw(t, yaw) {
|
||||
player.yaw = yaw
|
||||
var half = yaw / 2
|
||||
retro3d.transform_set_rotation_quat(t, 0, Math.sin(half), 0, Math.cos(half))
|
||||
}
|
||||
|
||||
function _init() {
|
||||
log.console("retro3d Forest (Diablo camera) Example")
|
||||
log.console("WASD move")
|
||||
log.console("Face mouse (ground cast)")
|
||||
log.console("ESC exit")
|
||||
log.console("lance3d Forest (Diablo camera) Example")
|
||||
log.console("WASD move, ESC exit")
|
||||
|
||||
retro3d.set_style("ps1")
|
||||
retro3d.seed(1337)
|
||||
lance3d.set_style("ps1")
|
||||
|
||||
retro3d.set_ambient(0.35, 0.35, 0.40)
|
||||
retro3d.set_light_dir(0.4, 1.0, 0.2, 1.0, 0.95, 0.9, 1.0)
|
||||
retro3d.set_fog(40, 160, [0.55, 0.70, 0.90])
|
||||
lance3d.seed(1337)
|
||||
|
||||
ground_model = retro3d.make_plane(220, 220)
|
||||
ground_transform = retro3d.make_transform()
|
||||
retro3d.transform_set_position(ground_transform, 0, 0, 0)
|
||||
ground_mat = retro3d.make_material("lit", { color: [0.12, 0.22, 0.10, 1.0] })
|
||||
lance3d.set_lighting({
|
||||
sun_dir: [0.4, 1.0, 0.2],
|
||||
sun_color: [1.0, 0.95, 0.9],
|
||||
ambient: [0.35, 0.35, 0.40]
|
||||
})
|
||||
|
||||
trunk_model = retro3d.make_cube(1, 1, 1)
|
||||
canopy_model = retro3d.make_cube(1, 1, 1)
|
||||
trunk_mat = retro3d.make_material("lit", { color: [0.35, 0.23, 0.14, 1.0] })
|
||||
canopy_mat_a = retro3d.make_material("lit", { color: [0.11, 0.40, 0.18, 1.0] })
|
||||
canopy_mat_b = retro3d.make_material("lit", { color: [0.09, 0.33, 0.14, 1.0] })
|
||||
lance3d.set_fog({
|
||||
enabled: true,
|
||||
color: [0.55, 0.70, 0.90],
|
||||
near: 40,
|
||||
far: 160
|
||||
})
|
||||
|
||||
player_model = retro3d.make_cube(1, 1, 1)
|
||||
player_mat = retro3d.make_material("lit", { color: [0.85, 0.25, 0.20, 1.0] })
|
||||
player.transform = retro3d.make_transform()
|
||||
retro3d.transform_set_position(player.transform, 0, 0.5, 0)
|
||||
retro3d.transform_set_scale(player.transform, 0.7, 1.0, 0.7)
|
||||
_set_yaw(player.transform, 0)
|
||||
// Create meshes
|
||||
ground_mesh = lance3d.make_plane(220, 220)
|
||||
trunk_mesh = lance3d.make_cube(1, 1, 1)
|
||||
canopy_mesh = lance3d.make_cube(1, 1, 1)
|
||||
player_mesh = lance3d.make_cube(1, 1, 1)
|
||||
|
||||
marker_model = retro3d.make_cube(1, 1, 1)
|
||||
marker_mat = retro3d.make_material("unlit", { color: [1.0, 0.95, 0.2, 1.0] })
|
||||
marker_transform = retro3d.make_transform()
|
||||
retro3d.transform_set_scale(marker_transform, 0.15, 0.15, 0.15)
|
||||
// Create materials
|
||||
ground_mat = { paint: [0.12, 0.22, 0.10, 1.0], coverage: "opaque", face: "single", lamp: "lit" }
|
||||
trunk_mat = { paint: [0.35, 0.23, 0.14, 1.0], coverage: "opaque", face: "single", lamp: "lit" }
|
||||
canopy_mat_a = { paint: [0.11, 0.40, 0.18, 1.0], coverage: "opaque", face: "single", lamp: "lit" }
|
||||
canopy_mat_b = { paint: [0.09, 0.33, 0.14, 1.0], coverage: "opaque", face: "single", lamp: "lit" }
|
||||
player_mat = { paint: [0.85, 0.25, 0.20, 1.0], coverage: "opaque", face: "single", lamp: "lit" }
|
||||
|
||||
// Generate trees
|
||||
for (var i = 0; i < num_trees; i++) {
|
||||
var x, z
|
||||
x = (retro3d.rand() - 0.5) * 90
|
||||
z = (retro3d.rand() - 0.5) * 90
|
||||
|
||||
var trunk_h = retro3d.rand() * 3 + 2
|
||||
var trunk_r = retro3d.rand() * 0.25 + 0.25
|
||||
var canopy_s = retro3d.rand() * 1.0 + 1.5
|
||||
|
||||
var trunk = retro3d.make_transform()
|
||||
retro3d.transform_set_position(trunk, x, trunk_h / 2, z)
|
||||
retro3d.transform_set_scale(trunk, trunk_r, trunk_h, trunk_r)
|
||||
|
||||
var canopy = retro3d.make_transform()
|
||||
retro3d.transform_set_position(canopy, x, trunk_h + canopy_s / 2, z)
|
||||
retro3d.transform_set_scale(canopy, canopy_s, canopy_s, canopy_s)
|
||||
var x = (lance3d.rand() - 0.5) * 90
|
||||
var z = (lance3d.rand() - 0.5) * 90
|
||||
|
||||
trees.push({
|
||||
trunk: trunk,
|
||||
canopy: canopy,
|
||||
canopy_mat: retro3d.rand() < 0.5 ? canopy_mat_a : canopy_mat_b
|
||||
x: x,
|
||||
z: z,
|
||||
trunk_h: lance3d.rand() * 3 + 2,
|
||||
trunk_r: lance3d.rand() * 0.25 + 0.25,
|
||||
canopy_s: lance3d.rand() * 1.0 + 1.5,
|
||||
canopy_mat: lance3d.rand() < 0.5 ? canopy_mat_a : canopy_mat_b
|
||||
})
|
||||
}
|
||||
|
||||
@@ -120,123 +89,103 @@ function _init() {
|
||||
}
|
||||
|
||||
function _update(dt) {
|
||||
if (retro3d._state.keys_held['escape']) {
|
||||
if (lance3d._state.keys_held['escape']) {
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
_set_camera()
|
||||
|
||||
var mx = retro3d._state.mouse_x || 0
|
||||
var my = retro3d._state.mouse_y || 0
|
||||
var hit = retro3d.screen_cast_ground(mx, my, 0)
|
||||
if (hit) {
|
||||
last_hit = hit
|
||||
retro3d.transform_set_position(marker_transform, hit.x, 0.05, hit.z)
|
||||
|
||||
var px = player.transform.x
|
||||
var pz = player.transform.z
|
||||
var dx = hit.x - px
|
||||
var dz = hit.z - pz
|
||||
if (dx * dx + dz * dz > 0.00001) {
|
||||
var yaw = Math.atan2(dx, dz)
|
||||
_set_yaw(player.transform, yaw)
|
||||
}
|
||||
}
|
||||
|
||||
// Movement input
|
||||
var forward = 0
|
||||
var right = 0
|
||||
if (retro3d._state.keys_held['w']) forward += 1
|
||||
if (retro3d._state.keys_held['s']) forward -= 1
|
||||
if (retro3d._state.keys_held['d']) right -= 1
|
||||
if (retro3d._state.keys_held['a']) right += 1
|
||||
if (lance3d._state.keys_held['w']) forward += 1
|
||||
if (lance3d._state.keys_held['s']) forward -= 1
|
||||
if (lance3d._state.keys_held['d']) right -= 1
|
||||
if (lance3d._state.keys_held['a']) right += 1
|
||||
|
||||
if (forward != 0 || right != 0) {
|
||||
// Update yaw based on movement direction
|
||||
player.yaw = Math.atan2(forward, -right)
|
||||
|
||||
var fx = Math.sin(player.yaw)
|
||||
var fz = Math.cos(player.yaw)
|
||||
var rx = Math.cos(player.yaw)
|
||||
var rz = -Math.sin(player.yaw)
|
||||
|
||||
var vx = fx * forward + rx * right
|
||||
var vz = fz * forward + rz * right
|
||||
|
||||
var len = Math.sqrt(vx * vx + vz * vz)
|
||||
var len = Math.sqrt(fx * fx + fz * fz)
|
||||
if (len > 0) {
|
||||
vx /= len
|
||||
vz /= len
|
||||
fx /= len
|
||||
fz /= len
|
||||
}
|
||||
|
||||
var px = player.transform.x + vx * player.speed * dt
|
||||
var pz = player.transform.z + vz * player.speed * dt
|
||||
retro3d.transform_set_position(player.transform, px, 0.5, pz)
|
||||
player.x += fx * player.speed * dt
|
||||
player.z += fz * player.speed * dt
|
||||
}
|
||||
}
|
||||
|
||||
function _draw() {
|
||||
retro3d.clear(0.55, 0.70, 0.90, 1.0)
|
||||
lance3d.clear(0.55, 0.70, 0.90, 1.0)
|
||||
|
||||
_set_camera()
|
||||
// Set up camera following player
|
||||
lance3d.camera_perspective(55, 0.1, 300)
|
||||
lance3d.camera_look_at(
|
||||
player.x + cam_offset.x,
|
||||
cam_offset.y,
|
||||
player.z + cam_offset.z,
|
||||
player.x, 0, player.z
|
||||
)
|
||||
|
||||
retro3d.push_state()
|
||||
retro3d.set_material(ground_mat)
|
||||
retro3d.draw_model(ground_model, ground_transform)
|
||||
retro3d.pop_state()
|
||||
// Draw ground
|
||||
lance3d.draw_mesh(ground_mesh, null, ground_mat)
|
||||
|
||||
retro3d.push_state()
|
||||
retro3d.set_material(trunk_mat)
|
||||
for (let i = 0; i < trees.length; i++) {
|
||||
retro3d.draw_model(trunk_model, trees[i].trunk)
|
||||
// Draw tree trunks
|
||||
for (var i = 0; i < trees.length; i++) {
|
||||
var tree = trees[i]
|
||||
var trunk_transform = lance3d.trs_matrix(
|
||||
tree.x, tree.trunk_h / 2, tree.z,
|
||||
0, 0, 0, 1,
|
||||
tree.trunk_r, tree.trunk_h, tree.trunk_r
|
||||
)
|
||||
lance3d.draw_mesh(trunk_mesh, trunk_transform, trunk_mat)
|
||||
}
|
||||
retro3d.pop_state()
|
||||
|
||||
retro3d.push_state()
|
||||
for (let i = 0; i < trees.length; i++) {
|
||||
retro3d.set_material(trees[i].canopy_mat)
|
||||
retro3d.draw_model(canopy_model, trees[i].canopy)
|
||||
// Draw tree canopies
|
||||
for (var i = 0; i < trees.length; i++) {
|
||||
var tree = trees[i]
|
||||
var canopy_transform = lance3d.trs_matrix(
|
||||
tree.x, tree.trunk_h + tree.canopy_s / 2, tree.z,
|
||||
0, 0, 0, 1,
|
||||
tree.canopy_s, tree.canopy_s, tree.canopy_s
|
||||
)
|
||||
lance3d.draw_mesh(canopy_mesh, canopy_transform, tree.canopy_mat)
|
||||
}
|
||||
retro3d.pop_state()
|
||||
|
||||
retro3d.push_state()
|
||||
retro3d.set_material(player_mat)
|
||||
retro3d.draw_model(player_model, player.transform)
|
||||
retro3d.pop_state()
|
||||
|
||||
if (last_hit) {
|
||||
retro3d.push_state()
|
||||
retro3d.set_material(marker_mat)
|
||||
retro3d.draw_model(marker_model, marker_transform)
|
||||
retro3d.pop_state()
|
||||
}
|
||||
// Draw player
|
||||
var q = lance3d.euler_to_quat(0, player.yaw, 0)
|
||||
var player_transform = lance3d.trs_matrix(
|
||||
player.x, player.y, player.z,
|
||||
q.x, q.y, q.z, q.w,
|
||||
0.7, 1.0, 0.7
|
||||
)
|
||||
lance3d.draw_mesh(player_mesh, player_transform, player_mat)
|
||||
}
|
||||
|
||||
function frame() {
|
||||
// Begin frame
|
||||
retro3d._begin_frame()
|
||||
lance3d._begin_frame()
|
||||
|
||||
// Process events
|
||||
if (!retro3d._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 (submit GPU commands)
|
||||
retro3d._end_frame()
|
||||
lance3d._end_frame()
|
||||
|
||||
// Schedule next frame
|
||||
$_.delay(frame, 1/60)
|
||||
}
|
||||
|
||||
// Start
|
||||
_init()
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
// 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
|
||||
// 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 retro3d = use('core')
|
||||
var lance3d = use('core')
|
||||
|
||||
log.console(lance3d.key)
|
||||
|
||||
// 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
|
||||
@@ -24,53 +20,52 @@ var cam_target_y = 0
|
||||
var orbit_speed = 2.0
|
||||
var zoom_speed = 0.5
|
||||
|
||||
// Model and transform
|
||||
// Model
|
||||
var model = null
|
||||
var transform = null
|
||||
|
||||
// Animation state
|
||||
var anim = null
|
||||
var anim_playing = false
|
||||
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("retro3d Model Viewer")
|
||||
log.console("Style: " + style)
|
||||
log.console("lance3d Model Viewer")
|
||||
log.console("Loading: " + model_path)
|
||||
|
||||
// Initialize retro3d with selected style
|
||||
retro3d.set_style(style)
|
||||
// Initialize lance3d with PS1 style
|
||||
lance3d.set_style(style)
|
||||
|
||||
// Load the model
|
||||
model = retro3d.load_model(model_path)
|
||||
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.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))
|
||||
log.console("Model loaded with " + text(model.length) + " mesh(es)")
|
||||
|
||||
// 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"))
|
||||
// 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
|
||||
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)
|
||||
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()
|
||||
|
||||
@@ -81,174 +76,145 @@ function _init() {
|
||||
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")
|
||||
log.console(" F1 - PS1 style")
|
||||
log.console(" F2 - N64 style")
|
||||
log.console(" F3 - Saturn style")
|
||||
|
||||
// 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']) {
|
||||
if (lance3d.key('a')) {
|
||||
cam_yaw -= orbit_speed * dt
|
||||
}
|
||||
if (retro3d._state.keys_held['d']) {
|
||||
if (lance3d.key('d')) {
|
||||
cam_yaw += orbit_speed * dt
|
||||
}
|
||||
if (retro3d._state.keys_held['w']) {
|
||||
if (lance3d.key('w')) {
|
||||
cam_pitch += orbit_speed * dt
|
||||
if (cam_pitch > 1.5) cam_pitch = 1.5
|
||||
}
|
||||
if (retro3d._state.keys_held['s']) {
|
||||
if (lance3d.key('s')) {
|
||||
cam_pitch -= orbit_speed * dt
|
||||
if (cam_pitch < -1.5) cam_pitch = -1.5
|
||||
}
|
||||
|
||||
// Zoom
|
||||
if (retro3d._state.keys_held['q']) {
|
||||
if (lance3d.key('q')) {
|
||||
cam_distance -= zoom_speed * dt * cam_distance
|
||||
if (cam_distance < 0.5) cam_distance = 0.5
|
||||
}
|
||||
if (retro3d._state.keys_held['e']) {
|
||||
if (lance3d.key('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']) {
|
||||
if (lance3d.key('r')) {
|
||||
cam_target_y += zoom_speed * dt
|
||||
}
|
||||
if (retro3d._state.keys_held['f']) {
|
||||
if (lance3d.key('f')) {
|
||||
cam_target_y -= zoom_speed * dt
|
||||
}
|
||||
|
||||
// Exit on escape
|
||||
if (retro3d._state.keys_held['escape']) {
|
||||
if (lance3d.key('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")
|
||||
}
|
||||
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 (anim && model.animation_count > 0) {
|
||||
if (animations.length > 0) {
|
||||
for (var i = 1; i <= 9; i++) {
|
||||
if (retro3d._state.keys_pressed[text(i)]) {
|
||||
if (lance3d.keyp(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"))
|
||||
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 (retro3d._state.keys_pressed['f1']) {
|
||||
_switch_to_style(0) // PS1
|
||||
if (lance3d.keyp('f1')) {
|
||||
_switch_to_style("ps1")
|
||||
}
|
||||
if (retro3d._state.keys_pressed['f2']) {
|
||||
_switch_to_style(1) // N64
|
||||
if (lance3d.keyp('f2')) {
|
||||
_switch_to_style("n64")
|
||||
}
|
||||
if (retro3d._state.keys_pressed['f3']) {
|
||||
_switch_to_style(2) // Saturn
|
||||
if (lance3d.keyp('f3')) {
|
||||
_switch_to_style("saturn")
|
||||
}
|
||||
|
||||
// Update animation
|
||||
if (anim && anim_playing) {
|
||||
retro3d.anim_update(anim, dt)
|
||||
retro3d.anim_apply(anim)
|
||||
// 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 gradient-ish color based on style
|
||||
// Clear with a nice color based on style
|
||||
if (style == "ps1") {
|
||||
retro3d.clear(0.1, 0.05, 0.15, 1.0)
|
||||
lance3d.clear(0.1, 0.05, 0.15, 1.0)
|
||||
} else if (style == "n64") {
|
||||
retro3d.clear(0.0, 0.1, 0.2, 1.0)
|
||||
lance3d.clear(0.0, 0.1, 0.2, 1.0)
|
||||
} else {
|
||||
retro3d.clear(0.05, 0.05, 0.1, 1.0)
|
||||
lance3d.clear(0.05, 0.05, 0.1, 1.0)
|
||||
}
|
||||
|
||||
// Set up camera
|
||||
retro3d.camera_perspective(60, 0.1, 100)
|
||||
lance3d.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)
|
||||
lance3d.camera_look_at(cam_x, cam_y, cam_z, 0, cam_target_y, 0)
|
||||
|
||||
// Draw the model
|
||||
if (model) {
|
||||
retro3d.draw_model(model, transform)
|
||||
var pose = null
|
||||
if (animations.length > 0) {
|
||||
pose = lance3d.sample_pose(model, current_anim, anim_time)
|
||||
}
|
||||
lance3d.draw_model(model, null, pose)
|
||||
}
|
||||
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()
|
||||
lance3d._begin_frame()
|
||||
|
||||
// Process events
|
||||
if (!retro3d._process_events()) {
|
||||
if (!lance3d._process_events()) {
|
||||
log.console("Exiting...")
|
||||
$_.stop()
|
||||
return
|
||||
@@ -265,8 +231,8 @@ function frame() {
|
||||
// Draw
|
||||
_draw()
|
||||
|
||||
// End frame (submit GPU commands)
|
||||
retro3d._end_frame()
|
||||
// End frame
|
||||
lance3d._end_frame()
|
||||
|
||||
// Schedule next frame
|
||||
$_.delay(frame, 1/240)
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
// Sprite Test for retro3d
|
||||
// Usage: cell run examples/sprite_test.ce <sprite_path>
|
||||
// sprite_path should be without extension, e.g. "assets/goblin"
|
||||
// Fills screen with sprites, hue-shifted based on normalized screen position
|
||||
|
||||
var time_mod = use('time')
|
||||
var retro3d = use('core')
|
||||
|
||||
var sprite_path = args[0]
|
||||
if (!sprite_path) {
|
||||
log.console("Usage: cell run examples/sprite_test.ce <sprite_path>")
|
||||
log.console(" sprite_path: path without extension (e.g. 'assets/goblin')")
|
||||
$_.stop()
|
||||
}
|
||||
|
||||
var sprite = null
|
||||
var last_time = 0
|
||||
|
||||
function hsv_to_rgb(h, s, v) {
|
||||
var c = v * s
|
||||
var x = c * (1 - Math.abs((h / 60) % 2 - 1))
|
||||
var m = v - c
|
||||
|
||||
var r = 0, g = 0, b = 0
|
||||
if (h < 60) { r = c; g = x; b = 0 }
|
||||
else if (h < 120) { r = x; g = c; b = 0 }
|
||||
else if (h < 180) { r = 0; g = c; b = x }
|
||||
else if (h < 240) { r = 0; g = x; b = c }
|
||||
else if (h < 300) { r = x; g = 0; b = c }
|
||||
else { r = c; g = 0; b = x }
|
||||
|
||||
return [r + m, g + m, b + m, 1]
|
||||
}
|
||||
|
||||
function _init() {
|
||||
log.console("retro3d Sprite Test")
|
||||
log.console("Loading sprite: " + sprite_path)
|
||||
|
||||
retro3d.set_style("ps1")
|
||||
|
||||
sprite = retro3d.load_sprite(sprite_path)
|
||||
if (!sprite) {
|
||||
log.console("Error: Could not load sprite: " + sprite_path)
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
log.console("Sprite loaded: " + text(sprite.width) + "x" + text(sprite.height))
|
||||
log.console("Press ESC to exit")
|
||||
|
||||
last_time = time_mod.number()
|
||||
frame()
|
||||
}
|
||||
|
||||
function _update(dt) {
|
||||
if (retro3d._state.keys_held['escape']) {
|
||||
$_.stop()
|
||||
}
|
||||
}
|
||||
|
||||
function _draw() {
|
||||
retro3d.clear(0.1, 0.1, 0.15, 1.0)
|
||||
|
||||
if (!sprite) return
|
||||
|
||||
var w = sprite.width
|
||||
var h = sprite.height
|
||||
|
||||
// Fill from bottom to top with sprites
|
||||
// Hue shifts based on normalized screen position
|
||||
var y = 0
|
||||
while (y < 240) {
|
||||
var x = 0
|
||||
while (x < 320) {
|
||||
// Normalized position (0-1)
|
||||
var nx = x / 320
|
||||
var ny = y / 240
|
||||
|
||||
// Hue based on position (0-360 degrees)
|
||||
var hue = (nx + ny) * 180 // Combined X and Y influence
|
||||
hue = hue % 360
|
||||
|
||||
var color = hsv_to_rgb(hue, 0.8, 1.0)
|
||||
|
||||
retro3d.draw_sprite(sprite, x, y, {
|
||||
color: color,
|
||||
mode: "cutout"
|
||||
})
|
||||
|
||||
x = x + w
|
||||
}
|
||||
y = y + h
|
||||
}
|
||||
}
|
||||
|
||||
function frame() {
|
||||
retro3d._begin_frame()
|
||||
|
||||
if (!retro3d._process_events()) {
|
||||
log.console("Exiting...")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var now = time_mod.number()
|
||||
var dt = now - last_time
|
||||
last_time = now
|
||||
|
||||
_update(dt)
|
||||
_draw()
|
||||
|
||||
retro3d._end_frame()
|
||||
|
||||
$_.delay(frame, 1/60)
|
||||
}
|
||||
|
||||
_init()
|
||||
Reference in New Issue
Block a user