Skip to content

Commit

Permalink
Reduce work for performance
Browse files Browse the repository at this point in the history
  • Loading branch information
STREGA committed Dec 11, 2023
1 parent f897e92 commit 665ad01
Showing 1 changed file with 102 additions and 69 deletions.
171 changes: 102 additions & 69 deletions Sources/GateEngine/Physics/SkinCollider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,105 +18,133 @@ public final class SkinCollider: Collider3D {
public let geometry: RawGeometry
public let skin: Skin

public private(set) var transformedTriangles: [CollisionTriangle] = []
public private(set) var transformedTriangles: [CollisionTriangle]
private var attributesPerTriangle: [UInt32]! = nil

@MainActor
@inline(__always)
var rigComponent: Rig3DComponent? {
return entity[Rig3DComponent.self]
return entity.component(ofType: Rig3DComponent.self)
}

var currentAnimation: ObjectIdentifier? = nil
var computedAtAnimationProgress: Float = -1
var forceRecompute: Bool = true
@MainActor var needsRecompute: Bool {
@MainActor
var needsRecompute: Bool {
if forceRecompute {
return true
}
if let activeAnimation = rigComponent?.activeAnimation {
if currentAnimation != ObjectIdentifier(activeAnimation) {
return true
if let rigComponent {
if let activeAnimation = rigComponent.activeAnimation {
if currentAnimation != ObjectIdentifier(activeAnimation) {
return true
}
}
return rigComponent.animationProgress != computedAtAnimationProgress
}
return rigComponent?.animationProgress != computedAtAnimationProgress
return false
}

@MainActor func recomputeIfNeeded() {
guard let rigComponent = rigComponent else {return}
@MainActor
func populateAttributes() {
let indicies = geometry.indices.map({Int($0)})
let uvs = geometry.uvSets

let positionCount: Int = indicies.count

var transformedUVs: [[Size2]] = Array(repeating: Array(repeating: .zero, count: positionCount), count: geometry.uvSets.count)
for vertexIndex in indicies.indices {
let index = indicies[vertexIndex]

let index2_1 = index * 2
let index2_2 = index2_1 + 1

for setIndex in 0 ..< geometry.uvSets.count {
transformedUVs[setIndex][vertexIndex] = Size2(uvs[setIndex][index2_1], uvs[setIndex][index2_2])
}
}

for triangleIndex in transformedTriangles.indices {
var attributes: UInt32 = 0
for uvSetIndex in 0 ..< transformedUVs.count {
let uvSet = transformedUVs[uvSetIndex]
let uv = uvSet[triangleIndex * 3]
attributes |= CollisionTriangle.attributeParser(uv.x, uv.y, UInt32(uvSetIndex))
}
transformedTriangles[triangleIndex]._attributes = attributes
}
}

@MainActor
func recomputeIfNeeded() {
guard needsRecompute else {return}
forceRecompute = false
guard let rigComponent = rigComponent else {return}
self.forceRecompute = false
if let activeAnimation = rigComponent.activeAnimation {
currentAnimation = ObjectIdentifier(activeAnimation)
self.currentAnimation = ObjectIdentifier(activeAnimation)
}
computedAtAnimationProgress = rigComponent.animationProgress
self.computedAtAnimationProgress = rigComponent.animationProgress

let matrix = transform.matrix()
let matrix = self.transform.matrix()

let indicies = geometry.indices.map({Int($0)})
let positions = geometry.positions
let uvs = geometry.uvSet1
let indicies = self.geometry.indices.map({Int($0)})
let positions = self.geometry.positions

let boneMatricies = rigComponent.skeleton.getPose().shaderMatrixArray(orderedFromSkinJoints: skin.joints).map({$0.transposed()})
let boneIndicies = skin.jointIndices.map({Int($0)})
let boneWeights = skin.jointWeights
let boneMatricies = rigComponent.skeleton.getPose().shaderMatrixArray(orderedFromSkinJoints: self.skin.joints).map({$0.transposed()})
let boneIndicies = self.skin.jointIndices.map({Int($0)})
let boneWeights = self.skin.jointWeights

let positionCount: Int = indicies.count

var transformedPositions: [Position3] = Array(repeating: .zero, count: positionCount)
var transformedUVs: [Size2] = Array(repeating: .zero, count: positionCount)
var triangleIndex = 0
var triangleVertex = 0
for vertexIndex in indicies.indices {
let index = indicies[vertexIndex]

let index3_1 = index * 3
let index3_2 = index3_1 + 1
let index3_3 = index3_2 + 1

let index2_1 = index * 2
let index2_2 = index2_1 + 1

let vertex = Position3(positions[index3_1], positions[index3_2], positions[index3_3])

let position: Position3 = {
let index4_1: Int = index * 4
let index4_2: Int = index4_1 + 1
let index4_3: Int = index4_2 + 1
let index4_4: Int = index4_3 + 1

let boneIndex1: Int = boneIndicies[index4_1]
let boneIndex2: Int = boneIndicies[index4_2]
let boneIndex3: Int = boneIndicies[index4_3]
let boneIndex4: Int = boneIndicies[index4_4]

let boneMaterix1: Matrix4x4 = boneMatricies[boneIndex1]
let boneMaterix2: Matrix4x4 = boneMatricies[boneIndex2]
let boneMaterix3: Matrix4x4 = boneMatricies[boneIndex3]
let boneMaterix4: Matrix4x4 = boneMatricies[boneIndex4]

let boneWeight1: Float = boneWeights[index4_1]
let boneWeight2: Float = boneWeights[index4_2]
let boneWeight3: Float = boneWeights[index4_3]
let boneWeight4: Float = boneWeights[index4_4]

let w1: Position3 = boneMaterix1 * vertex * boneWeight1
let w2: Position3 = boneMaterix2 * vertex * boneWeight2
let w3: Position3 = boneMaterix3 * vertex * boneWeight3
let w4: Position3 = boneMaterix4 * vertex * boneWeight4
let index4_1: Int = index * 4
let index4_2: Int = index4_1 + 1
let index4_3: Int = index4_2 + 1
let index4_4: Int = index4_3 + 1

let boneIndex1: Int = boneIndicies[index4_1]
let boneIndex2: Int = boneIndicies[index4_2]
let boneIndex3: Int = boneIndicies[index4_3]
let boneIndex4: Int = boneIndicies[index4_4]

let boneMaterix1: Matrix4x4 = boneMatricies[boneIndex1]
let boneMaterix2: Matrix4x4 = boneMatricies[boneIndex2]
let boneMaterix3: Matrix4x4 = boneMatricies[boneIndex3]
let boneMaterix4: Matrix4x4 = boneMatricies[boneIndex4]

let boneWeight1: Float = boneWeights[index4_1]
let boneWeight2: Float = boneWeights[index4_2]
let boneWeight3: Float = boneWeights[index4_3]
let boneWeight4: Float = boneWeights[index4_4]

let w1: Position3 = boneMaterix1 * vertex * boneWeight1
let w2: Position3 = boneMaterix2 * vertex * boneWeight2
let w3: Position3 = boneMaterix3 * vertex * boneWeight3
let w4: Position3 = boneMaterix4 * vertex * boneWeight4

let position: Position3 = w1 + w2 + w3 + w4

// Update the vertex of the triangle
self.transformedTriangles[triangleIndex].positions[triangleVertex] = position * matrix

triangleVertex += 1
if triangleVertex == 3 {
// Recomupte the triangle once after all 3 verts have been updated
self.transformedTriangles[triangleIndex].recomputeAll()

return w1 + w2 + w3 + w4
}()

transformedPositions[vertexIndex] = position * matrix
transformedUVs[vertexIndex] = Size2(uvs[index2_1], uvs[index2_2])
triangleIndex += 1
triangleVertex = 0
}
}

transformedTriangles = stride(from: 0, to: transformedPositions.count, by: 3).map({
let uv = transformedUVs[$0]
let attributes = CollisionTriangle.attributeParser(uv.x, uv.y, 0)
return CollisionTriangle(
transformedPositions[$0 + 0],
transformedPositions[$0 + 1],
transformedPositions[$0 + 2],
attributes: attributes
)
})
}

public var center: Position3 {
Expand Down Expand Up @@ -213,7 +241,7 @@ public final class SkinCollider: Collider3D {
}
}
if let closestTriangle, let closest {
return SurfaceImpact3D(normal: closestTriangle.normal, position: closest)
return SurfaceImpact3D(normal: closestTriangle.normal, position: closest, triangle: closestTriangle)
}
return nil
}
Expand All @@ -236,13 +264,18 @@ public final class SkinCollider: Collider3D {

public var boundingBox: AxisAlignedBoundingBox3D = AxisAlignedBoundingBox3D()

@MainActor
public init(entity: Entity, geometry: RawGeometry, skin: Skin, boundingBoxSize: Size3) {
self.entity = entity
self.geometry = geometry
self.skin = skin

self.transformedTriangles = []
self.boundingBox.size = boundingBoxSize
self.boundingBox.offset.y = boundingBoxSize.y * 0.5

self.forceRecompute = true

self.transformedTriangles = Array(repeating: CollisionTriangle(.zero, .zero, .zero, attributes: 0), count: Int(geometry.indices.count / 3))
self.populateAttributes()
}
}

0 comments on commit 665ad01

Please sign in to comment.