背景:Tk.mainloop 的循环条件是 window.is_active(win_id),而 is_active 对 win_id < 0 直接返回 0 ⇒ 一旦 create_window 失败,app 一次循环都不进、一句日志都不打就 process.exit(0)(现场:Scene3D spawn 后静默退出,「没有窗口」就是这么来的)。改动:window.vp 的 _attach / _connect / create_window 四个失败返回点补 [win] 错误上报(open 失败 / mmap 失败 / desk 未就绪超时 / 请求环压入失败 / CREATED 超时),这些是错误可见性而非临时噪音,长期保留;Scene3D/main.vp 加 _dbg 分步打点(start / tk ok / canvas ok / scene ok / geometry 后的 win_id 与 buf / 渲染线程 / mainloop 返回),用于定位它到底死在哪一步,定位完成后撤除。
86 lines
2.7 KiB
Plaintext
86 lines
2.7 KiB
Plaintext
import vpsdk.window as window
|
||
import vpsdk.process as process
|
||
import vpsdk.vpui as vpui
|
||
import vpsdk.devfs as devfs
|
||
import string
|
||
from stdint import *
|
||
import viperlib
|
||
import gfx
|
||
|
||
define SCENE_W = 640
|
||
define SCENE_H = 360
|
||
|
||
_zbuf_mem: [SCENE_W * SCENE_H * 8]uint8 = []
|
||
_fb_mem: [SCENE_W * SCENE_H]uint32 = []
|
||
|
||
_root_ptr: vpui.Tk*
|
||
_canvas_ptr: vpui.FBCanvas*
|
||
_s3d_ptr: gfx.Scene3D*
|
||
_time_val: float = float(0.0)
|
||
# 时间回绕周期 = 4π:Render 里 time*1 / time*2 / time*1.5 的 sin/cos 参数整体平移 2π 的整数倍
|
||
# ⇒ 动画严格连续;同时让相位半径永远很小,避免 float32 精度随运行时间退化
|
||
# (x 变大后相邻采样点的相位差被量化 ⇒ 曲线塌成一条平线、热力图颜色失去层次)。
|
||
define TIME_WRAP = float(12.566370614359172)
|
||
|
||
def _dbg(msg: const str):
|
||
# 【诊断·临时】与 explorer 同路径的串口输出。app 在建窗失败时会**静默退出**
|
||
# (Tk.mainloop 的循环条件是 win_id 有效,win_id=-1 时一次都不循环),所以必须分步打点。
|
||
devfs.serial_puts(msg)
|
||
|
||
def _render_thread(arg: t.CPtr):
|
||
global _time_val
|
||
root: vpui.Tk* = _root_ptr
|
||
canvas: vpui.FBCanvas* = _canvas_ptr
|
||
s3d: gfx.Scene3D* = _s3d_ptr
|
||
while root.winfo_exists():
|
||
s3d.Render(_time_val)
|
||
_time_val += float(0.02)
|
||
if _time_val >= TIME_WRAP: _time_val = _time_val - TIME_WRAP
|
||
root.update()
|
||
process.yield_cpu()
|
||
|
||
@__attribute__(section(".text.startup"), aligned(16))
|
||
export def _start() -> int:
|
||
_dbg("[s3d] start\n")
|
||
root: vpui.Tk = vpui.Tk()
|
||
_dbg("[s3d] tk ok\n")
|
||
root.title("3D Scene")
|
||
root.set_style(window.STYLE_WIN11)
|
||
root.bg_color = uint32(0x0F0F19)
|
||
master: vpui.Tk* = &root
|
||
|
||
canvas: vpui.FBCanvas = vpui.FBCanvas(master, SCENE_W, SCENE_H)
|
||
_dbg("[s3d] canvas ok\n")
|
||
root.pack(0, vpui.PACK_TOP, vpui.FILL_BOTH, 1, 0, 0)
|
||
|
||
zbuf: float* = &_zbuf_mem
|
||
string.memset(zbuf, 0, SCENE_W * SCENE_H * 8)
|
||
|
||
fb: UINT32PTR = &_fb_mem
|
||
string.memset(fb, 0, SCENE_W * SCENE_H * 4)
|
||
canvas.set_fb(fb, SCENE_W, SCENE_H)
|
||
|
||
s3d: gfx.Scene3D = gfx.Scene3D(fb, zbuf, SCENE_W, SCENE_H)
|
||
_dbg("[s3d] scene ok\n")
|
||
|
||
root.geometry(100, 30, SCENE_W, SCENE_H + 32)
|
||
_wbuf: [128]char
|
||
viperlib.snprintf(&_wbuf, 128, "[s3d] geometry win_id=%d buf=0x%lx\n",
|
||
root.win_id, uint64(root.buf))
|
||
_dbg(&_wbuf)
|
||
|
||
global _root_ptr, _canvas_ptr, _s3d_ptr
|
||
|
||
_root_ptr = &root
|
||
_canvas_ptr = &canvas
|
||
_s3d_ptr = &s3d
|
||
|
||
process.thread_create(_render_thread, None)
|
||
_dbg("[s3d] render thread created\n")
|
||
|
||
root.mainloop()
|
||
_dbg("[s3d] mainloop returned\n")
|
||
|
||
process.exit(0)
|
||
return 0
|