Compare commits

...

No commits in common. "2dccf140b1a405c9ae8ee63611633d5325826830" and "f1768275f4a6b8b272d70ffbad90bd389ede9e3a" have entirely different histories.

2 changed files with 6 additions and 553 deletions

View file

@ -382,65 +382,6 @@ type LookAtAxis* = enum
AxisMinusY
AxisMinusZ
# proc axisToVec3(axis: LookAtAxis): Vec3 {.inline.} =
# case axis:
# of AxisX: vec3(1,0,0)
# of AxisY: vec3(0,1,0)
# of AxisZ: vec3(0,0,1)
# of AxisMinusX: vec3(-1,0,0)
# of AxisMinusY: vec3(0,-1,0)
# of AxisMinusZ: vec3(0,0,-1)
# proc look_at*(self: GameObject,
# direction: Vec3,
# front: static[LookAtAxis] = AxisMinusY,
# up: static[LookAtAxis] = AxisZ,
# up_vector: Vec3 = vec3(0,0,1),
# influence: float32 = 1,
# ) =
# dump direction.normalize
# self.set_rotation_order Quaternion
# const front_i = if front <= AxisZ: front.int else: front.int - 3
# const up_i = if up <= AxisZ: up.int else: up.int - 3
# when front_i == up_i:
# {.error: "Front and up axes must be different".}
# dump front_i
# dump up_i
# var mat: array[3, Vec3]
# mat[front_i] = (if front <= AxisZ: direction else: -direction).normalize
# mat[up_i] = if up <= AxisZ: up_vector else: -up_vector
# var side_i = 0
# if front_i+1 in [up_i, up_i+3]:
# side_i = if front_i == 0: 2 else: front_i-1
# mat[side_i] = cross(mat[front_i], mat[up_i])
# mat[up_i] = cross(mat[side_i], mat[front_i])
# dump side_i
# echo "a"
# else:
# side_i = if up_i == 0: 2 else: up_i-1
# mat[side_i] = cross(mat[up_i], mat[front_i])
# mat[front_i] = cross(mat[side_i], mat[up_i])
# dump side_i
# echo "b"
# echo mat
# echo mix(self.rotation, cast[Mat3](mat).to_quat, influence).normalize * vec3(0,0,-1)
# var mat2 = mat
# mat2[side_i] = -mat2[side_i]
# echo mix(self.rotation, cast[Mat3](mat2).to_quat, influence).normalize * vec3(0,0,-1)
# self.rotation = mix(self.rotation, cast[Mat3](mat2).to_quat, influence).normalize
# proc add_behaviour*(self: GameObject, behaviour: unknown) =
# return behaviour.assign(self)
# proc remove_behaviour*(self: GameObject, behaviour: unknown) =
# return behaviour.unassign(self)
# proc add_behavior*(self: GameObject, behaviour: unknown) =
# return behaviour.assign(self)
# proc remove_behavior*(self: GameObject, behaviour: unknown) =
# return behaviour.unassign(self)
proc clone*(self: GameObject,
recursive: bool=true,
with_behaviours: bool=true,
@ -476,45 +417,26 @@ proc clone_impl*(self: GameObject, n: var GameObject, recursive: bool,
n.properties[k] = v.copy
# n.behaviours = @[]
# TODO: lods?
# if n.body.physics_mesh?
# n.body.physics_mesh = n.body.physics_mesh.clone {scene: null, recursive: false, instance_body: false}
# n.body.physics_mesh.scene = scene # assigning later to avoid being added
# TODO: lods
# TODO: physics version of a mesh
if new_parent != nil:
n.parent = new_parent
n.parent.children.add(n)
# self.body = self.body.clone # TODO if
# self.body = self.body.clone # TODO
# Warning! This only works reliably
# if the target scene have the same type of lights!
# # TODO: have all material based objects derive from mesh?
# if n.materials and scene != self.scene:
# for i,mat in n.materials:
# n.materials[i] = mat.clone_to_scene(scene)
n.scene = nil
if scene != nil:
scene.add_object(n, name=name)
# TODO
# if behaviours:
# for b in self.behaviours:
# b.assign(n)
# Adding children after ensures objects don't need to be sorted
# Adding children afterwards ensures objects don't need to be sorted
if recursive:
for i,child in self.children:
self.children[i] = child.clone(recursive, with_behaviours, name, new_parent=n, scene, instance_body=false)
# if instance_body
# n.body.instance()
# n._instance_children_bodies()
# TODO: instance children bodies
return n
# proc _instance_children_bodies*(self: GameObject) =
# for child in self.children:
# child.body.instance()
# child.instance_children_bodies()
# return
proc set_parent*(self: GameObject, parent: GameObject, keep_transform: bool=true) =
self.scene.make_parent(parent, self, keep_transform=keep_transform)
@ -559,13 +481,6 @@ iterator children_recursive*(self: GameObject, include_self: static[bool] = fals
else:
break
# proc load*(self: GameObject, options: Table[string, unknown]): Future[void] =
# if self.scene != nil
# return self.scene.load_objects(@[self], options)
# proc load_recursive*(self: GameObject, options: unknown) =
# return self.scene?.load_objects(self.get_descendants(true), options)
proc remove*(self: GameObject, recursive: bool = true) =
if self.scene.nonNil:
self.scene.remove_object(self, recursive)
@ -581,65 +496,6 @@ proc destroy*(self: GameObject, recursive: bool = true) =
self.object_render_ubo.unbind()
self.object_ubo.unbind()
# proc instance_probes*(self: GameObject) =
# if self.probe_cube != nil or self.probe_planar != nil:
# return
# var probe_options = self.properties.probe_options
# if probe_options != nil:
# let ob = self.scene.objects[probe_options.object]
# if probe_options.type == "OBJECT":
# if not ob != nil:
# if probe_options.object != "":
# console.error(&"Object '{self.name}' tries to use\n probe object '{probe_options.object}'\n which doesn't exist.")
# self.probe_cube = self.scene.background_probe ? self.scene.instance_probe()
# else:
# ob.probe_cube ? ob.instance_probes()
# self.probe_cube = ob.probe_cube
# self.probe_planar = ob.probe_planar
# case probe_options.type:
# of "CUBEMAP", "CUBE":
# self.probe_cube = newProbe(self, probe_options)
# of "PLANE":
# self.probe_planar = newProbe(self, probe_options)
# of "OBJECT":
# discard
# else:
# raise Error("Inavlid probe type: " & $probe_options.type)
# else:
# self.probe_cube = self.scene.background_probe ? self.scene.instance_probe()
# return
# proc draw_probe_once*(self: GameObject) =
# self.instance_probes()
# let probe = self.probe_cube or self.probe_planar
# if not probe:
# return
# probe.set_auto_refresh(false)
# probe.render()
# proc serialize_transform*(self: GameObject): seq[unknown] =
# let position = self.position
# let rotation = self.rotation
# return @[position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w]
# proc serialize_world_transform*(self: GameObject): seq[unknown] =
# let position = self.get_world_position_rotation().position
# let rotation = self.get_world_position_rotation().rotation
# return @[position.x, position.y, position.z, rotation.x, rotation.y, rotation.z, rotation.w]
# proc deserialize_transform*(self: GameObject, transform: unknown, influence: int = 1) =
# var position = self.position
# var rotation = self.rotation
# let scale = self.scale
# let (x,y,z,rx,ry,rz,rw) = transform.toTuple
# position.x += (x - position.x) * influence
# position.y += (y - position.y) * influence
# position.z += (z - position.z) * influence
# let q = quat(rx, ry, rz, rw)
# rotation = slerp(rotation, q, influence)
# return
proc convert_bone_child_to_bone_parent*(self: GameObject) =
assert self.parent == nil or self.parent.is_armature, "An armature parent is required"
var parent = self.parent.get_armature
@ -747,27 +603,3 @@ proc world_to_local*(self: GameObject, point: Vec3): Vec3 =
let wm = self.get_world_matrix.inverse
return wm * point
# proc get_bounding_box_recursive*(self: GameObject): Option[Vec3] =
# var (min,max) = self.bound_box
# var out_min = vec3(Inf, Inf, Inf)
# var out_max = vec3(-Inf, -Inf, -Inf)
# if not (min.x == min.y == min.z == max.x == max.y == max.z == 0):
# out_min = min(out_min, min)
# out_max = max(out_max, max)
# for c in self.children:
# let cbb = c.get_bounding_box_recursive()
# if cbb != nil:
# let mat = c.get_local_matrix()
# var v = vec3()
# # Transform all 8 permutations
# for x in @[0, 1]:
# for y in @[0, 1]:
# for z in @[0, 1]:
# v = vec3(cbb[x].x, cbb[y].y, cbb[z].z)
# v = transformMat4(v, mat)
# out_min = min(out_min, v)
# out_max = max(out_max, v)
# if out_min.x > out_max.x:
# return None
# return Some((out_min, out_max))

View file

@ -477,84 +477,6 @@ proc remove_modifier*(self: Mesh, modifier: VertexModifier) =
if index != -1:
self.remove_modifier index
# proc force_lod_level*(self: Mesh, level: unknown) =
# if not level != nil:
# for cam, data in pairs(self.last_lod):
# data.render_tick = -1
# return
# let mesh = self.lod_objects[level].?object ? self
# for cam, data in pairs(self.last_lod):
# data.mesh = mesh
# data.render_tick = nil
# return
# proc get_lod_mesh*(self: Mesh, viewport: unknown, min_length_px: unknown, render_tick: int): Mesh =
# # TODO: put min_length_px and render_tick in camera?
# var amesh = self
# if self.lod_objects.len != 0:
# var camera = viewport.camera
# camera = viewport.debug_camera ? camera
# # remember previous mesh and
# # avoid doing the same calculation several times
# var last_lod_data = self.last_lod[camera.name]
# if not last_lod_data != nil:
# self.last_lod[camera.name] = last_lod_data = {mesh: nil, render_tick: -1}.toTable
# let previous_mesh = last_lod_data.mesh
# if last_lod_data.render_tick >= render_tick:
# return previous_mesh
# last_lod_data.render_tick = render_tick
# let cwm = camera.world_matrix
# let cam_pos = vec3(cwm.m12, cwm.m13, cwm.m14)
# # Approximation to nearest point to the surface:
# # We clamp the camera position to the object's bounding box
# # we transform the point with the inverse matrix
# # we clamp with dimensions
# # we clamp with radius
# # we transform back with matrix
# # that's the approximate near distance
# # TODO: Optimize
# let inv = invert(self.world_matrix)
# if not inv != nil or not self.bound_box:
# if self.data != nil:
# # Return highest loaded LoD
# return self
# for {object}.toTable in self.lod_objects:
# if not object.data != nil:
# continue
# return object
# return self
# var p = transformMat4(cam_pos, inv)
# p = max(p, self.bound_box[0])
# p = min(p, self.bound_box[1])
# p = transformMat4(p, self.world_matrix)
# let distance_to_camera = dist(p, cam_pos)
# # world scale: assuming all three axes have same scale as X
# let m00 = self.world_matrix.m00
# let m01 = self.world_matrix.m01
# let m02 = self.world_matrix.m02
# let world_scale = sqrt(m00 * m00 + m01 * m01 + m02 * m02)
# # number that converts a length to screen pixels
# let poly_length_to_visual_size = (viewport.units_to_pixels / distance_to_camera) * world_scale
# # we'll going to find the biggest length
# # that is small enough on screen
# var biggest_length = self.avg_poly_length
# amesh = self
# # from highest to lowest
# for lod in reversed(self.lod_objects):
# var h_ratio = 1
# if amesh == previous_mesh:
# # hysteresis: ratio of distance the mesh can go
# # further away before popping back to a lower LoD
# h_ratio += lod.hysteresis
# let ob = lod.object
# let ob_apl = ob.avg_poly_length
# let visual_size_px = ob_apl * poly_length_to_visual_size * h_ratio
# if not amesh.data != nil or (ob_apl > biggest_length and visual_size_px < min_length_px):
# biggest_length = ob_apl
# amesh = ob
# last_lod_data.mesh = amesh
# return amesh
proc clone_impl*(self: Mesh, clone: Mesh): Mesh =
clone.last_lod.clear()
if clone.data.nonNil:
@ -575,169 +497,8 @@ proc clone*(self: Mesh,
return self.clone_impl(n)
proc sort_faces*(self: Mesh, camera_position: Vec3) =
# if self.data?.draw_method != GL_TRIANGLES:
# return
# let BIG_ENDIAN = 0
# let offsets = self.offsets
# let num_submeshes = (offsets.len / 2) - 1
# let varray = self.data.varray
# let iarray = self.data.iarray
# var stride = self.data.stride
# stride >>= 2
# let v = vec3()
# let vt = vec3()
# # we scale this vector so we avoid dividing triangle positions by 3
# var camera_position3 = camera_position
# var m4 = self.world_matrix
# m4 = invert(m4)
# camera_position3 = transformMat4(camera_position3, m4)
# camera_position3 = camera_position3 * 3
# let cp3x = camera_position3.x
# let cp3y = camera_position3.y
# let cp3z = camera_position3.z
# let sign = self.sort_sign
# # # Find out the furthest possible distance we can find, so that's 2**16
# # vec3
# for i in 0 ..< num_submeshes:
# let i2 = i << 1
# let va = varray.subarray(offsets[i2], offsets[i2 + 2])
# var ia = iarray.subarray(offsets[i2 + 1], offsets[i2 + 3])
# let num_triangles = (ia.len * 0.3333333333333333) or 0
# if face_sort_array.len < num_triangles:
# face_sort_array = makeSeq[float64](num_triangles)
# face_sort_array32 = makeSeq[uint32](face_sort_array.buffer)
# iarray_temporary = makeSeq[uint32](ia.len)
# var j2 = var j3 = 0
# for j in 0 ..< num_triangles:
# let v0 = ia[j3] * stride
# let v1 = ia[j3 + 1] * stride
# let v2 = ia[j3 + 2] * stride
# # vec3.set v, va[v0], va[v0+1], va[v0+2]
# # vec3.set vt, va[v1], va[v1+1], va[v1+2]
# # vec3.add v, v, vt
# # vec3.set vt, va[v2], va[v2+1], va[v2+2]
# # vec3.add v, v, vt
# # sqr_dist = vec3.sqrDist v, camera_position3
# var x = va[v0]
# var y = va[v0 + 1]
# var z = va[v0 + 2]
# x += va[v1]
# y += va[v1 + 1]
# z += va[v1 + 2]
# x += va[v2] - cp3x
# y += va[v2 + 1] - cp3y
# z += va[v2 + 2] - cp3z
# let sqr_dist = x * x + y * y + z * z
# face_sort_array[j] = sqr_dist * sign
# face_sort_array32[j2 + BIG_ENDIAN] = j
# j2 += 2
# j3 += 3
# face_sort_array.subarray(0, num_triangles).sort()
# iarray_temporary.set(ia)
# j3 = 0
# j2 = BIG_ENDIAN
# while j2 < num_triangles * 2:
# let t = face_sort_array32[j2]
# let t3 = t + (t << 1)
# ia[j3] = iarray_temporary[t3]
# ia[j3 + 1] = iarray_temporary[t3 + 1]
# ia[j3 + 2] = iarray_temporary[t3 + 2]
# j3 += 3
# j2 += 2
# self.update_iarray()
return
# proc generate_normals*(self: Mesh, normal_offset: float = 4 * 3) =
# # dbg?.clear_vertices()
# let offsets = self.offsets
# let num_submeshes = (offsets.len / 2) - 1
# let varray = self.data.varray
# let varray_byte = self.data.varray_byte
# let iarray = self.data.iarray
# var stride = self.data.stride
# let varray_int8 = makeSeq[int8](varray.buffer, varray.byteOffset, varray.bytelength)
# let iarray_u32 = makeSeq[uint32](iarray.buffer, iarray.byteOffset, iarray.bytelength >> 2)
# stride = stride
# let stride_f = stride >> 2
# # TODO: have the size be of the largest submesh, not the whole thing
# var normals = makeSeq[float32](varray.len * 3 / stride_f)
# var a = vec3()
# var b = vec3()
# let c = vec3()
# for i in 0 ..< num_submeshes:
# let i2 = i << 1
# let va = varray.subarray(offsets[i2], offsets[i2 + 2])
# # pre-adding normal offset to slice instead of adding it each time
# var va_n = varray_int8.subarray((offsets[i2] << 2) + normal_offset, (offsets[i2 + 2] << 2) + normal_offset)
# if va.bytelength / stride >= 65536:
# var ia = iarray_u32.subarray(offsets[i2 + 1] >> 1, offsets[i2 + 3] >> 1)
# else:
# ia = iarray.subarray(offsets[i2 + 1], offsets[i2 + 3])
# j = 0
# while j < ia.len:
# # get vertex indices, multiply by stride_f
# var v0 = var v0_3 = ia[j]
# var v1 = var v1_3 = ia[j + 1]
# var v2 = var v2_3 = ia[j + 2]
# v0 *= stride_f
# v1 *= stride_f
# v2 *= stride_f
# v0_3 *= 3
# v1_3 *= 3
# v2_3 *= 3
# # get delta position of v1 v2
# var x = va[v0]
# var y = va[v0 + 1]
# var z = va[v0 + 2]
# let v1x = va[v1] - x
# let v1y = va[v1 + 1] - y
# let v1z = va[v1 + 2] - z
# let v2x = va[v2] - x
# let v2y = va[v2 + 1] - y
# let v2z = va[v2 + 2] - z
# a = vec3(v1x, v1y, v1z)
# b = vec3(v2x, v2y, v2z)
# a = cross(a, b)
# a = normalize(a)
# # if dbg?
# # vec3.set b, x,y,z
# # vec3.add b, b, {x: v1x/3, y: v1y/3, z: v1z/3}
# # vec3.add b, b, {x: v2x/3, y: v2y/3, z: v2z/3}
# # vec3.transformMat4 c, b, @world_matrix
# # dbg.add_vertex c, {r:1,g:0,b:0,a:1}
# # vec3.scale a, a, 0.01
# # vec3.add b, b, a
# # vec3.scale a, a, 100
# # vec3.transformMat4 c, b, @world_matrix
# # dbg.add_vertex c, {r:1,g:0,b:0,a:1}
# # add to all vertices
# # TODO: add normal count
# # to divide at the ends instead of normalizing
# let (x,y,z) = a.toTuple
# normals[v0_3] += x
# normals[v0_3 + 1] += y
# normals[v0_3 + 2] += z
# normals[v1_3] += x
# normals[v1_3 + 1] += y
# normals[v1_3 + 2] += z
# normals[v2_3] += x
# normals[v2_3 + 1] += y
# normals[v2_3 + 2] += z
# j += 3
# # copy normals normalized to bytes
# var i_b = 0
# i3 = 0
# while i3 < normals.len:
# a = vec3(normals[i3], normals[i3 + 1], normals[i3 + 2])
# a = normalize(a)
# # console.log a
# va_n[i_b] = a.x * 127
# va_n[i_b + 1] = a.y * 127
# va_n[i_b + 2] = a.z * 127
# i_b += stride
# i3 += 3
# return
# TODO: support multiple index types with a generic?
# NOTE: doing it using the triangles and not the original polygons might be
# slightly inaccurate, unless mesh is trianglulated when baking
@ -836,100 +597,6 @@ proc generate_tangents*(self: MeshData, uv_layer_name, tangent_layer_name: strin
if i_b >= va_i8_len:
break
# proc displace_vertices*(self: Mesh, offset: Vec3) =
# if not self.data:
# return
# let (x,y,z) = offset.toTuple
# var varray = self.data.varray
# var stride = self.data.stride
# stride >>= 2
# i = 0
# while i < varray.len:
# varray[i] += x
# varray[i + 1] += y
# varray[i + 2] += z
# i += stride
# for bb in self.bound_box:
# let bb = bb + offset
# if self.data.vertex_buffers.len != 0:
# self.update_varray()
# return
# proc has_attribute*(self: Mesh, attribute_name: unknown): bool =
# for {name}.toTable in self.layout:
# if not attribute_name == name:
# continue
# return true
# return false
# proc insert_attribute*(self: Mesh, attribute: unknown) =
# # {name: 'xxxx', type: 'f', count: 3, offset: 0, location: 0}
# let varray = self.data.varray
# let iarray = self.data.iarray
# let stride = self.data.stride
# self.data?.remove(self)
# attribute.offset = stride
# attribute.location = self.layout[self.layout.len - 1].location + 1
# self.layout.add(attribute)
# let stride_f = stride >> 2 # assuming it's always aligned to 4 bytes
# var stride_f_out = stride_f
# let attr_size = attribute.dtype.size * attribute.count
# stride_f_out += ceil(attr_size / 4)
# let varray2 = makeSeq[float32]((varray.len / stride_f) * stride_f_out)
# var pos_in = var pos_out = 0
# let len = varray2.len
# let uarray = makeSeq[uint32](varray.buffer, varray.byteOffset, varray.len)
# var uarray2 = makeSeq[uint32](varray2.buffer, varray2.byteOffset, varray2.len)
# while pos_out < len:
# for i in 0 ..< stride_f:
# uarray2[pos_out + i] = uarray[pos_in + i]
# pos_in += stride_f
# pos_out += stride_f_out
# self.stride = stride_f_out << 2
# i = 2
# while i < self.offsets.len:
# self.offsets[i] = (self.offsets[i] / stride_f) * stride_f_out
# i += 2
# self.load_from_va_ia(varray2, iarray)
# proc split_triangles*(self: Mesh) =
# var varray_byte = self.data.varray_byte
# var iarray = self.data.iarray
# let stride = self.data.stride
# let vertices = @[]
# let indices = @[]
# let idx_out = 0
# for idx_in in iarray:
# let i = idx_in * stride
# vertices.add(varray_byte.subarray(i, i + stride)...)
# indices.add(++idx_out)
# varray_byte = makeSeq[uint8](vertices)
# let varray = makeSeq[float32](varray_byte.buffer)
# if idx_out > (1 << 16):
# iarray = makeSeq[uint32](indices)
# iarray = makeSeq[uint16](iarray.buffer)
# else:
# iarray = makeSeq[uint16](indices)
# self.offsets = @[0, 0, varray.len, iarray.bytelength >> 1]
# self.load_from_va_ia(varray, iarray)
# return
# proc origin_to_bounding_box_center*(self: Mesh, options: Table[string, unknown] = {:}.toTable) =
# let preserve_visual_position = options.preserve_visual_position ?: true
# let (bb0,bb1) = self.bound_box.toTuple
# var v = vec3()
# v = lerp(bb0, bb1, 0.5)
# v = -v
# self.displace_vertices(v)
# v = v * self.scale
# v = -v
# if preserve_visual_position:
# self.translate(v, self)
# return
# proc update_BB*(self: Mesh) =
# return self.update_bounding_box()
proc update_bounding_box*(self: Mesh) =
if self.data == nil or self.layout.len == 0:
return
@ -955,26 +622,6 @@ proc update_bounding_box*(self: Mesh) =
self.bound_box[0] = vec3(minx, miny, minz)
self.bound_box[1] = vec3(maxx, maxy, maxz)
# proc unload*(self: Mesh) =
# self.data?.remove(self)
# # @data = null
# for tex in self.related_textures:
# var idx = tex.mesh_users.find(self)
# if idx == -1:
# raise Error("this shouldn't happen")
# var popped = tex.mesh_users.pop()
# if popped != self:
# tex.mesh_users[idx] = popped
# if tex.mesh_users.len == 0:
# console.log(&"Texture {tex.name} has no more users, unloading")
# tex.unload()
# self.related_textures = @[]
# return
# proc destroy*(self: Mesh, recursive: bool = true) =
# self.data?.remove(self)
# procCall(self.GameObject.destroy(recursive))
proc debug_print_vertices*(self: Mesh, starts: int = 0, ends: int = 10) =
if self.data.varrays[0].len == 0:
return
@ -1032,29 +679,3 @@ proc add_polygonal_line*(self: Mesh, orig, dest: Vec3, width: float) =
self.last_polyline_left = left
self.data.update_varray()
# var fl32 = makeSeq[float32](1)
# var ui32 = makeSeq[uint32](fl32.buffer)
# let rounder = (1 << 12)
# proc write_f16(float: unknown): int =
# fl32[0] = float
# var fltInt32 = ui32[0]
# fltInt32 += fltInt32 and rounder
# var fltInt16 = (fltInt32 >> 31) << 5
# var tmp = (fltInt32 >> 23) and 255
# tmp = (tmp - 112) and (((112 - tmp) >> 4) >> 27)
# fltInt16 = (fltInt16 or tmp) << 10
# fltInt16 |= (fltInt32 >> 13) and 1023
# return fltInt16
# ui32[0] = (254 - 15) << 23
# let magic = fl32[0]
# ui32[0] = (127 + 16) << 23
# let was_inf_nan = fl32[0]
# proc read_f16(short: unknown) =
# ui32[0] = (short and 32767) << 13
# fl32[0] *= magic
# if fl32[0] >= was_inf_nan:
# ui32[0] |= 255 << 23
# ui32[0] |= (short and 32768) << 16
# return fl32[0]