Fix B3D reader: Don't rely on table constructor execution order

This commit is contained in:
Lars Mueller 2021-02-26 18:36:46 +01:00
parent ba4a6ab8e6
commit fe26d4c793

114
b3d.lua

@ -82,12 +82,12 @@ function read(stream)
end end
local function color() local function color()
return { local color = {}
r = float(), color.r = float()
g = float(), color.g = float()
b = float(), color.b = float()
a = float() color.a = float()
} return color
end end
local function vector3() local function vector3()
@ -95,7 +95,8 @@ function read(stream)
end end
local function quaternion() local function quaternion()
return {[4] = float(), [1] = float(), [2] = float(), [3] = float()} local w, x, y, z = float(), float(), float(), float()
return {x, y, z, w}
end end
local function content() local function content()
@ -108,14 +109,14 @@ function read(stream)
TEXS = function() TEXS = function()
local textures = {} local textures = {}
while content() do while content() do
table.insert(textures, { local texture = {}
file = string(), texture.file = string()
flags = int(), texture.flags = int()
blend = int(), texture.blend = int()
pos = float_array(2), texture.pos = float_array(2)
scale = float_array(2), texture.scale = float_array(2)
rotation = float() texture.rotation = float()
}) table.insert(textures, texture)
end end
return textures return textures
end, end,
@ -124,14 +125,13 @@ function read(stream)
brushes.n_texs = int() brushes.n_texs = int()
assert(brushes.n_texs <= 8) assert(brushes.n_texs <= 8)
while content() do while content() do
local brush = { local brush = {}
name = string(), brush.name = string()
color = color(), brush.color = color()
shininess = float(), brush.shininess = float()
blend = float(), brush.blend = float()
fx = float(), brush.fx = float()
texture_id = {} brush.texture_id = {}
}
for index = 1, brushes.n_texs do for index = 1, brushes.n_texs do
brush.texture_id[index] = optional_id() brush.texture_id[index] = optional_id()
end end
@ -140,21 +140,19 @@ function read(stream)
return brushes return brushes
end, end,
VRTS = function() VRTS = function()
local vertices = { local vertices = {}
flags = int(), vertices.flags = int()
tex_coord_sets = int(), vertices.tex_coord_sets = int()
tex_coord_set_size = int() vertices.tex_coord_set_size = int()
}
assert(vertices.tex_coord_sets <= 8 and vertices.tex_coord_set_size <= 4) assert(vertices.tex_coord_sets <= 8 and vertices.tex_coord_set_size <= 4)
local has_normal = (vertices.flags % 2 == 1) or nil local has_normal = (vertices.flags % 2 == 1) or nil
local has_color = (math.floor(vertices.flags / 2) % 2 == 1) or nil local has_color = (math.floor(vertices.flags / 2) % 2 == 1) or nil
while content() do while content() do
local vertex = { local vertex = {}
pos = vector3(), vertex.pos = vector3()
normal = has_normal and vector3(), vertex.normal = has_normal and vector3()
color = has_color and color(), vertex.color = has_color and color()
tex_coords = {} vertex.tex_coords = {}
}
for tex_coord_set = 1, vertices.tex_coord_sets do for tex_coord_set = 1, vertices.tex_coord_sets do
local tex_coords = {} local tex_coords = {}
for tex_coord = 1, vertices.tex_coord_set_size do for tex_coord = 1, vertices.tex_coord_set_size do
@ -172,15 +170,16 @@ function read(stream)
vertex_ids = {} vertex_ids = {}
} }
while content() do while content() do
table.insert(tris.vertex_ids, {id(), id(), id()}) -- possibly obsolete if Lua guarantees a certain order of execution for list table constructors
local id_1, id_2, id_3 = id(), id(), id()
table.insert(tris.vertex_ids, {id_1, id_2, id_3})
end end
return tris return tris
end, end,
MESH = function() MESH = function()
local mesh = { local mesh = {}
brush_id = optional_id(), mesh.brush_id = optional_id()
vertices = chunk{VRTS = true} mesh.vertices = chunk{VRTS = true}
}
mesh.triangle_sets = {} mesh.triangle_sets = {}
repeat repeat
local tris = chunk{TRIS = true} local tris = chunk{TRIS = true}
@ -218,34 +217,33 @@ function read(stream)
flags = flags flags = flags
} }
while content() do while content() do
table.insert(bone, { local frame = {}
frame = int(), frame.frame = int()
position = position and vector3() or nil, frame.position = position and vector3() or nil
scale = scale and vector3() or nil, frame.scale = scale and vector3() or nil
rotation = rotation and quaternion() or nil frame.rotation = rotation and quaternion() or nil
}) table.insert(bone, frame)
end end
-- Ensure frames are sorted ascending -- Ensure frames are sorted ascending
table.sort(bone, function(a, b) return a.frame < b.frame end) table.sort(bone, function(a, b) return a.frame < b.frame end)
return bone return bone
end, end,
ANIM = function() ANIM = function()
return { local anim = {}
-- flags are unused -- flags are unused
flags = int(), anim.flags = int()
frames = int(), anim.frames = int()
fps = float() anim.fps = float()
} return anim
end, end,
NODE = function() NODE = function()
local node = { local node = {}
name = string(), node.name = string()
position = vector3(), node.position = vector3()
scale = vector3(), node.scale = vector3()
keys = {}, node.keys = {}
rotation = quaternion(), node.rotation = quaternion()
children = {} node.children = {}
}
local node_type local node_type
-- See https://github.com/blitz-research/blitz3d/blob/master/blitz3d/loader_b3d.cpp#L263 -- See https://github.com/blitz-research/blitz3d/blob/master/blitz3d/loader_b3d.cpp#L263
-- Order is not validated; double occurences of mutually exclusive node def are -- Order is not validated; double occurences of mutually exclusive node def are