Util: Remove unused JS functions, add min/max(vec), improve remove, add docs.

This commit is contained in:
Alberto Torres 2024-09-21 02:21:25 +02:00
parent 40b70003ec
commit 29e4735626
2 changed files with 50 additions and 82 deletions

View file

@ -342,16 +342,18 @@ proc clear_vertices*(self: Mesh) =
self.data.num_indices[0] = 0
proc remove_vertex*(self: Mesh, index: int) =
# TODO: This is only valid for points mode
if not (index >= 0):
return
# -1 or undefined
let num_indices = self.data.num_indices
return # ignore -1
assert self.data.num_indices[0] > index, "Invalid index"
let stride = self.data.stride
# move the last vertex to the one in index
let pos0 = num_indices[0] * stride
let pos0 = self.data.num_indices[0] * stride
let pos1 = index * stride
var bytes = self.data.varrays[0].to(int8)
bytes.copyWithin(pos1, pos0, pos0 + stride)
for i in 0 ..< stride:
bytes[pos1+i] = bytes[pos0+i]
self.data.num_indices[0] -= 1
proc ensure_capacity*(self: Mesh, extra_elements: int) =
if self.data == nil:
@ -371,7 +373,7 @@ proc ensure_capacity*(self: Mesh, extra_elements: int) =
while fpos >= cap:
cap *= 2
var va = newArrRef[float32](cap)
varray.copy_bytes_to va
copyMem(va.toPointer, varray.toPointer, bytelen)
self.load_from_va_ia @[va]
self.data.num_indices[0] = current_index
@ -381,8 +383,8 @@ proc ensure_capacity*(self: Mesh, extra_elements: int) =
# let ilen = self.offsets[self.offsets.len - 1]
# let offset = (self.pack_offset or 0) + buffer_offset
# try:
# let va = makeSeq[float32](data, offset, vlen)
# let ia = makeSeq[uint16](data, offset + vlen * 4, ilen)
# let va = newSeq[float32](data, offset, vlen)
# let ia = newSeq[uint16](data, offset + vlen * 4, ilen)
# except Exception as e:
# let e = Error(&"Mesh {self.name} is corrupt")
# raise e
@ -518,7 +520,7 @@ proc generate_tangents*(self: MeshData, uv_layer_name, tangent_layer_name: strin
for idx in ia.to int32:
maxi = max(maxi, idx)
# dump (max_len, maxi)
var tangents = makeSeq[Vec3](max_len div stride_f.int)
var tangents = newSeq[Vec3](max_len div stride_f.int)
# for va, ia in zip(self.varrays, self.iarrays):
for i in 0 ..< self.varrays.len:
let va = self.varrays[i]
@ -627,7 +629,7 @@ proc debug_print_vertices*(self: Mesh, starts: int = 0, ends: int = 10) =
of Short:
($cast[ptr array[16, uint16]](varray[offset].addr)[]).split(',')[0 ..< attr.count].join(",") & "]"
# of HalfFloat:
# let a = makeSeq[uint16](varray.buffer, offset, attr.count)
# let a = newSeq[uint16](varray.buffer, offset, attr.count)
# @[read_f16(a[0]), read_f16(a[1]), read_f16(a[2])]
else: ""
echo &"{attr.name} {data}"

View file

@ -75,96 +75,55 @@ func remove_scale_skew*[T](m: GMat4[T]): GMat4[T] =
result[3,1] = m[3,1]
result[3,2] = m[3,2]
proc remove*[T](s: var seq[T], element: T) =
proc remove*[T](s: var seq[T], element: T): bool {.raises:[],discardable.} =
## Removes a value from a seq if it exists. Returns whether an item was
## removed. Preserves the order of the other elements. If the element is
## repeated, only one instance is removed.
let index = s.find element
if index != -1:
s.delete index
# TODO: option to warn or break when not present
# and a version or an argument to not warn
# Since we only remove an existing element, it should never raise,
# but we have to use try/except to satisfy raises:[]
try: s.delete index
except: discard
return true
proc remove_unordered*[T](s: seq[T], element: T) =
proc remove_unordered*[T](s: seq[T], element: T): bool {.raises:[],discardable.} =
## Removes a value from a seq if it exists. Returns whether an item was
## removed. It's quicker than `remove` by moving the last element to the slot
## of the removed one. If the element is repeated, only one instance is
## removed.
let index = s.find element
if index != -1:
s.del index
# Since we only remove an existing element, it should never raise,
# but we have to use try/except to satisfy raises:[]
try: s.del index
except: discard
return true
func align4*[T: SomeInteger](n: T): T = n + ((4-(n and 3)) and 3)
func align4*[T: SomeInteger](n: T): T =
# Increments the number to the nearest multiplier of 4 if it's not already
# aligned.
n + ((4-(n and 3)) and 3)
func align*[T: SomeInteger](n, align: T): T =
## Increments the number to the nearest multiplier of the `align` parameter,
## if it's not already aligned. `align` must be a power of two.
let mask = align - 1
assert((align and mask) == 0, "align must be a power of two")
return n + ((align-(n and mask)) and mask)
func bytelen*[T](s: seq[T]): int = s.len * sizeof(T)
func bytelen*[T](s: seq[T]): int =
## Provides the size of the seq in bytes.
s.len * sizeof(T)
func get_or_default*[T](s: seq[T], i: int, default: T = T.default): T =
func getOrDefault*[T](s: seq[T], i: int, default: T = T.default): T =
## Returns an element of the seq if the index is within bounds, otherwise it
## returns a default value, optionally given as argument.
if i >= s.low and i <= s.high:
return s[i]
return default
when defined(js):
import jsffi
proc newArrayBufferView(size: uint8): seq[uint8] {.importjs: "(new Uint8Array(#))".}
proc newArrayBufferView(size: uint16): seq[uint16] {.importjs: "(new Uint16Array(#))".}
proc newArrayBufferView(size: uint32): seq[uint32] {.importjs: "(new Uint32Array(#))".}
proc newArrayBufferView(size: int8): seq[int8] {.importjs: "(new Int8Array(#))".}
proc newArrayBufferView(size: int16): seq[int16] {.importjs: "(new Int16Array(#))".}
proc newArrayBufferView(size: int32): seq[int32] {.importjs: "(new Int32Array(#))".}
proc newArrayBufferView(size: float32): seq[float32] {.importjs: "(new Float32Array(#))".}
proc newArrayBufferView(size: float64): seq[float64] {.importjs: "(new Float64Array(#))".}
template makeSeq*[T](size: int): seq[T] =
# incredibly cursed hack, but it works
newArrayBufferView(size.tojs.to(typeof T))
proc as_byte_array*[T](arr: seq[T]): seq[int8] {.importjs: "(new Int8Array((#).buffer))".}
proc as_ubyte_array*[T](arr: seq[T]): seq[uint8] {.importjs: "(new Uint8Array((#).buffer))".}
proc set*[T](arr, arr2: seq[T]) {.importjs: "((#).set(#))"}
template copy_bytes_to*[T](arr, arr2: seq[T]) =
arr2.as_byte_array.set arr.as_byte_array
proc copyWithin*[T](arr: seq[T], target, start, ends: int) {.importjs: "#.copyWithin(#,#,#)".}
else:
template makeSeq*[T](size: int): seq[T] = newSeq[T](size)
template as_byte_array*[T](arr: openArray[T]): ptr UncheckedArray[int8] =
cast[ptr UncheckedArray[int8]](addr arr[0])
template as_ubyte_array*[T](arr: openArray[T]): ptr UncheckedArray[uint8] =
cast[ptr UncheckedArray[uint8]](addr arr[0])
template as_byte_array*[T](arr: ArrRef[T]): ArrRef[int8] =
arr.to(int8)
template as_ubyte_array*[T](arr: ArrRef[T]): ArrRef[uint8] =
arr.to(uint8)
template set*[T](arr, arr2: seq[T]) =
for i,v in arr2:
arr[i] = v
template copy_bytes_to*[T](arr, arr2: seq[T]|ArrRef[T]) =
let src = arr.as_byte_array
let dst = arr2.as_byte_array
for i in 0 .. min(arr.byte_len, arr2.byte_len):
dst[i] = src[i]
# TODO: version of arrays with len, that clamps bounds and can use negative indices
proc copyWithin*[T](arr: ptr UncheckedArray[T], target, start, ends: int) =
let len = ends-start
let target_end = target + len
if start < target and target < ends:
# reverse (#TODO: only the overlapping section?)
var i = ends - 1
var o = target_end - 1
while i != start:
arr[o] = arr[i]
i -= 1; o -= 1
else:
var i = start
var o = target
while i != ends:
arr[o] = arr[i]
i += 1; o += 1
template copyWithin*[T](arr: ArrRef[T], target, start, ends: int) =
copyWithin(cast[ptr UncheckedArray[T]](arr[0].addr), target, start, ends)
template rotate_cw*[T](v: GVec3[T]): GVec3[T] = gvec3[T](v.y, -v.x, v.z)
template rotate_ccw*[T](v: GVec3[T]): GVec3[T] = gvec3[T](-v.y, v.x, v.z)
@ -243,6 +202,13 @@ template high*[T](x: typedesc[GVec2[T]]): GVec2[T] = gvec2[T](T.high,T.high)
template high*[T](x: typedesc[GVec3[T]]): GVec3[T] = gvec3[T](T.high,T.high,T.high)
template high*[T](x: typedesc[GVec4[T]]): GVec4[T] = gvec4[T](T.high,T.high,T.high,T.high)
proc min*[T](v: GVec2[T]): T {.inline.} = min(v.x, v.y)
proc min*[T](v: GVec3[T]): T {.inline.} = min(min(v.x, v.y), v.z)
proc min*[T](v: GVec4[T]): T {.inline.} = min(min(min(v.x, v.y), v.z), v.w)
proc max*[T](v: GVec2[T]): T {.inline.} = max(v.x, v.y)
proc max*[T](v: GVec3[T]): T {.inline.} = max(max(v.x, v.y), v.z)
proc max*[T](v: GVec4[T]): T {.inline.} = max(max(max(v.x, v.y), v.z), v.w)
# bounding box operations
template `&`*[T](a, b: (GVec3[T], GVec3[T])): (GVec3[T], GVec3[T]) =