Mercurial > games > semicongine
changeset 746:386417abacba
add: need separate 2D collision in order to get correct normals
author | Sam <sam@basx.dev> |
---|---|
date | Tue, 06 Jun 2023 01:00:43 +0700 |
parents | 4d6609a44ea5 |
children | 37a9abfd0008 |
files | src/semicongine/collision.nim src/semicongine/core/vector.nim |
diffstat | 2 files changed, 71 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/src/semicongine/collision.nim Mon Jun 05 23:57:16 2023 +0700 +++ b/src/semicongine/collision.nim Tue Jun 06 01:00:43 2023 +0700 @@ -3,8 +3,8 @@ import ./core import ./scene -const MAX_COLLISON_DETECTION_ITERATIONS = 10 -const MAX_COLLISON_POINT_CALCULATION_ITERATIONS = 10 +const MAX_COLLISON_DETECTION_ITERATIONS = 20 +const MAX_COLLISON_POINT_CALCULATION_ITERATIONS = 20 type HitBox* = ref object of Component @@ -92,7 +92,7 @@ return false -func triangle(simplex: var seq[Vec3f], direction: var Vec3f): bool = +func triangle(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = let a = simplex[0] b = simplex[1] @@ -114,6 +114,8 @@ simplex = @[a, b] return line(simplex, direction) else: + if twoDimensional: + return true if (sameDirection(abc, ao)): direction = abc else: @@ -182,14 +184,14 @@ else: edges.add (faces[a], faces[b]) -func nextSimplex(simplex: var seq[Vec3f], direction: var Vec3f): bool = +func nextSimplex(simplex: var seq[Vec3f], direction: var Vec3f, twoDimensional=false): bool = case simplex.len of 2: simplex.line(direction) - of 3: simplex.triangle(direction) + of 3: simplex.triangle(direction, twoDimensional) of 4: simplex.tetrahedron(direction) else: raise newException(Exception, "Error in simplex") -func collisionPoint*[A, B](simplex: var seq[Vec3f], a: A, b: B): tuple[normal: Vec3f, penetrationDepth: float32] = +func collisionPoint3D[A, B](simplex: var seq[Vec3f], a: A, b: B): tuple[normal: Vec3f, penetrationDepth: float32] = var polytope = simplex faces = @[ @@ -260,6 +262,46 @@ result = (normal: minNormal, penetrationDepth: minDistance + 0.001'f32) + +func collisionPoint2D*[A, B](polytopeIn: seq[Vec3f], a: A, b: B): tuple[normal: Vec2f, penetrationDepth: float32] = + var + polytope = polytopeIn + minIndex = 0 + minDistance = high(float32) + iterCount = 0 + minNormal: Vec2f + + while minDistance == high(float32) and iterCount < MAX_COLLISON_POINT_CALCULATION_ITERATIONS: + for i in 0 ..< polytope.len: + let + j = (i + 1) mod polytope.len + vertexI = polytope[i] + vertexJ = polytope[j] + ij = vertexJ - vertexI + var + normal = newVec2f(ij.y, -ij.x).normalized() + distance = normal.dot(vertexI) + + if (distance < 0): + distance *= -1'f32 + normal = normal * -1'f32 + + if distance < minDistance: + minDistance = distance + minNormal = normal + minIndex = j + + let + support = supportPoint(a, b, minNormal.toVec3) + sDistance = minNormal.dot(support) + + if(abs(sDistance - minDistance) > 0.001): + minDistance = high(float32) + polytope.insert(support, minIndex) + inc iterCount + + result = (normal: minNormal, penetrationDepth: minDistance + 0.001'f32) + func intersects*[A, B](a: A, b: B): bool = var support = supportPoint(a, b, newVec3f(0.8153, -0.4239, 0.5786)) # just random initial vector @@ -292,7 +334,27 @@ return result simplex.insert(support, 0) if nextSimplex(simplex, direction): - let (normal, depth) = collisionPoint(simplex, a, b) + let (normal, depth) = collisionPoint3D(simplex, a, b) + return (true, normal, depth) + # prevent numeric instability + if direction == newVec3f(0, 0, 0): + direction[0] = 0.0001 + inc n + +func collision2D*[A, B](a: A, b: B): tuple[hasCollision: bool, normal: Vec2f, penetrationDepth: float32] = + var + support = supportPoint(a, b, newVec3f(0.8153, -0.4239, 0)) # just random initial vector + simplex = newSeq[Vec3f]() + direction = -support + n = 0 + simplex.insert(support, 0) + while n < MAX_COLLISON_DETECTION_ITERATIONS: + support = supportPoint(a, b, direction) + if support.dot(direction) <= 0: + return result + simplex.insert(support, 0) + if nextSimplex(simplex, direction, twoDimensional=true): + let (normal, depth) = collisionPoint2D(simplex, a, b) return (true, normal, depth) # prevent numeric instability if direction == newVec3f(0, 0, 0):
--- a/src/semicongine/core/vector.nim Mon Jun 05 23:57:16 2023 +0700 +++ b/src/semicongine/core/vector.nim Tue Jun 06 01:00:43 2023 +0700 @@ -26,6 +26,8 @@ func toVec4*[T: SomeNumber](orig: TVec3[T], value: T = default(T)): TVec4[T] = TVec4[T]([orig[0], orig[1], orig[2], value]) +func toVec3*[T: SomeNumber](orig: TVec2[T], value: T = default(T)): TVec3[T] = + TVec3[T]([orig[0], orig[1], value]) # define some often used constants func ConstOne2[T: SomeNumber](): auto {.compiletime.} = TVec2[T]([T(1), T(1)])