refactor
This commit is contained in:
115
app/src/physics.ts
Normal file
115
app/src/physics.ts
Normal file
@@ -0,0 +1,115 @@
|
||||
import * as THREE from 'three'
|
||||
import * as CANNON from 'cannon-es'
|
||||
|
||||
export class PhysicsManager {
|
||||
static setupPhysicsWorld(): CANNON.World {
|
||||
const world = new CANNON.World()
|
||||
|
||||
// Setup physics world
|
||||
world.gravity.set(0, 0, 0)
|
||||
|
||||
// Use SAPBroadphase for better collision detection with many objects
|
||||
world.broadphase = new CANNON.SAPBroadphase(world)
|
||||
|
||||
// Enable collision detection and response
|
||||
world.allowSleep = false // Prevent objects from sleeping
|
||||
|
||||
// Configure contact material for better collisions
|
||||
const defaultMaterial = new CANNON.Material('default')
|
||||
const defaultContactMaterial = new CANNON.ContactMaterial(defaultMaterial, defaultMaterial, {
|
||||
friction: 0.4,
|
||||
restitution: 0.3,
|
||||
contactEquationStiffness: 1e8,
|
||||
contactEquationRelaxation: 3,
|
||||
frictionEquationStiffness: 1e8,
|
||||
frictionEquationRelaxation: 3
|
||||
})
|
||||
world.addContactMaterial(defaultContactMaterial)
|
||||
world.defaultMaterial = defaultMaterial
|
||||
|
||||
return world
|
||||
}
|
||||
|
||||
static updatePhysics(
|
||||
world: CANNON.World,
|
||||
physicsObjects: Array<{ mesh: THREE.Object3D; body: CANNON.Body }>,
|
||||
attractionPoint: THREE.Vector3,
|
||||
mouseWorldPosition: THREE.Vector3,
|
||||
deltaTime: number
|
||||
): void {
|
||||
// Use a smaller, more stable timestep for better collision detection
|
||||
const fixedTimeStep = 1/60 // 60 Hz - more stable than 120 Hz
|
||||
const maxSubSteps = 5 // Increased substeps for better collision accuracy
|
||||
|
||||
world.step(fixedTimeStep, deltaTime, maxSubSteps)
|
||||
|
||||
// Apply forces to objects
|
||||
physicsObjects.forEach((obj) => {
|
||||
// Attraction to center point
|
||||
const attractionForce = new CANNON.Vec3()
|
||||
attractionForce.x = attractionPoint.x - obj.body.position.x
|
||||
attractionForce.y = attractionPoint.y - obj.body.position.y
|
||||
attractionForce.z = attractionPoint.z - obj.body.position.z
|
||||
|
||||
const distance = Math.sqrt(
|
||||
attractionForce.x * attractionForce.x +
|
||||
attractionForce.y * attractionForce.y +
|
||||
attractionForce.z * attractionForce.z
|
||||
)
|
||||
|
||||
if (distance > 0) {
|
||||
const strength = 16.0 / (distance * distance + 1) // Reduced from 8.0 to prevent objects moving too fast
|
||||
attractionForce.scale(strength, attractionForce)
|
||||
obj.body.force.set(
|
||||
obj.body.force.x + attractionForce.x,
|
||||
obj.body.force.y + attractionForce.y,
|
||||
obj.body.force.z + attractionForce.z
|
||||
)
|
||||
}
|
||||
|
||||
// Mouse repulsion
|
||||
const repulsionForce = new CANNON.Vec3()
|
||||
repulsionForce.x = obj.body.position.x - mouseWorldPosition.x
|
||||
repulsionForce.y = obj.body.position.y - mouseWorldPosition.y
|
||||
repulsionForce.z = obj.body.position.z - mouseWorldPosition.z
|
||||
|
||||
const mouseDistance = Math.sqrt(
|
||||
repulsionForce.x * repulsionForce.x +
|
||||
repulsionForce.y * repulsionForce.y +
|
||||
repulsionForce.z * repulsionForce.z
|
||||
)
|
||||
|
||||
if (mouseDistance < 3 && mouseDistance > 0) {
|
||||
const repulsionStrength = 5.0 / (mouseDistance * mouseDistance + 0.1)
|
||||
repulsionForce.scale(repulsionStrength, repulsionForce)
|
||||
obj.body.force.set(
|
||||
obj.body.force.x + repulsionForce.x,
|
||||
obj.body.force.y + repulsionForce.y,
|
||||
obj.body.force.z + repulsionForce.z
|
||||
)
|
||||
|
||||
// Debug log to verify mouse repulsion is working
|
||||
console.log('Mouse repulsion applied, distance:', mouseDistance.toFixed(2), 'strength:', repulsionStrength.toFixed(2))
|
||||
|
||||
// Add rotational torque from mouse interaction
|
||||
const torque = new CANNON.Vec3(
|
||||
(Math.random() - 0.5) * repulsionStrength * 0.1,
|
||||
(Math.random() - 0.5) * repulsionStrength * 0.1,
|
||||
(Math.random() - 0.5) * repulsionStrength * 0.1
|
||||
)
|
||||
obj.body.torque.set(
|
||||
obj.body.torque.x + torque.x,
|
||||
obj.body.torque.y + torque.y,
|
||||
obj.body.torque.z + torque.z
|
||||
)
|
||||
}
|
||||
|
||||
// Apply damping
|
||||
obj.body.velocity.scale(0.99, obj.body.velocity)
|
||||
|
||||
// Update mesh position to match physics body
|
||||
obj.mesh.position.copy(obj.body.position as any)
|
||||
obj.mesh.quaternion.copy(obj.body.quaternion as any)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user