Util: Remove unused JS functions, add min/max(vec), improve remove, add docs.
This commit is contained in:
parent
40b70003ec
commit
29e4735626
2 changed files with 50 additions and 82 deletions
|
@ -342,16 +342,18 @@ proc clear_vertices*(self: Mesh) =
|
||||||
self.data.num_indices[0] = 0
|
self.data.num_indices[0] = 0
|
||||||
|
|
||||||
proc remove_vertex*(self: Mesh, index: int) =
|
proc remove_vertex*(self: Mesh, index: int) =
|
||||||
|
# TODO: This is only valid for points mode
|
||||||
if not (index >= 0):
|
if not (index >= 0):
|
||||||
return
|
return # ignore -1
|
||||||
# -1 or undefined
|
assert self.data.num_indices[0] > index, "Invalid index"
|
||||||
let num_indices = self.data.num_indices
|
|
||||||
let stride = self.data.stride
|
let stride = self.data.stride
|
||||||
# move the last vertex to the one in index
|
# 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
|
let pos1 = index * stride
|
||||||
var bytes = self.data.varrays[0].to(int8)
|
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) =
|
proc ensure_capacity*(self: Mesh, extra_elements: int) =
|
||||||
if self.data == nil:
|
if self.data == nil:
|
||||||
|
@ -371,7 +373,7 @@ proc ensure_capacity*(self: Mesh, extra_elements: int) =
|
||||||
while fpos >= cap:
|
while fpos >= cap:
|
||||||
cap *= 2
|
cap *= 2
|
||||||
var va = newArrRef[float32](cap)
|
var va = newArrRef[float32](cap)
|
||||||
varray.copy_bytes_to va
|
copyMem(va.toPointer, varray.toPointer, bytelen)
|
||||||
self.load_from_va_ia @[va]
|
self.load_from_va_ia @[va]
|
||||||
self.data.num_indices[0] = current_index
|
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 ilen = self.offsets[self.offsets.len - 1]
|
||||||
# let offset = (self.pack_offset or 0) + buffer_offset
|
# let offset = (self.pack_offset or 0) + buffer_offset
|
||||||
# try:
|
# try:
|
||||||
# let va = makeSeq[float32](data, offset, vlen)
|
# let va = newSeq[float32](data, offset, vlen)
|
||||||
# let ia = makeSeq[uint16](data, offset + vlen * 4, ilen)
|
# let ia = newSeq[uint16](data, offset + vlen * 4, ilen)
|
||||||
# except Exception as e:
|
# except Exception as e:
|
||||||
# let e = Error(&"Mesh {self.name} is corrupt")
|
# let e = Error(&"Mesh {self.name} is corrupt")
|
||||||
# raise e
|
# raise e
|
||||||
|
@ -518,7 +520,7 @@ proc generate_tangents*(self: MeshData, uv_layer_name, tangent_layer_name: strin
|
||||||
for idx in ia.to int32:
|
for idx in ia.to int32:
|
||||||
maxi = max(maxi, idx)
|
maxi = max(maxi, idx)
|
||||||
# dump (max_len, maxi)
|
# 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 va, ia in zip(self.varrays, self.iarrays):
|
||||||
for i in 0 ..< self.varrays.len:
|
for i in 0 ..< self.varrays.len:
|
||||||
let va = self.varrays[i]
|
let va = self.varrays[i]
|
||||||
|
@ -627,7 +629,7 @@ proc debug_print_vertices*(self: Mesh, starts: int = 0, ends: int = 10) =
|
||||||
of Short:
|
of Short:
|
||||||
($cast[ptr array[16, uint16]](varray[offset].addr)[]).split(',')[0 ..< attr.count].join(",") & "]"
|
($cast[ptr array[16, uint16]](varray[offset].addr)[]).split(',')[0 ..< attr.count].join(",") & "]"
|
||||||
# of HalfFloat:
|
# 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])]
|
# @[read_f16(a[0]), read_f16(a[1]), read_f16(a[2])]
|
||||||
else: ""
|
else: ""
|
||||||
echo &"{attr.name} {data}"
|
echo &"{attr.name} {data}"
|
||||||
|
|
110
src/util.nim
110
src/util.nim
|
@ -75,96 +75,55 @@ func remove_scale_skew*[T](m: GMat4[T]): GMat4[T] =
|
||||||
result[3,1] = m[3,1]
|
result[3,1] = m[3,1]
|
||||||
result[3,2] = m[3,2]
|
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
|
let index = s.find element
|
||||||
if index != -1:
|
if index != -1:
|
||||||
s.delete index
|
# Since we only remove an existing element, it should never raise,
|
||||||
# TODO: option to warn or break when not present
|
# but we have to use try/except to satisfy raises:[]
|
||||||
# and a version or an argument to not warn
|
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
|
let index = s.find element
|
||||||
if index != -1:
|
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 =
|
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
|
let mask = align - 1
|
||||||
assert((align and mask) == 0, "align must be a power of two")
|
assert((align and mask) == 0, "align must be a power of two")
|
||||||
return n + ((align-(n and mask)) and mask)
|
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:
|
if i >= s.low and i <= s.high:
|
||||||
return s[i]
|
return s[i]
|
||||||
return default
|
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_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)
|
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[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)
|
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
|
# bounding box operations
|
||||||
|
|
||||||
template `&`*[T](a, b: (GVec3[T], GVec3[T])): (GVec3[T], GVec3[T]) =
|
template `&`*[T](a, b: (GVec3[T], GVec3[T])): (GVec3[T], GVec3[T]) =
|
||||||
|
|
Loading…
Reference in a new issue