perf(render3d): an actor knows its row - removal swaps the last one in (O(1)) instead of building a new list of every other actor, never freed; actor_keep puts one back after a world swap; actor_clear_all clears in place
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b9d0cca281
commit
c97e64c3c0
1 changed files with 25 additions and 7 deletions
|
|
@ -30,6 +30,7 @@ property Actor {
|
|||
cast_hidden: bool = false,
|
||||
casts: bool = true,
|
||||
id: int = 0,
|
||||
row: int = -1, # where it stands in ac_actors, so it leaves in O(1); -1 off the stage
|
||||
cutout: bool = false, # alpha-tested (a flame's cards)
|
||||
emissive: float = 0.0, # float bits: self-lit strength
|
||||
skin: Skin, # this instance's own pose (skin_clone); null: the model's
|
||||
|
|
@ -82,11 +83,27 @@ function actor_init(render3d_st: mut Render3dState) -> void {
|
|||
render3d_st.ac_out_cut = ac_prog_new(render3d_st, "skin.vert", "outline.frag", "#define OUTLINE\n#define ALPHA_TEST\n")
|
||||
render3d_st.ac_actors = new []Actor
|
||||
}
|
||||
# off the stage: the last actor takes its row, so the list stays dense and nothing is rebuilt
|
||||
# (it was a new list of every other actor per removal, never freed)
|
||||
function actor_remove(render3d_st: mut Render3dState, a: Actor) -> void {
|
||||
if render3d_st.ac_actors == null { return }
|
||||
let keep = new []Actor
|
||||
for i in 0 .. len(render3d_st.ac_actors) { if render3d_st.ac_actors[i].id != a.id { push(keep, render3d_st.ac_actors[i]) } }
|
||||
render3d_st.ac_actors = keep
|
||||
let l = render3d_st.ac_actors
|
||||
if l == null or a == null { return }
|
||||
let r = a.row
|
||||
if r < 0 or r >= len(l) or l[r].id != a.id { return }
|
||||
let last = List.pop(l)
|
||||
if last.id != a.id {
|
||||
l[r] = last
|
||||
last.row = r
|
||||
}
|
||||
a.row = -1
|
||||
}
|
||||
|
||||
# back on the stage (an actor kept across a world swap)
|
||||
function actor_keep(render3d_st: mut Render3dState, a: Actor) -> void {
|
||||
if a == null { return }
|
||||
if render3d_st.ac_actors == null { render3d_st.ac_actors = new []Actor }
|
||||
a.row = len(render3d_st.ac_actors)
|
||||
push(render3d_st.ac_actors, a)
|
||||
}
|
||||
# colour one named part of the model (a material name from the file)
|
||||
function actor_tint_part(a: Actor, name: string, r: float, g: float, b: float) -> void {
|
||||
|
|
@ -114,8 +131,7 @@ function actor_new(render3d_st: mut Render3dState, model: Model) -> Actor {
|
|||
render3d_st.ac_next_id += 1; a.id = render3d_st.ac_next_id
|
||||
if model != null { a.radius = Math.max(model.radius, model.height) + 1.0 }
|
||||
a.cull = 450.0
|
||||
if render3d_st.ac_actors == null { render3d_st.ac_actors = new []Actor }
|
||||
push(render3d_st.ac_actors, a)
|
||||
actor_keep(render3d_st, a)
|
||||
return a
|
||||
}
|
||||
|
||||
|
|
@ -396,6 +412,8 @@ function ac_caster_count(render3d_st: mut Render3dState, a: Actor) -> void {
|
|||
# every actor off the stage at once, for a world being replaced. Actors own no GL objects;
|
||||
# their models belong to whoever loaded them.
|
||||
function actor_clear_all(render3d_st: mut Render3dState) -> void {
|
||||
render3d_st.ac_actors = new []Actor
|
||||
if render3d_st.ac_actors == null { render3d_st.ac_actors = new []Actor }
|
||||
for i in 0 .. len(render3d_st.ac_actors) { render3d_st.ac_actors[i].row = -1 }
|
||||
List.clear(render3d_st.ac_actors)
|
||||
outline_clear(render3d_st)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue