# HG changeset patch # User Sam # Date 1688817154 -25200 # Node ID bb4c36d684440d2046a58268d919d25a62012340 # Parent bc48fcc1ac7b74f893c24b9837dca2eda401305d add: some API improvments for vector, entity, and some other stuff diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/core/vector.nim --- a/src/semicongine/core/vector.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/core/vector.nim Sat Jul 08 18:52:34 2023 +0700 @@ -15,9 +15,12 @@ Vec2f* = TVec2[float32] Vec3f* = TVec3[float32] Vec4f* = TVec4[float32] - Vec2i* = TVec2[uint32] - Vec3i* = TVec3[uint32] - Vec4i* = TVec4[uint32] + Vec2i* = TVec2[int32] + Vec3i* = TVec3[int32] + Vec4i* = TVec4[int32] + Vec2u* = TVec2[uint32] + Vec3u* = TVec3[uint32] + Vec4u* = TVec4[uint32] converter toVec2*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec2[T] = TVec2[T]([orig[0], orig[1]]) @@ -46,6 +49,18 @@ Vec3f([x, y, z]) func newVec4f*(x=0'f32, y=0'f32, z=0'f32, a=0'f32): auto = Vec4f([x, y, z, a]) +func newVec2i*(x=0'i32, y=0'i32): auto = + Vec2i([x, y]) +func newVec3i*(x=0'i32, y=0'i32, z=0'i32): auto = + Vec3i([x, y, z]) +func newVec4i*(x=0'i32, y=0'i32, z=0'i32, a=0'i32): auto = + Vec4i([x, y, z, a]) +func newVec2u*(x=0'u32, y=0'u32): auto = + Vec2u([x, y]) +func newVec3u*(x=0'u32, y=0'u32, z=0'u32): auto = + Vec3u([x, y, z]) +func newVec4u*(x=0'u32, y=0'u32, z=0'u32, a=0'u32): auto = + Vec4u([x, y, z, a]) # generates constants: Xf, Xf32, Xf64, Xi, Xi8, Xi16, Xi32, Xi64 # Also for Y, Z, R, G, B and One @@ -105,25 +120,18 @@ func length*(vec: TVec4[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[ 1] * vec[1] + vec[2] * vec[2] + vec[3] * vec[3])) -func normalized*[T](vec: TVec2[T]): auto = +func normalized*[T: SomeFloat](vec: TVec2[T]): auto = let l = vec.length - when T is SomeFloat: - TVec2[T]([vec[0] / l, vec[1] / l]) - else: - TVec2[float]([float(vec[0]) / l, float(vec[1]) / l]) -func normalized*[T](vec: TVec3[T]): auto = + if l == 0: vec + else: TVec2[T]([vec[0] / l, vec[1] / l]) +func normalized*[T: SomeFloat](vec: TVec3[T]): auto = let l = vec.length - when T is SomeFloat: - TVec3[T]([vec[0] / l, vec[1] / l, vec[2] / l]) - else: - TVec3[float]([float(vec[0]) / l, float(vec[1]) / l, float(vec[2]) / l]) -func normalized*[T](vec: TVec4[T]): auto = + if l == 0: return vec + else: TVec3[T]([vec[0] / l, vec[1] / l, vec[2] / l]) +func normalized*[T: SomeFloat](vec: TVec4[T]): auto = let l = vec.length - when T is SomeFloat: - TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) - else: - TVec4[float]([float(vec[0]) / l, float(vec[1]) / l, float(vec[2]) / l, - float(vec[3]) / l]) + if l == 0: return vec + else: TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l]) # scalar operations func `+`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] + b, a[1] + b]) @@ -222,7 +230,7 @@ # macro to allow creation of new vectors by specifying vector components as attributes # e.g. myVec.xxy will return a new Vec3 that contains the components x, x an y of the original vector # (instead of x, y, z for a simple copy) -proc vectorAttributeAccessor(accessor: string): NimNode = +proc vectorAttributeAccessor(accessor: string): seq[NimNode] = const ACCESSOR_INDICES = { 'x': 0, 'y': 1, @@ -233,28 +241,55 @@ 'b': 2, 'a': 3, }.toTable - var ret: NimNode + var getterCode, setterCode: NimNode let accessorvalue = accessor if accessorvalue.len == 0: raise newException(Exception, "empty attribute") elif accessorvalue.len == 1: - ret = nnkBracketExpr.newTree(ident("value"), newLit(ACCESSOR_INDICES[ - accessorvalue[0]])) + getterCode = nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])) + setterCode = nnkStmtList.newTree( + nnkAsgn.newTree( + nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[accessorvalue[0]])), ident("value")) + ) if accessorvalue.len > 1: var attrs = nnkBracket.newTree() for attrname in accessorvalue: - attrs.add(nnkBracketExpr.newTree(ident("value"), newLit(ACCESSOR_INDICES[attrname]))) - ret = nnkCall.newTree(ident("TVec" & $accessorvalue.len), attrs) + attrs.add(nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname]))) + getterCode = nnkCall.newTree(ident("TVec" & $accessorvalue.len), attrs) + setterCode = nnkStmtList.newTree() + var i = 0 + for attrname in accessorvalue: + setterCode.add nnkAsgn.newTree( + nnkBracketExpr.newTree(ident("vec"), newLit(ACCESSOR_INDICES[attrname])), + nnkBracketExpr.newTree(ident("value"), newLit(i)), + ) + inc i - newProc( + result.add newProc( name = nnkPostfix.newTree(ident("*"), ident(accessor)), - params = [ident("auto"), nnkIdentDefs.newTree(ident("value"), ident("TVec"), - newEmptyNode())], - body = newStmtList(ret), + params = [ident("auto"), nnkIdentDefs.newTree(ident("vec"), ident("TVec"), newEmptyNode())], + body = newStmtList(getterCode), procType = nnkFuncDef, ) + result.add nnkFuncDef.newTree( + nnkPostfix.newTree( + newIdentNode("*"), + nnkAccQuoted.newTree(newIdentNode(accessor), newIdentNode("=")) + ), + newEmptyNode(), + nnkGenericParams.newTree(nnkIdentDefs.newTree(newIdentNode("T"), newEmptyNode(), newEmptyNode())), + nnkFormalParams.newTree( + newEmptyNode(), + nnkIdentDefs.newTree( newIdentNode("vec"), nnkVarTy.newTree(newIdentNode("TVec")), newEmptyNode()), + nnkIdentDefs.newTree( newIdentNode("value"), newIdentNode("T"), newEmptyNode()) + ), + newEmptyNode(), + newEmptyNode(), + setterCode + ) + macro createVectorAttribAccessorFuncs() = const COORD_ATTRS = ["x", "y", "z", "w"] const COLOR_ATTRS = ["r", "g", "b", "a"] diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/engine.nim --- a/src/semicongine/engine.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/engine.nim Sat Jul 08 18:52:34 2023 +0700 @@ -82,7 +82,7 @@ enabledLayers.add "VK_LAYER_KHRONOS_validation" putEnv("VK_LAYER_ENABLES", "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT") - if defined(linux): + if defined(linux) and DEBUG: enabledLayers.add "VK_LAYER_MESA_overlay" result.instance = result.window.createInstance( vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/renderer.nim --- a/src/semicongine/renderer.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/renderer.nim Sat Jul 08 18:52:34 2023 +0700 @@ -142,6 +142,7 @@ let indexed = mesh.indexType != MeshIndexType.None var drawable = Drawable( + mesh: mesh, elementCount: if indexed: mesh.indicesCount else: mesh.vertexCount, bufferOffsets: offsets, instanceCount: mesh.instanceCount, diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/scene.nim Sat Jul 08 18:52:34 2023 +0700 @@ -60,6 +60,10 @@ if component of EntityAnimation and EntityAnimation(component).player.playing: result = result * EntityAnimation(component).player.currentValue +# TODO: position-setter +func position*(entity: Entity): Vec3f = + return entity.transform.col(3) + func originalTransform*(entity: Entity): Mat4 = entity.internal_transform diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/settings.nim --- a/src/semicongine/settings.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/settings.nim Sat Jul 08 18:52:34 2023 +0700 @@ -43,36 +43,36 @@ proc reloadSettings*() = allsettings = loadAllConfig() -proc configStr(key, section, namespace: string, default: string): string = +proc configStr(key, section, namespace: string): string = when CONFIGHOTRELOAD: while configUpdates.peek() > 0: let (updatedNamespace, updatedConfig) = configUpdates.recv() allsettings[updatedNamespace] = loadConfig(newStringStream(updatedConfig)) if not allsettings.hasKey(namespace): - return default - allsettings[namespace].getSectionValue(section, key, default) + raise newException(Exception, &"Settings {namespace}.{section}.{key} was not found") + allsettings[namespace].getSectionValue(section, key) -proc setting*[T: int|float|string](key, section, namespace: string, default: T): T = +proc setting*[T: int|float|string](key, section, namespace: string): T = when T is int: - let value = configStr(key, section, namespace, $default) + let value = configStr(key, section, namespace) if parseInt(value, result) == 0: raise newException(Exception, &"Unable to parse int from settings {namespace}.{section}.{key}: {value}") elif T is float: - let value = configStr(key, section, namespace, $default) + let value = configStr(key, section, namespace) if parseFloat(value, result) == 0: raise newException(Exception, &"Unable to parse float from settings {namespace}.{section}.{key}: {value}") else: - result = configStr(key, section, namespace, default) + result = configStr(key, section, namespace) -proc setting*[T: int|float|string](identifier: string, default: T): T = +proc setting*[T: int|float|string](identifier: string): T = # identifier can be in the form: # {namespace}.{key} # {namespace}.{section}.{key} let parts = identifier.rsplit(".") if parts.len == 1: raise newException(Exception, &"Setting with name {identifier} has no namespace") - if parts.len == 2: result = setting[T](parts[1], "", parts[0], default) - else: result = setting[T](parts[^1], parts[^2], joinPath(parts[0 .. ^3]), default) + if parts.len == 2: result = setting[T](parts[1], "", parts[0]) + else: result = setting[T](parts[^1], parts[^2], joinPath(parts[0 .. ^3])) proc hadConfigUpdate*(): bool = when CONFIGHOTRELOAD == true: diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/vulkan/drawable.nim --- a/src/semicongine/vulkan/drawable.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/vulkan/drawable.nim Sat Jul 08 18:52:34 2023 +0700 @@ -3,10 +3,13 @@ import std/logging import ../core +import ../mesh +import ../scene import ./buffer type Drawable* = object + mesh*: Mesh elementCount*: uint32 # number of vertices or indices bufferOffsets*: seq[(string, MemoryPerformanceHint, uint64)] # list of buffers and list of offset for each attribute in that buffer instanceCount*: uint32 # number of instance @@ -24,6 +27,8 @@ &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets})" proc draw*(commandBuffer: VkCommandBuffer, drawable: Drawable, vertexBuffers: Table[MemoryPerformanceHint, Buffer], indexBuffer: Buffer) = + if drawable.mesh.entity.transform == Mat4(): + return debug "Draw ", drawable var buffers: seq[VkBuffer] diff -r bc48fcc1ac7b -r bb4c36d68444 src/semicongine/vulkan/framebuffer.nim --- a/src/semicongine/vulkan/framebuffer.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/src/semicongine/vulkan/framebuffer.nim Sat Jul 08 18:52:34 2023 +0700 @@ -7,9 +7,9 @@ Framebuffer* = object device*: Device vk*: VkFramebuffer - dimension*: Vec2I + dimension*: Vec2u -proc createFramebuffer*(device: Device, renderpass: VkRenderPass, attachments: openArray[ImageView], dimension: Vec2I): Framebuffer = +proc createFramebuffer*(device: Device, renderpass: VkRenderPass, attachments: openArray[ImageView], dimension: Vec2u): Framebuffer = assert device.vk.valid assert renderpass.valid diff -r bc48fcc1ac7b -r bb4c36d68444 tests/test_vector.nim --- a/tests/test_vector.nim Wed Jun 28 00:36:57 2023 +0700 +++ b/tests/test_vector.nim Sat Jul 08 18:52:34 2023 +0700 @@ -1,13 +1,13 @@ import random -import math import semicongine -proc echoInfo(v: TVec) = +proc echoInfo[T](v: TVec2[T] or TVec3[T] or TVec4[T]) = echo v echo " Length: ", v.length - echo " Normlized: ", v.normalized + when T is SomeFloat: + echo " Normlized: ", v.normalized echo " negated: ", -v proc echoAdd[T, U](v1: T, v2: U) = @@ -144,6 +144,22 @@ echo "V3I.g: ", randVec3I().g echo "V3F.b: ", randVec3F().b + # test setters + var v1 = randVec2I(); v1.x = 1 ; v1.y = 2 ; v1.r = 3 ; v1.g = 4 + v1.xy = randVec2I() ; v1.yx = randVec2I() ; v1.rg = randVec2I() ; v1.gr = randVec2I() + var v2 = randVec2F(); v2.x = 1.0 ; v2.y = 2.0 ; v2.r = 3.0 ; v2.g = 4.0 + v2.xy = randVec2F() ; v2.yx = randVec2F() ; v2.rg = randVec2F() ; v2.gr = randVec2F() + + var v3 = randVec3I(); v3.x = 1 ; v3.y = 2 ; v3.z = 3 ; v3.r = 4 ; v3.g = 5 ; v3.b = 6 + v3.xyz = randVec3I() ; v3.rgb = randVec3I() + var v4 = randVec3F(); v4.x = 1.0 ; v4.y = 2.0 ; v4.z = 3.0 ; v4.r = 4.0 ; v4.g = 5.0 ; v4.b = 6.0 + v4.xyz = randVec3F() ; v4.rgb = randVec3F() + + var v5 = randVec4I(); v5.x = 1 ; v5.y = 2 ; v5.z = 3; v5.w = 4 ; v5.r = 5 ; v5.g = 6 ; v5.b = 7 ; v5.a = 8 + v5.xyzw = randVec4I() ; v5.rgba = randVec4I() + var v6 = randVec4F(); v6.x = 1.0 ; v6.y = 2.0 ; v6.z = 3.0 ; v6.w = 4.0 ; v6.r = 5.0 ; v6.g = 6.0 ; v6.b = 7.0 ; v6.a = 8.0 + v6.xyzw = randVec4F() ; v6.rgba = randVec4F() + echo "V2I.xx: ", randVec2I().xx echo "V2I.yx: ", randVec2I().xy echo "V2F.xx: ", randVec2F().xx