import * as RE from 'rogue-engine'; import * as THREE from 'three'; import * as CANNON from 'cannon-es'; import CannonRaycastVehicle from './CannonRaycastVehicle.re'; export default class CannonWheel extends RE.Component { @RE.props.object3d() wheel: THREE.Object3D; @RE.props.num() radiusOffset = 0; connectionPoint = new THREE.Vector3(0, 0, 0); raycastVehicle: CannonRaycastVehicle; wheelInfo: CANNON.WheelInfo; private matrixA = new THREE.Matrix4(); private matrixB = new THREE.Matrix4(); private matrixC = new THREE.Matrix4(); start() { this.raycastVehicle = RE.getComponent(CannonRaycastVehicle, this.object3d) as CannonRaycastVehicle; if (!(this.raycastVehicle instanceof CannonRaycastVehicle)) return; let radius = 0.3; if (this.wheel) { this.connectionPoint.copy(this.wheel.position); const bbox = new THREE.Box3().setFromObject(this.wheel); radius = bbox.max.x - bbox.min.x; } this.wheelInfo = new CANNON.WheelInfo({ radius: radius + this.radiusOffset, directionLocal: new CANNON.Vec3(0, -1, 0), suspensionStiffness: this.raycastVehicle.suspensionStiffness, suspensionRestLength: this.raycastVehicle.suspensionRestLength, frictionSlip: this.raycastVehicle.frictionSlip, dampingRelaxation: this.raycastVehicle.dampingRelaxation, dampingCompression: this.raycastVehicle.dampingCompression, maxSuspensionForce: this.raycastVehicle.maxSuspensionForce, rollInfluence: this.raycastVehicle.rollInfluence, axleLocal: new CANNON.Vec3(-1, 0, 0), chassisConnectionPointLocal: new CANNON.Vec3(this.connectionPoint.x, this.connectionPoint.y, this.connectionPoint.z), maxSuspensionTravel: this.raycastVehicle.maxSuspensionTravel, customSlidingRotationalSpeed: this.raycastVehicle.customSlidingRotationalSpeed, useCustomSlidingRotationalSpeed: this.raycastVehicle.useCustomSlidingRotationalSpeed, }); this.raycastVehicle.vehicle.wheelInfos.push(this.wheelInfo); } afterUpdate(): void { if (!this.wheel) return; const wheel = this.wheelInfo; if (!wheel) return; const pos = wheel.worldTransform.position; const rot = wheel.worldTransform.quaternion; this.wheel.position.set(pos.x, pos.y, pos.z); this.wheel.parent?.worldToLocal(this.wheel.position); this.wheel.quaternion.set(rot.x, rot.y, rot.z, rot.w); this.matrixA.makeRotationFromQuaternion(this.wheel.quaternion); this.wheel.updateMatrixWorld(); this.matrixB.copy((this.wheel.parent as THREE.Object3D).matrixWorld).invert(); this.matrixC.extractRotation(this.matrixB); this.matrixA.premultiply(this.matrixC); this.wheel.quaternion.setFromRotationMatrix(this.matrixA); } } RE.registerComponent(CannonWheel);