three-player-controller 0.3.6 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/playerController.ts","../src/utils/pathPlanner.ts","../src/utils/useVehicleController.ts"],"sourcesContent":["export * from \"./playerController\";\r\n","import type { RigidBody, World } from \"@dimforge/rapier3d-compat\";\r\nimport * as THREE from \"three\";\r\nimport { acceleratedRaycast, MeshBVH, MeshBVHHelper } from \"three-mesh-bvh\";\r\nimport type { GLTF } from \"three/examples/jsm/Addons.js\";\r\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\r\nimport { RoundedBoxGeometry } from \"three/examples/jsm/geometries/RoundedBoxGeometry.js\";\r\nimport { DRACOLoader } from \"three/examples/jsm/loaders/DRACOLoader.js\";\r\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\r\nimport * as BufferGeometryUtils from \"three/examples/jsm/utils/BufferGeometryUtils.js\";\r\nimport breakIconModule from \"../assets/imgs/break.png\";\r\nimport flyIconModule from \"../assets/imgs/fly.png\";\r\nimport jumpIconModule from \"../assets/imgs/jump.png\";\r\nimport vehicleIconModule from \"../assets/imgs/vehicle.png\";\r\nimport viewIconModule from \"../assets/imgs/view.png\";\r\nimport { ObstacleChecker, PathPlanner } from \"./utils/pathPlanner\";\r\nimport { createVehicleController } from \"./utils/useVehicleController\";\r\n\r\nTHREE.Mesh.prototype.raycast = acceleratedRaycast;\r\n\r\nlet controllerInstance: PlayerController | null = null;\r\nconst clock = new THREE.Clock();\r\n\r\n// ==================== 玩家控制器类型 ====================\r\nexport type PlayerControllerOptions = {\r\n scene: THREE.Scene;\r\n camera: THREE.PerspectiveCamera;\r\n controls: OrbitControls;\r\n playerModel: {\r\n url: string;\r\n idleAnim: string;\r\n walkAnim: string;\r\n runAnim: string;\r\n jumpAnim: string;\r\n leftWalkAnim?: string;\r\n rightWalkAnim?: string;\r\n backwardAnim?: string;\r\n flyAnim?: string;\r\n flyIdleAnim?: string;\r\n enterCarAnim?: string;\r\n exitCarAnim?: string;\r\n scale: number;\r\n gravity?: number;\r\n jumpHeight?: number;\r\n speed?: number;\r\n playerFlySpeed?: number;\r\n rotateY?: number;\r\n headObjName?: string;\r\n flyEnabled?: boolean;\r\n };\r\n initPos?: THREE.Vector3;\r\n mouseSensity?: number;\r\n minCamDistance?: number;\r\n maxCamDistance?: number;\r\n colliderMeshUrl?: string;\r\n isShowMobileControls?: boolean;\r\n thirdMouseMode?: 0 | 1 | 2 | 3;\r\n enableZoom?: boolean;\r\n enableOverShoulderView?: boolean;\r\n};\r\n\r\n// ==================== 车辆类型 ====================\r\nexport type VehicleOptions = {\r\n url: string;\r\n position: THREE.Vector3;\r\n wheelsNames: string[];\r\n scale?: number;\r\n animations: {\r\n openDoorAnim?: string;\r\n };\r\n boardingPoint: THREE.Vector3;\r\n seatOffset?: THREE.Vector3;\r\n chassisRatio?: number;\r\n suspensionRestLengthRatio?: number;\r\n followVehicleDirection?: boolean;\r\n speedMultiplier?: number;\r\n};\r\n\r\n// ==================== 多车辆实例类型 ====================\r\nexport type VehicleInstance = {\r\n vehicleGroup: THREE.Group;\r\n chassisBody: RigidBody;\r\n vehicleController: any;\r\n updateWheelVisuals: () => void;\r\n vehicleMixer?: THREE.AnimationMixer;\r\n vehicleActions?: Map<string, THREE.AnimationAction>;\r\n vehiclIsOpenDoor: boolean;\r\n vehicleBBox: THREE.Box3;\r\n pathPlanner: PathPlanner;\r\n // 每辆车独立的参数\r\n scale: number;\r\n boardingPoint: THREE.Vector3;\r\n seatOffset: THREE.Vector3;\r\n enterVehicleTime: number;\r\n chassisRatio: number;\r\n suspensionRestLengthRatio: number;\r\n size: {\r\n l: number;\r\n w: number;\r\n h: number;\r\n };\r\n speedMultiplier: number;\r\n};\r\n\r\nclass PlayerController {\r\n // ==================== 基本配置与参数 ====================\r\n loader: GLTFLoader = new GLTFLoader();\r\n scene!: THREE.Scene;\r\n camera!: THREE.PerspectiveCamera;\r\n controls!: OrbitControls;\r\n playerModel!: PlayerControllerOptions[\"playerModel\"];\r\n initPos!: THREE.Vector3;\r\n gravity!: number;\r\n jumpHeight!: number;\r\n curPlayerSpeed!: number;\r\n playerFlySpeed!: number;\r\n playerSpeed!: number;\r\n mouseSensity!: number;\r\n colliderMeshUrl!: string;\r\n playerFlyEnabled!: boolean;\r\n isShowMobileControls!: boolean;\r\n thirdMouseMode!: 0 | 1 | 2 | 3;\r\n enableZoom!: boolean;\r\n controllerMode: 0 | 1 = 0; // 0: 人物 1: 车辆\r\n enableOverShoulderView: boolean = false;\r\n isChangeControllerTransitionTimer: any = null;\r\n\r\n // ==================== 玩家基本属性 ====================\r\n playerRadius: number = 45;\r\n playerHeight: number = 180; // 玩家参考身高\r\n isFirstPerson: boolean = false;\r\n boundingBoxMinY: number = 0;\r\n\r\n // ==================== 测试参数 ====================\r\n displayPlayer: boolean = false;\r\n displayCollider: boolean = false;\r\n displayVisualizer: boolean = false;\r\n\r\n // ==================== 场景对象 ====================\r\n collider: THREE.Mesh | null = null;\r\n visualizer: MeshBVHHelper | null = null;\r\n player!: THREE.Mesh & { capsuleInfo?: any };\r\n person: THREE.Object3D | null = null;\r\n personHead: THREE.Object3D | null = null;\r\n collected: THREE.BufferGeometry[] = [];\r\n\r\n dynamicCollider: THREE.Mesh | null = null;\r\n dynamicCollected: THREE.BufferGeometry[] = [];\r\n\r\n // ==================== 多车辆相关 ====================\r\n vehicles: VehicleInstance[] = []; // 所有已加载车辆\r\n activeVehicle: VehicleInstance | null = null; // 当前驾驶/交互的车辆\r\n\r\n vehicleLength: number = 6; // 车辆参考长度\r\n readonly wheelSteeringQuat = new THREE.Quaternion();\r\n readonly wheelRotationQuat = new THREE.Quaternion();\r\n RAPIER: any | null = null;\r\n world: World | null = null;\r\n\r\n // 全局车辆共享参数\r\n vehicleParams = {\r\n debug: {\r\n showPhysicsBox: true,\r\n },\r\n chassis: {\r\n linearDamping: 0.5,\r\n angularDamping: 0.5,\r\n },\r\n model: {\r\n rotation: -Math.PI / 2,\r\n },\r\n power: {\r\n accelerateForce: 50, // 推进\r\n brakeForce: 200, // 刹车\r\n maxSpeed: 10000, // 最大速度\r\n },\r\n steering: {\r\n maxSteerAngle: Math.PI / 4,\r\n steerSpeed: 0.5,\r\n steerReturnSpeed: 1,\r\n },\r\n followVehicleDirection: true,\r\n };\r\n\r\n camBehindDir = new THREE.Vector3(0, 0, 1);\r\n\r\n // ==================== 上车相关 ====================\r\n isMovingToBoardingPoint: boolean = false;\r\n boardingWaypoints: THREE.Vector3[] = [];\r\n currentWaypointIndex: number = 0;\r\n boardingTargetDir: THREE.Vector3 | null = null;\r\n boardingMoveSpeed: number = 300;\r\n boardingRotateSpeed: number = 10;\r\n flip180Quat = new THREE.Quaternion().setFromAxisAngle(\r\n new THREE.Vector3(0, 1, 0),\r\n Math.PI,\r\n );\r\n closeVehicleDoorTimer: any | null = null;\r\n boardingPointWorld: THREE.Vector3 | null = null;\r\n isBoardingAnimPlaying: boolean = false;\r\n closeDoorTriggered: boolean = false;\r\n isExitAnimPlaying: boolean = false;\r\n closeExitDoorTriggered: boolean = false;\r\n\r\n // ==================== 状态开关 ====================\r\n playerIsOnGround: boolean = false;\r\n isupdate: boolean = true;\r\n isFlying: boolean = false;\r\n\r\n // ==================== 输入状态 ====================\r\n fwdPressed: boolean = false;\r\n bkdPressed: boolean = false;\r\n lftPressed: boolean = false;\r\n rgtPressed: boolean = false;\r\n spacePressed: boolean = false;\r\n ctPressed: boolean = false;\r\n shiftPressed: boolean = false;\r\n\r\n // ==================== 移动端输入 ====================\r\n prevJoyState = { dirX: 0, dirY: 0, shift: false };\r\n nippleModule: any = null;\r\n joystickManager: any = null;\r\n joystickZoneEl: HTMLDivElement | null = null;\r\n lookAreaEl: HTMLDivElement | null = null;\r\n jumpBtnEl: HTMLButtonElement | null = null;\r\n flyBtnEl: HTMLButtonElement | null = null;\r\n viewBtnEl: HTMLButtonElement | null = null;\r\n vehicleBtnEl: HTMLButtonElement | null = null;\r\n lookPointerId: number | null = null;\r\n isLookDown = false;\r\n lastTouchX = 0;\r\n lastTouchY = 0;\r\n nearCheckLocal = new THREE.Vector3();\r\n nearCheckWorld = new THREE.Vector3();\r\n isNearVehicle = false;\r\n\r\n // ==================== 第三人称相机参数 ====================\r\n _camCollisionLerp: number = 0.18;\r\n _camEpsilon: number = 0.35;\r\n minCamDistance: number = 1.0;\r\n maxCamDistance: number = 4.4;\r\n orginMaxCamDistance: number = 4.4;\r\n\r\n // ==================== 物理/运动 ====================\r\n playerVelocity = new THREE.Vector3();\r\n readonly upVector = new THREE.Vector3(0, 1, 0);\r\n\r\n // ==================== 临时复用向量/矩阵 ====================\r\n readonly tempVector = new THREE.Vector3();\r\n readonly tempVector2 = new THREE.Vector3();\r\n readonly tempBox = new THREE.Box3();\r\n readonly tempMat = new THREE.Matrix4();\r\n readonly tempSegment = new THREE.Line3();\r\n\r\n // ==================== 动画相关 ====================\r\n personMixer?: THREE.AnimationMixer;\r\n personActions?: Map<string, THREE.AnimationAction>;\r\n idleAction!: THREE.AnimationAction;\r\n walkAction!: THREE.AnimationAction;\r\n leftWalkAction!: THREE.AnimationAction;\r\n rightWalkAction!: THREE.AnimationAction;\r\n backwardAction!: THREE.AnimationAction;\r\n jumpAction!: THREE.AnimationAction;\r\n runAction!: THREE.AnimationAction;\r\n flyidleAction!: THREE.AnimationAction;\r\n flyAction!: THREE.AnimationAction;\r\n actionState!: THREE.AnimationAction;\r\n recheckAnimTimer: any | null = null;\r\n\r\n // ==================== 相机朝向/移动复用向量 ====================\r\n readonly camDir = new THREE.Vector3();\r\n readonly moveDir = new THREE.Vector3();\r\n readonly targetQuat = new THREE.Quaternion();\r\n readonly targetMat = new THREE.Matrix4();\r\n readonly rotationSpeed = 10;\r\n readonly DIR_FWD = new THREE.Vector3(0, 0, -1);\r\n readonly DIR_BKD = new THREE.Vector3(0, 0, 1);\r\n readonly DIR_LFT = new THREE.Vector3(-1, 0, 0);\r\n readonly DIR_RGT = new THREE.Vector3(1, 0, 0);\r\n readonly DIR_UP = new THREE.Vector3(0, 1, 0);\r\n\r\n // ==================== 射线检测 ====================\r\n readonly _personToCam = new THREE.Vector3();\r\n readonly _originTmp = new THREE.Vector3();\r\n readonly _raycaster = new THREE.Raycaster(\r\n new THREE.Vector3(),\r\n new THREE.Vector3(0, -1, 0),\r\n );\r\n readonly _raycasterPersonToCam = new THREE.Raycaster(\r\n new THREE.Vector3(),\r\n new THREE.Vector3(),\r\n );\r\n\r\n centerRay = new THREE.Raycaster();\r\n centerMouse = new THREE.Vector2();\r\n\r\n constructor() {\r\n (this._raycaster as any).firstHitOnly = true;\r\n (this._raycasterPersonToCam as any).firstHitOnly = true;\r\n }\r\n\r\n // ==================== 初始化相关方法 ====================\r\n\r\n async init(opts: PlayerControllerOptions, callback?: () => void) {\r\n this.scene = opts.scene;\r\n this.camera = opts.camera;\r\n this.camera.rotation.order = \"YXZ\";\r\n this.controls = opts.controls;\r\n this.playerModel = opts.playerModel;\r\n this.initPos = opts.initPos ?? new THREE.Vector3(0, 0, 0);\r\n this.mouseSensity = opts.mouseSensity ?? 5;\r\n\r\n const s = this.playerModel.scale;\r\n this.gravity = (opts.playerModel.gravity ?? -2400) * s;\r\n this.jumpHeight = (opts.playerModel.jumpHeight ?? 600) * s;\r\n this.playerSpeed = (opts.playerModel.speed ?? 300) * s;\r\n this.playerFlySpeed = (opts.playerModel.playerFlySpeed ?? 2100) * s;\r\n this.curPlayerSpeed = this.playerSpeed;\r\n this.playerModel.rotateY = opts.playerModel.rotateY ?? 0;\r\n this.playerFlyEnabled = opts.playerModel.flyEnabled ?? true;\r\n\r\n this._camCollisionLerp = 0.18;\r\n this._camEpsilon = 35 * s;\r\n this.minCamDistance = (opts.minCamDistance ?? 100) * s;\r\n this.maxCamDistance = (opts.maxCamDistance ?? 440) * s;\r\n this.orginMaxCamDistance = this.maxCamDistance;\r\n this.thirdMouseMode = opts.thirdMouseMode ?? 1;\r\n this.enableZoom = opts.enableZoom ?? false;\r\n\r\n const isMobileDevice = () =>\r\n (navigator.maxTouchPoints && navigator.maxTouchPoints > 0) ||\r\n \"ontouchstart\" in window ||\r\n /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent);\r\n this.isShowMobileControls =\r\n (opts.isShowMobileControls ?? true) && isMobileDevice();\r\n if (this.isShowMobileControls) {\r\n await this.initMobileControls();\r\n }\r\n\r\n await this.createBVH(opts.colliderMeshUrl);\r\n await this.loadPersonGLB();\r\n\r\n this.onAllEvent();\r\n this.setCameraPos();\r\n this.setControls();\r\n if (callback) callback();\r\n\r\n this.enableOverShoulderView = opts.enableOverShoulderView ?? false;\r\n this.setOverShoulderView(this.enableOverShoulderView)\r\n }\r\n\r\n setOverShoulderView(enable: boolean) {\r\n if (!enable || this.controllerMode == 1) {\r\n this.camera.clearViewOffset();\r\n return;\r\n }\r\n const w = window.innerWidth;\r\n const h = window.innerHeight;\r\n this.camera.setViewOffset(\r\n w, h,\r\n -w * -0.15, 0,\r\n w, h\r\n );\r\n }\r\n\r\n async initLoader() {\r\n const dracoLoader = new DRACOLoader();\r\n dracoLoader.setDecoderPath(\"https://unpkg.com/three@0.180.0/examples/jsm/libs/draco/gltf/\");\r\n dracoLoader.setDecoderConfig({ type: \"js\" });\r\n this.loader.setDRACOLoader(dracoLoader);\r\n }\r\n\r\n async initRapier() {\r\n if (this.RAPIER) return;\r\n this.RAPIER = await import(\"@dimforge/rapier3d-compat\");\r\n await this.RAPIER.init();\r\n\r\n const gravity = new this.RAPIER.Vector3(0, -9.81, 0);\r\n this.world = new this.RAPIER.World(gravity) as World;\r\n (this.world as any).maxCcdSubsteps = 2;\r\n\r\n const addGeometryAsTrimesh = (\r\n RAPIER: any,\r\n world: any,\r\n geom: THREE.BufferGeometry,\r\n ) => {\r\n let geometry = geom.index\r\n ? geom.clone().toNonIndexed()\r\n : geom.clone();\r\n const posAttr = geometry.attributes.position;\r\n const vertexCount = posAttr.count;\r\n if (vertexCount % 3 !== 0) {\r\n console.warn(\"顶点数不是3的倍数,三角形可能不完整\");\r\n }\r\n const vertices = new Float32Array(vertexCount * 3);\r\n const tmp = new THREE.Vector3();\r\n for (let i = 0; i < vertexCount; i++) {\r\n tmp.fromBufferAttribute(posAttr, i);\r\n vertices[i * 3 + 0] = tmp.x;\r\n vertices[i * 3 + 1] = tmp.y;\r\n vertices[i * 3 + 2] = tmp.z;\r\n }\r\n const indices =\r\n vertexCount > 65535\r\n ? new Uint32Array(vertexCount)\r\n : new Uint16Array(vertexCount);\r\n for (let i = 0; i < vertexCount; i++) indices[i] = i;\r\n\r\n const bodyDesc = RAPIER.RigidBodyDesc.fixed();\r\n const body = world.createRigidBody(bodyDesc);\r\n // const flags = RAPIER.TriMeshFlags.FIX_INTERNAL_EDGES;\r\n const colliderDesc = RAPIER.ColliderDesc.trimesh(vertices, indices)\r\n .setRestitution(0)\r\n .setFriction(0.8);\r\n world.createCollider(colliderDesc, body);\r\n };\r\n\r\n for (const g of this.collected) {\r\n addGeometryAsTrimesh(this.RAPIER, this.world, g);\r\n }\r\n\r\n const groundDesc = this.RAPIER.RigidBodyDesc.fixed();\r\n const groundBody = this.world.createRigidBody(groundDesc);\r\n groundBody.userData = { outOfBounds: true };\r\n }\r\n\r\n // ==================== 玩家模型相关方法 ====================\r\n\r\n async loadPersonGLB() {\r\n try {\r\n const gltf: GLTF = await this.loader.loadAsync(\r\n this.playerModel.url,\r\n );\r\n this.person = gltf.scene;\r\n const { size } = this.getBbox(this.person);\r\n const ratio = this.playerHeight / size.y;\r\n const power = Math.round(Math.log10(ratio));\r\n const modelScale = Math.pow(10, power);\r\n this.playerRadius = Number(Math.min(size.x, size.z).toFixed(0)) * modelScale;\r\n this.playerHeight = Number(size.y.toFixed(0)) * modelScale;\r\n\r\n const scale = this.playerModel.scale;\r\n const material = new THREE.MeshStandardMaterial({\r\n color: new THREE.Color(1, 0, 0),\r\n shadowSide: THREE.DoubleSide,\r\n depthTest: false,\r\n transparent: true,\r\n opacity: this.displayPlayer ? 0.5 : 0,\r\n wireframe: true,\r\n depthWrite: false,\r\n });\r\n\r\n const r = this.playerRadius * scale;\r\n const h = this.playerHeight * scale;\r\n this.player = new THREE.Mesh(\r\n new RoundedBoxGeometry(r * 2, h, r * 2, 1, 75),\r\n material,\r\n );\r\n this.player.geometry.translate(0, -h * 0.25, 0);\r\n this.player.capsuleInfo = {\r\n radius: r,\r\n segment: new THREE.Line3(\r\n new THREE.Vector3(),\r\n new THREE.Vector3(0, -h * 0.5, 0),\r\n ),\r\n };\r\n this.player.name = \"capsule\";\r\n this.scene.add(this.player);\r\n this.reset();\r\n this.player.rotateY(this.playerModel.rotateY ?? 0);\r\n\r\n this.person.scale.multiplyScalar(modelScale * scale);\r\n this.person.position.set(0, -h * 0.75, 0);\r\n this.person.traverse((child: any) => {\r\n if (child.name == this.playerModel?.headObjName) {\r\n this.personHead = child;\r\n }\r\n });\r\n this.player.add(this.person);\r\n this.reset();\r\n\r\n this.personMixer = new THREE.AnimationMixer(this.person);\r\n const animations = gltf.animations ?? [];\r\n console.log('animations', animations)\r\n this.personActions = new Map<string, THREE.AnimationAction>();\r\n\r\n const animationMappings: [string, string][] = [\r\n [this.playerModel.idleAnim, \"idle\"],\r\n [this.playerModel.walkAnim, \"walking\"],\r\n [this.playerModel.leftWalkAnim || this.playerModel.walkAnim, \"left_walking\",],\r\n [this.playerModel.rightWalkAnim || this.playerModel.walkAnim, \"right_walking\",],\r\n [this.playerModel.backwardAnim || this.playerModel.walkAnim, \"walking_backward\",],\r\n [this.playerModel.jumpAnim, \"jumping\"],\r\n [this.playerModel.runAnim, \"running\"],\r\n [this.playerModel.flyIdleAnim || this.playerModel.idleAnim, \"flyidle\"],\r\n [this.playerModel.flyAnim || this.playerModel.idleAnim, \"flying\"],\r\n [this.playerModel.enterCarAnim || this.playerModel.idleAnim, \"enterCar\"],\r\n [this.playerModel.exitCarAnim || this.playerModel.idleAnim, \"exitCar\"],\r\n ];\r\n\r\n const findClip = (name: string) => animations.find((a: any) => a.name === name);\r\n for (const [clipName, actionName] of animationMappings) {\r\n const clip = findClip(clipName);\r\n if (!clip) continue;\r\n const action = this.personMixer.clipAction(clip);\r\n if (actionName === \"jumping\") {\r\n action.setLoop(THREE.LoopOnce, 1);\r\n action.clampWhenFinished = true;\r\n action.setEffectiveTimeScale(1.2);\r\n } else {\r\n action.setLoop(THREE.LoopRepeat, Infinity);\r\n action.clampWhenFinished = false;\r\n action.setEffectiveTimeScale(1);\r\n }\r\n action.enabled = true;\r\n action.setEffectiveWeight(0);\r\n this.personActions.set(actionName, action);\r\n }\r\n\r\n this.idleAction = this.personActions.get(\"idle\")!;\r\n this.walkAction = this.personActions.get(\"walking\")!;\r\n this.leftWalkAction = this.personActions.get(\"left_walking\")!;\r\n this.rightWalkAction = this.personActions.get(\"right_walking\")!;\r\n this.backwardAction = this.personActions.get(\"walking_backward\")!;\r\n this.jumpAction = this.personActions.get(\"jumping\")!;\r\n this.runAction = this.personActions.get(\"running\")!;\r\n this.flyidleAction = this.personActions.get(\"flyidle\")!;\r\n this.flyAction = this.personActions.get(\"flying\")!;\r\n\r\n this.idleAction.setEffectiveWeight(1);\r\n this.idleAction.play();\r\n this.actionState = this.idleAction;\r\n\r\n this.personMixer.addEventListener(\"finished\", (ev: any) => {\r\n const finishedAction: THREE.AnimationAction = ev.action;\r\n if (finishedAction === this.jumpAction) {\r\n if (this.fwdPressed) {\r\n this.playPersonAnimationByName(\r\n this.shiftPressed ? \"running\" : \"walking\",\r\n );\r\n return;\r\n }\r\n if (this.bkdPressed) {\r\n this.playPersonAnimationByName(\"walking_backward\");\r\n return;\r\n }\r\n if (this.rgtPressed || this.lftPressed) {\r\n this.playPersonAnimationByName(\"walking\");\r\n return;\r\n }\r\n this.playPersonAnimationByName(\"idle\");\r\n }\r\n if (finishedAction === this.personActions?.get(\"enterCar\")) {\r\n this.onEnterCarAnimFinished();\r\n }\r\n if (finishedAction === this.personActions?.get(\"exitCar\")) {\r\n // this._onExitCarAnimFinished();\r\n }\r\n });\r\n } catch (error) {\r\n console.error(\"加载玩家模型失败:\", error);\r\n }\r\n }\r\n\r\n async switchPlayerModel(newPlayerModel: PlayerControllerOptions[\"playerModel\"]) {\r\n const savedPos = this.player.position.clone();\r\n const savedQuat = this.player.quaternion.clone();\r\n\r\n const wasFirstPerson = this.isFirstPerson;\r\n if (wasFirstPerson) {\r\n this.scene.attach(this.camera);\r\n }\r\n\r\n if (this.player) {\r\n this.scene.remove(this.player);\r\n }\r\n\r\n if (this.person) {\r\n this.player.remove(this.person);\r\n this.person = null;\r\n this.personHead = null;\r\n }\r\n\r\n if (this.personMixer) {\r\n this.personMixer.stopAllAction();\r\n this.personMixer.uncacheRoot(this.personMixer.getRoot());\r\n this.personMixer = undefined;\r\n this.personActions = undefined;\r\n }\r\n\r\n const ratio = newPlayerModel.scale / this.playerModel.scale;\r\n this.playerModel = { ...this.playerModel, ...newPlayerModel };\r\n\r\n this.gravity *= ratio;\r\n this.jumpHeight *= ratio;\r\n this.playerSpeed *= ratio;\r\n this.playerFlySpeed *= ratio;\r\n this.curPlayerSpeed *= ratio;\r\n this._camEpsilon *= ratio;\r\n this.minCamDistance *= ratio;\r\n this.maxCamDistance *= ratio;\r\n this.orginMaxCamDistance *= ratio;\r\n\r\n await this.loadPersonGLB();\r\n\r\n this.player.position.copy(savedPos);\r\n this.player.quaternion.copy(savedQuat);\r\n\r\n if (wasFirstPerson) {\r\n this.setFirstPersonCamera();\r\n }\r\n\r\n this.setDebug(this.displayCollider);\r\n }\r\n\r\n playPersonAnimationByName(name: string, fade = 0.18) {\r\n if (!this.personActions || this.ctPressed) return;\r\n const next = this.personActions.get(name);\r\n if (!next || this.actionState === next) return;\r\n\r\n const duration = next.getClip().duration;\r\n const prev = this.actionState;\r\n\r\n next.reset();\r\n next.setEffectiveWeight(1);\r\n\r\n if (name == \"enterCar\" || name == \"exitCar\") {\r\n const enterTime = this.activeVehicle?.enterVehicleTime ?? 1.5;\r\n next.setEffectiveTimeScale(duration / enterTime);\r\n next.setLoop(THREE.LoopOnce, 1);\r\n next.clampWhenFinished = true;\r\n }\r\n\r\n next.play();\r\n\r\n if (prev && prev !== next) {\r\n prev.fadeOut(fade);\r\n next.fadeIn(fade);\r\n } else {\r\n next.fadeIn(fade);\r\n }\r\n\r\n this.actionState = next;\r\n }\r\n\r\n // ==================== 车辆模型相关 ====================\r\n\r\n /**\r\n * 加载车辆模型\r\n */\r\n async loadVehicleModel(opts: VehicleOptions) {\r\n try {\r\n if (!this.playerModel.enterCarAnim) {\r\n return console.warn(\"未配置上车动画,不执行车辆相关逻辑\");\r\n }\r\n\r\n // 物理引擎只初始化一次\r\n await this.initRapier();\r\n if (!this.world) return;\r\n\r\n const scale = opts.scale ?? 1;\r\n const chassisRatio = opts.chassisRatio ?? 0.2;\r\n const suspensionRestLengthRatio = opts.suspensionRestLengthRatio ?? 0.2;\r\n const speedMultiplier = opts.speedMultiplier ?? 1;\r\n const followVehicleDirection = opts.followVehicleDirection ?? true;\r\n\r\n // 参数调整\r\n this.vehicleParams.power.accelerateForce = 50 * scale;\r\n this.vehicleParams.power.brakeForce = 200 * scale;\r\n this.vehicleParams.power.maxSpeed = 10000 * scale;\r\n this.vehicleParams.followVehicleDirection = followVehicleDirection;\r\n\r\n // 加载模型\r\n const vehicleModel = await this.loader.loadAsync(opts.url);\r\n\r\n const { size: originalSize } = this.getBbox(vehicleModel.scene);\r\n const ratio = this.vehicleLength / Math.max(originalSize.x, originalSize.y, originalSize.z);\r\n const power = Math.round(Math.log10(ratio));\r\n const modelScale = Math.pow(10, power);\r\n\r\n // 动画混合器\r\n const vehicleMixer = new THREE.AnimationMixer(vehicleModel.scene);\r\n const animations = vehicleModel.animations ?? [];\r\n const vehicleActions = new Map<string, THREE.AnimationAction>();\r\n\r\n const findClip = (name: string) =>\r\n animations.find((a: any) => a.name === name);\r\n const openDoorClip = findClip(opts.animations?.openDoorAnim || \"\");\r\n if (openDoorClip) {\r\n const action = vehicleMixer.clipAction(openDoorClip);\r\n action.setLoop(THREE.LoopOnce, 1);\r\n action.clampWhenFinished = true;\r\n action.setEffectiveTimeScale(openDoorClip.duration);\r\n action.enabled = true;\r\n action.setEffectiveWeight(0);\r\n vehicleActions.set(\"openDoor\", action);\r\n }\r\n\r\n // 按名称顺序查找轮子\r\n const wheelObjects: THREE.Object3D[] = [];\r\n for (const wheelName of opts.wheelsNames) {\r\n let found = false;\r\n vehicleModel.scene.traverse((child) => {\r\n if (child.name === wheelName && !found) {\r\n wheelObjects.push(child);\r\n found = true;\r\n }\r\n });\r\n if (!found) console.warn(`未找到轮子: ${wheelName}`);\r\n }\r\n\r\n // 临时挂载以获取世界坐标\r\n const tempGroup = new THREE.Group();\r\n this.scene.add(tempGroup);\r\n vehicleModel.scene.scale.multiplyScalar(modelScale * scale);\r\n vehicleModel.scene.rotateY(this.vehicleParams.model.rotation);\r\n const { size, bbox, center } = this.getBbox(vehicleModel.scene);\r\n vehicleModel.scene.position.set(-center.x, -center.y, -center.z);\r\n tempGroup.add(vehicleModel.scene);\r\n tempGroup.updateMatrixWorld(true);\r\n\r\n const wheelsInfo: any[] = [];\r\n let wheelRadius = 0;\r\n let wheelWidth = 0;\r\n let suspensionRestLength = 0;\r\n let chassisHeight = 0;\r\n let wheelSizeInit = false;\r\n\r\n for (let i = 0; i < wheelObjects.length; i++) {\r\n const wheel = wheelObjects[i];\r\n const worldPos = new THREE.Vector3();\r\n const worldQuat = new THREE.Quaternion();\r\n const worldScale = new THREE.Vector3();\r\n wheel.getWorldPosition(worldPos);\r\n wheel.getWorldQuaternion(worldQuat);\r\n wheel.getWorldScale(worldScale);\r\n\r\n if (!wheelSizeInit) {\r\n const { size: ws } = this.getBbox(wheel);\r\n wheelRadius = Number((Math.max(ws.x, ws.y, ws.z) / 2).toFixed(2));\r\n wheelWidth = Number(Math.min(ws.x, ws.y, ws.z).toFixed(2));\r\n suspensionRestLength = Number((wheelRadius * 2 * suspensionRestLengthRatio).toFixed(2));\r\n chassisHeight = Number((wheelRadius * 2 * chassisRatio).toFixed(2));\r\n wheelSizeInit = true;\r\n }\r\n\r\n wheelsInfo.push({\r\n axleCs: new THREE.Vector3(0, 0, -1),\r\n position: worldPos,\r\n quaternion: worldQuat,\r\n scale: worldScale,\r\n radius: wheelRadius,\r\n width: wheelWidth,\r\n suspensionRestLength,\r\n object: wheel,\r\n });\r\n }\r\n\r\n tempGroup.remove(vehicleModel.scene);\r\n this.scene.remove(tempGroup);\r\n\r\n // 创建 vehicleGroup\r\n const vehicleGroup = new THREE.Group();\r\n this.scene.add(vehicleGroup);\r\n vehicleGroup.add(vehicleModel.scene);\r\n vehicleGroup.updateMatrixWorld(true);\r\n\r\n // 创建轮子包装组\r\n const wheelWrappers: THREE.Group[] = [];\r\n for (let i = 0; i < wheelsInfo.length; i++) {\r\n const wheel = wheelsInfo[i];\r\n const localPos = vehicleGroup.worldToLocal(wheel.position.clone());\r\n const wheelWrapper = new THREE.Group();\r\n wheelWrapper.position.copy(localPos);\r\n\r\n const wheelObj = wheelsInfo[i].object;\r\n if (wheelObj.parent) wheelObj.parent.remove(wheelObj);\r\n wheelObj.position.set(0, 0, 0);\r\n wheelObj.quaternion.copy(wheel.quaternion);\r\n wheelObj.scale.copy(wheel.scale);\r\n wheelObj.updateMatrixWorld();\r\n\r\n wheelWrapper.add(wheelObj);\r\n vehicleGroup.add(wheelWrapper);\r\n wheelWrappers.push(wheelWrapper);\r\n }\r\n\r\n // 车身刚体与碰撞体\r\n const halfExtents = size.clone().multiplyScalar(0.5);\r\n halfExtents.y -= chassisHeight / 2;\r\n vehicleModel.scene.position.y -= chassisHeight / 2;\r\n halfExtents.x *= 0.95;\r\n halfExtents.z *= 0.95;\r\n\r\n const chassisDesc = this.RAPIER.RigidBodyDesc.dynamic()\r\n .setTranslation(\r\n opts.position.x,\r\n opts.position.y,\r\n opts.position.z,\r\n )\r\n .setLinearDamping(this.vehicleParams.chassis.linearDamping)\r\n .setAngularDamping(this.vehicleParams.chassis.angularDamping)\r\n .setCanSleep(true)\r\n .setAdditionalMass(10);\r\n const chassisBody = this.world.createRigidBody(chassisDesc);\r\n const chassisCollider = this.RAPIER.ColliderDesc.cuboid(\r\n halfExtents.x,\r\n halfExtents.y,\r\n halfExtents.z,\r\n );\r\n this.world.createCollider(chassisCollider, chassisBody);\r\n\r\n if (this.vehicleParams.debug.showPhysicsBox) {\r\n const debugBox = new THREE.Mesh(\r\n new THREE.BoxGeometry(\r\n halfExtents.x * 2,\r\n halfExtents.y * 2,\r\n halfExtents.z * 2,\r\n ),\r\n new THREE.MeshBasicMaterial({\r\n color: 0xff0000,\r\n wireframe: true,\r\n transparent: true,\r\n opacity: 0.3,\r\n }),\r\n );\r\n vehicleGroup.add(debugBox);\r\n }\r\n\r\n vehicleGroup.position.copy(opts.position);\r\n vehicleGroup.updateMatrixWorld(true);\r\n\r\n // 创建车辆控制器\r\n const { vehicle, updateWheelVisuals } = createVehicleController(\r\n this.world,\r\n chassisBody,\r\n wheelWrappers,\r\n wheelsInfo,\r\n );\r\n\r\n // 组装 VehicleInstance\r\n const vehicleInstance: VehicleInstance = {\r\n vehicleGroup,\r\n chassisBody,\r\n vehicleController: vehicle,\r\n updateWheelVisuals,\r\n vehicleMixer,\r\n vehicleActions,\r\n vehiclIsOpenDoor: false,\r\n vehicleBBox: bbox.clone(),\r\n pathPlanner: new PathPlanner(\r\n this._createObstacleCheckerFor(vehicleGroup, bbox, scale),\r\n {\r\n debugEnabled: false,\r\n scene: this.scene,\r\n scale: this.playerModel.scale,\r\n },\r\n ),\r\n scale,\r\n boardingPoint: opts.boardingPoint,\r\n seatOffset: opts.seatOffset ?? new THREE.Vector3(0, 0, 0),\r\n enterVehicleTime: 1.5,\r\n chassisRatio,\r\n suspensionRestLengthRatio,\r\n size: {\r\n l: Math.max(size.x, size.z),\r\n w: Math.min(size.x, size.z),\r\n h: size.y,\r\n }, \r\n speedMultiplier,\r\n };\r\n\r\n this.vehicles.push(vehicleInstance);\r\n // console.log(\r\n // `车辆加载完成,当前共 ${this.vehicles.length} 辆车`,\r\n // vehicleInstance,\r\n // );\r\n // 初始化过渡\r\n this.setControllerTransition();\r\n } catch (error) {\r\n console.error(\"加载车辆模型失败:\", error);\r\n }\r\n }\r\n\r\n getBbox(object: THREE.Object3D) {\r\n const bbox = new THREE.Box3().setFromObject(object);\r\n const center = new THREE.Vector3();\r\n const size = new THREE.Vector3();\r\n bbox.getCenter(center);\r\n bbox.getSize(size);\r\n return { bbox, center, size };\r\n }\r\n\r\n /**\r\n * 为指定车辆创建障碍物检测器\r\n */\r\n private _createObstacleCheckerFor(\r\n vehicleGroup: THREE.Group,\r\n bbox: THREE.Box3,\r\n scale: number,\r\n ): ObstacleChecker {\r\n return {\r\n isBlocked: (start: THREE.Vector3, end: THREE.Vector3): boolean => {\r\n const vehiclePos = vehicleGroup.position;\r\n const vehicleQuat = vehicleGroup.quaternion;\r\n\r\n const center = new THREE.Vector3();\r\n const size = new THREE.Vector3();\r\n bbox.getCenter(center);\r\n bbox.getSize(size);\r\n\r\n center.applyQuaternion(vehicleQuat).add(vehiclePos);\r\n\r\n const halfSize = size.clone().multiplyScalar(0.5 * scale);\r\n const corners: THREE.Vector3[] = [];\r\n for (let x = -1; x <= 1; x += 2) {\r\n for (let y = -1; y <= 1; y += 2) {\r\n for (let z = -1; z <= 1; z += 2) {\r\n const localCorner = new THREE.Vector3(\r\n halfSize.x * x,\r\n halfSize.y * y,\r\n halfSize.z * z,\r\n );\r\n const worldCorner = localCorner\r\n .applyQuaternion(vehicleQuat)\r\n .add(center);\r\n corners.push(worldCorner);\r\n }\r\n }\r\n }\r\n\r\n const expandedBBox = new THREE.Box3();\r\n corners.forEach((corner) => expandedBBox.expandByPoint(corner));\r\n expandedBBox.expandByScalar(100 * this.playerModel.scale);\r\n\r\n const direction = new THREE.Vector3().subVectors(end, start);\r\n const length = direction.length();\r\n direction.normalize();\r\n\r\n const ray = new THREE.Ray(start, direction);\r\n const intersection = new THREE.Vector3();\r\n const intersects = ray.intersectBox(expandedBBox, intersection);\r\n return (\r\n intersects !== null &&\r\n start.distanceTo(intersection) < length\r\n );\r\n },\r\n\r\n getNavigationNodes: (\r\n start: THREE.Vector3,\r\n _goal: THREE.Vector3,\r\n ): THREE.Vector3[] => {\r\n const nodes: THREE.Vector3[] = [];\r\n const vehiclePos = vehicleGroup.position;\r\n const vehicleQuat = vehicleGroup.quaternion;\r\n\r\n const vehicleForward = new THREE.Vector3(\r\n 0,\r\n 0,\r\n 1,\r\n ).applyQuaternion(vehicleQuat);\r\n const vehicleRight = new THREE.Vector3(1, 0, 0).applyQuaternion(\r\n vehicleQuat,\r\n );\r\n\r\n const bboxSize = new THREE.Vector3();\r\n bbox.getSize(bboxSize);\r\n\r\n const halfLength = (bboxSize.z / 2) * scale;\r\n const halfWidth = (bboxSize.x / 2) * scale;\r\n\r\n const bypassMargin = 300 * this.playerModel.scale;\r\n const extendedMargin = 500 * this.playerModel.scale;\r\n const groundY = start.y;\r\n\r\n for (const margin of [bypassMargin, extendedMargin]) {\r\n nodes.push(\r\n vehiclePos\r\n .clone()\r\n .add(\r\n vehicleForward\r\n .clone()\r\n .multiplyScalar(halfLength + margin),\r\n )\r\n .add(\r\n vehicleRight\r\n .clone()\r\n .multiplyScalar(-halfWidth - margin),\r\n )\r\n .setY(groundY),\r\n );\r\n nodes.push(\r\n vehiclePos\r\n .clone()\r\n .add(\r\n vehicleForward\r\n .clone()\r\n .multiplyScalar(halfLength + margin),\r\n )\r\n .add(\r\n vehicleRight\r\n .clone()\r\n .multiplyScalar(halfWidth + margin),\r\n )\r\n .setY(groundY),\r\n );\r\n nodes.push(\r\n vehiclePos\r\n .clone()\r\n .add(\r\n vehicleForward\r\n .clone()\r\n .multiplyScalar(-halfLength - margin),\r\n )\r\n .add(\r\n vehicleRight\r\n .clone()\r\n .multiplyScalar(-halfWidth - margin),\r\n )\r\n .setY(groundY),\r\n );\r\n nodes.push(\r\n vehiclePos\r\n .clone()\r\n .add(\r\n vehicleForward\r\n .clone()\r\n .multiplyScalar(-halfLength - margin),\r\n )\r\n .add(\r\n vehicleRight\r\n .clone()\r\n .multiplyScalar(halfWidth + margin),\r\n )\r\n .setY(groundY),\r\n );\r\n }\r\n\r\n return nodes;\r\n },\r\n };\r\n }\r\n\r\n /**\r\n * 开关车门动画(操作当前 activeVehicle)\r\n */\r\n openVehicleDoor(isOpen = true) {\r\n const v = this.activeVehicle;\r\n if (!v?.vehicleActions) return;\r\n\r\n const next = v.vehicleActions.get(\"openDoor\");\r\n if (!next) return;\r\n\r\n const duration = next.getClip().duration;\r\n next.reset();\r\n next.setEffectiveWeight(1);\r\n\r\n if (isOpen) {\r\n next.setEffectiveTimeScale(duration * 2);\r\n next.time = 0;\r\n v.vehiclIsOpenDoor = true;\r\n } else {\r\n next.setEffectiveTimeScale(-duration * 2);\r\n next.time = duration;\r\n v.vehiclIsOpenDoor = false;\r\n }\r\n\r\n next.setLoop(THREE.LoopOnce, 1);\r\n next.clampWhenFinished = true;\r\n next.play();\r\n }\r\n\r\n /**\r\n * 上车:自动寻找最近的车辆\r\n */\r\n enterVehicle() {\r\n if (this.vehicles.length === 0 || this.isMovingToBoardingPoint) return;\r\n\r\n // 遍历所有车辆,找距离最近的上车点\r\n let nearestVehicle: VehicleInstance | null = null;\r\n let nearestDist = Infinity;\r\n let nearBoardingPointWorld: THREE.Vector3 | null = null;\r\n\r\n for (const v of this.vehicles) {\r\n // 计算上车点世界坐标\r\n const boardingPointLocal = v.boardingPoint\r\n .clone()\r\n .multiplyScalar(v.scale);\r\n const boardingPointWorld = new THREE.Vector3();\r\n v.vehicleGroup.localToWorld(\r\n boardingPointWorld.copy(boardingPointLocal),\r\n );\r\n\r\n const dist = this.player.position.distanceTo(boardingPointWorld);\r\n if (dist < 800 * this.playerModel.scale && dist < nearestDist) {\r\n nearestDist = dist;\r\n nearestVehicle = v;\r\n nearBoardingPointWorld = boardingPointWorld;\r\n }\r\n }\r\n\r\n if (!nearestVehicle || !nearBoardingPointWorld) return;\r\n\r\n // 锁定目标车辆\r\n this.activeVehicle = nearestVehicle;\r\n const v = nearestVehicle;\r\n const vel = v.chassisBody.linvel();\r\n const horizSpeed = Math.sqrt(vel.x * vel.x + vel.z * vel.z);\r\n if (horizSpeed > 0.1) return;\r\n\r\n this.boardingPointWorld = nearBoardingPointWorld;\r\n // 计算车辆朝向\r\n const vehicleForward = new THREE.Vector3(0, 0, 1)\r\n .applyQuaternion(v.vehicleGroup.quaternion)\r\n .normalize();\r\n\r\n // 路径规划\r\n const path = v.pathPlanner.findPath(\r\n this.player.position.clone(),\r\n this.boardingPointWorld,\r\n );\r\n this.boardingWaypoints = path;\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = vehicleForward;\r\n this.isMovingToBoardingPoint = true;\r\n\r\n this.playPersonAnimationByName(\"walking\");\r\n }\r\n\r\n /**\r\n * 走向上车点\r\n */\r\n updateMoveToBoardingPoint(delta: number) {\r\n if (\r\n !this.isMovingToBoardingPoint ||\r\n !this.boardingTargetDir ||\r\n this.boardingWaypoints.length === 0\r\n ) {\r\n return;\r\n }\r\n\r\n if (this.currentWaypointIndex >= this.boardingWaypoints.length) {\r\n this.finalizeBoarding(delta);\r\n return;\r\n }\r\n\r\n const currentWaypoint =\r\n this.boardingWaypoints[this.currentWaypointIndex];\r\n const currentPos = this.player.position.clone();\r\n\r\n const horizontalDistance = new THREE.Vector2(\r\n currentWaypoint.x - currentPos.x,\r\n currentWaypoint.z - currentPos.z,\r\n ).length();\r\n\r\n const isLastWaypoint = this.currentWaypointIndex === this.boardingWaypoints.length - 1;\r\n const waypointThreshold = isLastWaypoint ? 0 : 10 * this.playerModel.scale;\r\n\r\n if (horizontalDistance > waypointThreshold) {\r\n const moveDir = new THREE.Vector3(\r\n currentWaypoint.x - currentPos.x,\r\n 0,\r\n currentWaypoint.z - currentPos.z,\r\n ).normalize();\r\n\r\n const moveDistance = Math.min(\r\n this.boardingMoveSpeed * this.playerModel.scale * delta,\r\n horizontalDistance,\r\n );\r\n this.player.position.add(moveDir.multiplyScalar(moveDistance));\r\n\r\n const lookTarget = this.player.position.clone().add(moveDir);\r\n this.targetMat.lookAt(\r\n this.player.position,\r\n lookTarget,\r\n this.player.up,\r\n );\r\n this.targetQuat.setFromRotationMatrix(this.targetMat);\r\n this.targetQuat.multiply(this.flip180Quat);\r\n const rotateAlpha = Math.min(1, this.boardingRotateSpeed * delta);\r\n this.player.quaternion.slerp(this.targetQuat, rotateAlpha);\r\n } else {\r\n this.currentWaypointIndex++;\r\n }\r\n }\r\n\r\n /**\r\n * 完成上车\r\n */\r\n finalizeBoarding(delta: number) {\r\n const v = this.activeVehicle;\r\n if (!this.boardingTargetDir || !v || !this.isMovingToBoardingPoint) return;\r\n\r\n const currentDir = new THREE.Vector3(0, 0, -1)\r\n .applyQuaternion(this.player.quaternion)\r\n .normalize();\r\n const targetDir = this.boardingTargetDir.clone().normalize();\r\n const angleDiff = currentDir.angleTo(targetDir);\r\n\r\n if (angleDiff > 0.01) {\r\n const lookTarget = this.player.position.clone().add(targetDir);\r\n this.targetMat.lookAt(\r\n this.player.position,\r\n lookTarget,\r\n this.player.up,\r\n );\r\n this.targetQuat.setFromRotationMatrix(this.targetMat);\r\n const rotateAlpha = Math.min(1, this.boardingRotateSpeed * delta);\r\n this.player.quaternion.slerp(this.targetQuat, rotateAlpha);\r\n } else {\r\n this.boardingWaypoints = [];\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = null;\r\n\r\n v.pathPlanner?.clearVisualization();\r\n\r\n this.playPersonAnimationByName(\"enterCar\");\r\n this.isBoardingAnimPlaying = true;\r\n this.closeDoorTriggered = false;\r\n if (!v.vehiclIsOpenDoor) this.openVehicleDoor();\r\n this.player.rotation.copy(v.vehicleGroup.rotation);\r\n this.player.quaternion.multiply(this.flip180Quat);\r\n }\r\n }\r\n\r\n onEnterCarAnimFinished() {\r\n const v = this.activeVehicle;\r\n if (!v || !this.isMovingToBoardingPoint) return;\r\n this.player.updateMatrixWorld(true);\r\n const offsetY = this.boardingPointWorld.y - this.player.position.y;\r\n this.controllerMode = 1;\r\n this.syncControllerModeBtnEl();\r\n this.setOverShoulderView(false);\r\n v.vehicleGroup.attach(this.player);\r\n this.player.position.add(\r\n v.seatOffset\r\n .clone()\r\n .multiplyScalar(v.scale)\r\n .add(new THREE.Vector3(0, offsetY, 0)),\r\n );\r\n this.isMovingToBoardingPoint = false;\r\n }\r\n\r\n /**\r\n * 下车\r\n */\r\n exitVehicle() {\r\n const v = this.activeVehicle;\r\n if (!v) return;\r\n\r\n this.isMovingToBoardingPoint = false;\r\n this.boardingWaypoints = [];\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = null;\r\n\r\n const vel = v.chassisBody.linvel();\r\n const horizSpeed = Math.sqrt(vel.x * vel.x + vel.z * vel.z);\r\n const isStationary = horizSpeed < 0.1;\r\n if (isStationary) {\r\n this.playPersonAnimationByName(\"exitCar\");\r\n this.isExitAnimPlaying = true;\r\n this.closeExitDoorTriggered = false;\r\n } else {\r\n this.playPersonAnimationByName(\"idle\");\r\n }\r\n\r\n this.openVehicleDoor(true);\r\n this.controllerMode = 0;\r\n this.syncControllerModeBtnEl();\r\n this.setOverShoulderView(this.enableOverShoulderView);\r\n this.scene.attach(this.player);\r\n\r\n if (this.isFirstPerson) {\r\n this.setFirstPersonCamera();\r\n }\r\n\r\n this.setControllerTransition();\r\n }\r\n\r\n // ==================== 相机与视角控制 ====================\r\n\r\n changeView() {\r\n this.isFirstPerson = !this.isFirstPerson;\r\n\r\n if (this.isFirstPerson) {\r\n this.setFirstPersonCamera();\r\n this.setOverShoulderView(false)\r\n } else {\r\n this.controls.enabled = true;\r\n this.scene.attach(this.camera);\r\n const worldPos = this.player.position.clone();\r\n const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(\r\n this.player.quaternion,\r\n );\r\n const angle = Math.atan2(dir.z, dir.x);\r\n const offset = new THREE.Vector3(\r\n Math.cos(angle) * 400 * this.playerModel.scale,\r\n 200 * this.playerModel.scale,\r\n Math.sin(angle) * 400 * this.playerModel.scale,\r\n );\r\n this.camera.position.copy(worldPos).add(offset);\r\n this.controls.target.copy(worldPos);\r\n this.controls.enableZoom = this.enableZoom;\r\n this.setOverShoulderView(this.enableOverShoulderView);\r\n }\r\n\r\n this.setPointerLock();\r\n }\r\n\r\n setFirstPersonCamera() {\r\n this.controls.enabled = false;\r\n if (this.personHead) {\r\n this.personHead?.attach(this.camera);\r\n this.camera.position.set(0, 10, 20);\r\n } else {\r\n this.player.attach(this.camera);\r\n this.camera.position.set(\r\n 0,\r\n 40 * this.playerModel.scale,\r\n 30 * this.playerModel.scale,\r\n );\r\n }\r\n this.camera.rotation.set(0, Math.PI, 0);\r\n this.controls.enableZoom = false;\r\n }\r\n\r\n setPointerLock() {\r\n if (\r\n ((this.thirdMouseMode === 0 || this.thirdMouseMode === 1) &&\r\n !this.isFirstPerson) ||\r\n this.isFirstPerson\r\n ) {\r\n document.body.requestPointerLock();\r\n } else {\r\n document.exitPointerLock();\r\n }\r\n }\r\n\r\n setCameraPos() {\r\n requestAnimationFrame(() => {\r\n if (this.isFirstPerson) {\r\n this.person.add(this.camera);\r\n this.camera.position.set(\r\n 0,\r\n 40 * this.playerModel.scale,\r\n 30 * this.playerModel.scale,\r\n );\r\n } else {\r\n const worldPos = this.player.position.clone();\r\n const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(\r\n this.player.quaternion,\r\n ); \r\n const angle = Math.atan2(dir.z, dir.x);\r\n const offset = new THREE.Vector3(\r\n Math.cos(angle) * 400 * this.playerModel.scale,\r\n 200 * this.playerModel.scale,\r\n Math.sin(angle) * 400 * this.playerModel.scale,\r\n );\r\n this.camera.position.copy(worldPos).add(offset);\r\n this.controls.enableZoom = this.enableZoom;\r\n }\r\n this.camera.updateProjectionMatrix();\r\n });\r\n\r\n }\r\n\r\n setControls() {\r\n // this.controls.enabled = !(this.thirdMouseMode === 0 || this.thirdMouseMode === 1);\r\n this.controls.enableZoom = this.enableZoom;\r\n this.controls.rotateSpeed = this.mouseSensity * 0.05;\r\n this.controls.maxPolarAngle = Math.PI * (300 / 360);\r\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\r\n }\r\n\r\n resetControls() {\r\n if (!this.controls) return;\r\n this.controls.enabled = true;\r\n this.controls.enablePan = true;\r\n this.controls.maxPolarAngle = Math.PI / 2;\r\n this.controls.rotateSpeed = 1;\r\n this.controls.enableZoom = true;\r\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\r\n }\r\n\r\n setToward(dx: number, dy: number, speed: number) {\r\n if (this.controllerMode == 0) {\r\n if (this.isFirstPerson) {\r\n if (this.isMovingToBoardingPoint) return;\r\n const yaw = -dx * speed * this.mouseSensity;\r\n const pitch = -dy * speed * this.mouseSensity;\r\n this.player.rotateY(yaw);\r\n this.camera.rotation.x = THREE.MathUtils.clamp(\r\n this.camera.rotation.x + pitch,\r\n -1.1,\r\n 1.4,\r\n );\r\n } else {\r\n const sensitivity = this.mouseSensity;\r\n const deltaX = -dx * speed * sensitivity;\r\n const deltaY = -dy * speed * sensitivity;\r\n const target = this.player.position.clone();\r\n const distance = this.camera.position.distanceTo(target);\r\n const currentPosition = this.camera.position\r\n .clone()\r\n .sub(target);\r\n let theta = Math.atan2(currentPosition.x, currentPosition.z);\r\n let phi = Math.acos(currentPosition.y / distance);\r\n theta += deltaX;\r\n phi += deltaY;\r\n phi = Math.max(0.1, Math.min(Math.PI - 0.1, phi));\r\n const newX = distance * Math.sin(phi) * Math.sin(theta);\r\n const newY = distance * Math.cos(phi);\r\n const newZ = distance * Math.sin(phi) * Math.cos(theta);\r\n this.camera.position.set(\r\n target.x + newX,\r\n target.y + newY,\r\n target.z + newZ,\r\n );\r\n this.camera.lookAt(target);\r\n }\r\n } else {\r\n const v = this.activeVehicle;\r\n if (!v) return;\r\n if (this.isFirstPerson) {\r\n const yaw = -dx * speed * this.mouseSensity;\r\n const pitch = -dy * speed * this.mouseSensity;\r\n this.camera.rotation.y = THREE.MathUtils.clamp(\r\n this.camera.rotation.y + yaw,\r\n Math.PI * (3 / 4),\r\n Math.PI * (5 / 4),\r\n );\r\n this.camera.rotation.x = THREE.MathUtils.clamp(\r\n this.camera.rotation.x + pitch,\r\n 0,\r\n Math.PI * (1 / 3),\r\n );\r\n } else {\r\n const sensitivity = this.mouseSensity;\r\n const deltaX = -dx * speed * sensitivity;\r\n const deltaY = -dy * speed * sensitivity;\r\n const target = v.vehicleGroup.position.clone();\r\n const distance = this.camera.position.distanceTo(target);\r\n const currentPosition = this.camera.position\r\n .clone()\r\n .sub(target);\r\n let theta = Math.atan2(currentPosition.x, currentPosition.z);\r\n let phi = Math.acos(currentPosition.y / distance);\r\n theta += deltaX;\r\n phi += deltaY;\r\n phi = Math.max(0.1, Math.min(Math.PI - 0.1, phi));\r\n const newX = distance * Math.sin(phi) * Math.sin(theta);\r\n const newY = distance * Math.cos(phi);\r\n const newZ = distance * Math.sin(phi) * Math.cos(theta);\r\n this.camera.position.set(\r\n target.x + newX,\r\n target.y + newY,\r\n target.z + newZ,\r\n );\r\n this.camera.lookAt(target);\r\n }\r\n }\r\n }\r\n\r\n // ==================== 物理与碰撞检测 ====================\r\n\r\n ensureAttributesMinimal = (\r\n geom: THREE.BufferGeometry,\r\n ): THREE.BufferGeometry | null => {\r\n if (!geom.attributes.position) return null;\r\n if (!geom.attributes.normal) geom.computeVertexNormals();\r\n if (!geom.attributes.uv) {\r\n const count = geom.attributes.position.count;\r\n const dummyUV = new Float32Array(count * 2);\r\n geom.setAttribute(\"uv\", new THREE.BufferAttribute(dummyUV, 2));\r\n }\r\n return geom;\r\n };\r\n\r\n unifiedAttribute(collected: THREE.BufferGeometry[]) {\r\n type AttrMeta = {\r\n itemSize: number;\r\n arrayCtor: any;\r\n examples: number;\r\n normalized: boolean;\r\n };\r\n const attrMap = new Map<string, AttrMeta>();\r\n const attrConflict = new Set<string>();\r\n const requiredAttrs = new Set([\"position\", \"normal\", \"uv\"]);\r\n\r\n for (const g of collected) {\r\n const attrNames = Object.keys(g.attributes);\r\n for (const name of attrNames) {\r\n if (!requiredAttrs.has(name)) {\r\n g.deleteAttribute(name);\r\n }\r\n }\r\n }\r\n\r\n for (const g of collected) {\r\n for (const name of Object.keys(g.attributes)) {\r\n const attr = g.attributes[name] as THREE.BufferAttribute;\r\n const ctor = (attr.array as any).constructor;\r\n const itemSize = attr.itemSize;\r\n const normalized = attr.normalized;\r\n\r\n if (!attrMap.has(name)) {\r\n attrMap.set(name, {\r\n itemSize,\r\n arrayCtor: ctor,\r\n examples: 1,\r\n normalized,\r\n });\r\n } else {\r\n const m = attrMap.get(name)!;\r\n if (\r\n m.itemSize !== itemSize ||\r\n m.arrayCtor !== ctor ||\r\n m.normalized !== normalized\r\n ) {\r\n attrConflict.add(name);\r\n } else {\r\n m.examples++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (attrConflict.size) {\r\n for (const g of collected) {\r\n for (const name of Array.from(attrConflict)) {\r\n if (g.attributes[name]) g.deleteAttribute(name);\r\n }\r\n }\r\n for (const name of attrConflict) attrMap.delete(name);\r\n }\r\n\r\n const attrNames = Array.from(attrMap.keys());\r\n for (const g of collected) {\r\n const count = g.attributes.position.count;\r\n for (const name of attrNames) {\r\n if (!g.attributes[name]) {\r\n const meta = attrMap.get(name)!;\r\n const len = count * meta.itemSize;\r\n const array = new meta.arrayCtor(len);\r\n g.setAttribute(\r\n name,\r\n new THREE.BufferAttribute(\r\n array,\r\n meta.itemSize,\r\n meta.normalized,\r\n ),\r\n );\r\n }\r\n }\r\n }\r\n\r\n return collected;\r\n }\r\n\r\n async createBVH(meshUrl: string = \"\"): Promise<void> {\r\n await this.initLoader();\r\n\r\n if (meshUrl === \"\") {\r\n if (this.collider) {\r\n this.scene.remove(this.collider);\r\n this.collider = null;\r\n }\r\n this.scene.traverse((c) => {\r\n const mesh = c as THREE.Mesh;\r\n if (mesh?.isMesh && mesh.geometry && c.name !== \"capsule\") {\r\n try {\r\n let geom = (mesh.geometry as THREE.BufferGeometry).clone();\r\n geom.applyMatrix4(mesh.matrixWorld);\r\n if (geom.index) geom = geom.toNonIndexed();\r\n const safe = this.ensureAttributesMinimal(geom);\r\n if (safe) this.collected.push(safe);\r\n } catch (e) {\r\n console.warn(\"处理网格时出错:\", mesh, e);\r\n }\r\n }\r\n });\r\n if (!this.collected.length) return;\r\n this.collected = this.unifiedAttribute(this.collected);\r\n } else {\r\n const gltf: GLTF = await this.loader.loadAsync(meshUrl);\r\n const obj = gltf.scene.children[0] as any;\r\n if (obj && obj?.geometry) {\r\n const mesh = obj;\r\n let geom = mesh.geometry.clone();\r\n geom.applyMatrix4(mesh.matrixWorld);\r\n if (geom.index) geom = geom.toNonIndexed();\r\n const safe = this.ensureAttributesMinimal(geom);\r\n if (safe) this.collected.push(safe);\r\n } else {\r\n obj.traverse((c: any) => {\r\n const mesh = c;\r\n if (mesh?.isMesh && mesh.geometry && c.name !== \"capsule\") {\r\n try {\r\n let geom = (mesh.geometry as THREE.BufferGeometry).clone();\r\n geom.applyMatrix4(mesh.matrixWorld);\r\n if (geom.index) geom = geom.toNonIndexed();\r\n const safe = this.ensureAttributesMinimal(geom);\r\n if (safe) this.collected.push(safe);\r\n } catch (e) {\r\n console.warn(\"处理网格时出错:\", mesh, e);\r\n }\r\n }\r\n });\r\n if (!this.collected.length) return;\r\n this.collected = this.unifiedAttribute(this.collected);\r\n }\r\n }\r\n\r\n const merged = BufferGeometryUtils.mergeGeometries(\r\n this.collected,\r\n false,\r\n );\r\n if (!merged) {\r\n console.error(\"合并几何失败\");\r\n return;\r\n }\r\n\r\n (merged as any).boundsTree = new MeshBVH(merged, { maxDepth: 100 });\r\n this.collider = new THREE.Mesh(\r\n merged,\r\n new THREE.MeshBasicMaterial({\r\n opacity: 0.5,\r\n transparent: true,\r\n wireframe: true,\r\n depthTest: true,\r\n }),\r\n );\r\n\r\n if (this.displayCollider) this.scene.add(this.collider);\r\n if (this.displayVisualizer) {\r\n if (this.visualizer) this.scene.remove(this.visualizer);\r\n this.visualizer = new MeshBVHHelper(this.collider, 0);\r\n this.scene.add(this.visualizer);\r\n }\r\n\r\n this.boundingBoxMinY = (this.collider as any).geometry.boundingBox.min.y;\r\n }\r\n\r\n createDynamicBVH(objects: THREE.Object3D[] = []) {\r\n if (this.dynamicCollider) {\r\n this.scene.remove(this.dynamicCollider);\r\n this.dynamicCollider = null;\r\n }\r\n this.dynamicCollected = [];\r\n objects.forEach((object: THREE.Object3D) => {\r\n object.traverse((c) => {\r\n const mesh = c as THREE.Mesh;\r\n if (mesh?.isMesh && mesh.geometry && c.name !== \"capsule\") {\r\n try {\r\n let geom = (\r\n mesh.geometry as THREE.BufferGeometry\r\n ).clone();\r\n geom.applyMatrix4(mesh.matrixWorld);\r\n if (geom.index) geom = geom.toNonIndexed();\r\n const safe = this.ensureAttributesMinimal(geom);\r\n if (safe) this.dynamicCollected.push(safe);\r\n } catch (e) {\r\n console.warn(\"处理网格时出错:\", mesh, e);\r\n }\r\n }\r\n });\r\n });\r\n\r\n if (!this.dynamicCollected.length) return;\r\n this.dynamicCollected = this.unifiedAttribute(this.dynamicCollected);\r\n\r\n const merged = BufferGeometryUtils.mergeGeometries(\r\n this.dynamicCollected,\r\n false,\r\n );\r\n if (!merged) {\r\n console.error(\"合并几何失败\");\r\n return;\r\n }\r\n (merged as any).boundsTree = new MeshBVH(merged);\r\n this.dynamicCollider = new THREE.Mesh(\r\n merged,\r\n new THREE.MeshBasicMaterial({\r\n opacity: 0.5,\r\n transparent: true,\r\n wireframe: true,\r\n depthTest: true,\r\n }),\r\n );\r\n if (this.displayCollider) this.scene.add(this.dynamicCollider);\r\n }\r\n\r\n getAngleWithYAxis(normal: { x: number; y: number; z: number }): number {\r\n const yAxis = { x: 0, y: 1, z: 0 };\r\n const dotProduct =\r\n normal.x * yAxis.x + normal.y * yAxis.y + normal.z * yAxis.z;\r\n const normalMagnitude = Math.sqrt(\r\n normal.x * normal.x + normal.y * normal.y + normal.z * normal.z,\r\n );\r\n const cosTheta = dotProduct / normalMagnitude;\r\n return Math.acos(cosTheta);\r\n }\r\n\r\n // ==================== 设置控制器过渡 ====================\r\n\r\n setControllerTransition() {\r\n if (this.isChangeControllerTransitionTimer) {\r\n clearTimeout(this.isChangeControllerTransitionTimer);\r\n this.isChangeControllerTransitionTimer = null;\r\n }\r\n // 先加一次碰撞体\r\n let vGroups: THREE.Group[] = [];\r\n for (const v of this.vehicles) {\r\n vGroups.push(v.vehicleGroup);\r\n }\r\n this.createDynamicBVH(vGroups);\r\n this.isChangeControllerTransitionTimer = setTimeout(() => {\r\n this.isChangeControllerTransitionTimer = null;\r\n // 用 activeVehicle 创建动态碰撞体,并清除所有车辆速度\r\n for (const v of this.vehicles) {\r\n this.clearVehicleVelocity(v);\r\n }\r\n this.createDynamicBVH(vGroups);\r\n }, 3000);\r\n }\r\n\r\n // 清除车辆速度\r\n private clearVehicleVelocity(v: VehicleInstance) {\r\n if (!v || !this.world || !this.RAPIER) return;\r\n\r\n const { chassisBody, vehicleController } = v;\r\n const ZERO = new this.RAPIER.Vector3(0, 0, 0);\r\n\r\n // 第一次清刚体速度\r\n chassisBody.setLinvel(ZERO, true);\r\n chassisBody.setAngvel(ZERO, true);\r\n\r\n // 清轮子引擎力,施加极大刹车力\r\n const BIG_BRAKE = 1e6;\r\n for (let i = 0; i < 4; i++) {\r\n vehicleController.setWheelEngineForce(i, 0);\r\n vehicleController.setWheelBrake(i, BIG_BRAKE);\r\n }\r\n\r\n // 让控制器用上面的参数覆盖内部轮速缓存\r\n vehicleController.updateVehicle(1 / 60);\r\n this.world.timestep = 1 / 60;\r\n this.world.step();\r\n\r\n // 第二次清刚体速度\r\n chassisBody.setLinvel(ZERO, true);\r\n chassisBody.setAngvel(ZERO, true);\r\n\r\n // 刹车力归零,避免影响下次正常驾驶\r\n for (let i = 0; i < 4; i++) {\r\n vehicleController.setWheelBrake(i, 0);\r\n }\r\n }\r\n\r\n // ==================== 循环更新 ====================\r\n\r\n async update(delta: number = clock.getDelta()) {\r\n if (!this.isupdate || !this.player || !this.collider) return;\r\n\r\n delta = Math.min(delta, 1 / 40);\r\n\r\n if (this.controllerMode == 1) {\r\n this.updateVehicle(delta);\r\n } else {\r\n this.updatePlayer(delta);\r\n if (this.isChangeControllerTransitionTimer)\r\n this.updateVehicleInertia(delta);\r\n }\r\n }\r\n\r\n /**\r\n * 更新当前驾驶的车辆\r\n */\r\n updateVehicle(delta: number) {\r\n const v = this.activeVehicle;\r\n if (!v || !this.world) return;\r\n\r\n const { vehicleController, chassisBody, vehicleGroup } = v;\r\n\r\n // 坡度检测与额外推力补偿\r\n const rotation = chassisBody.rotation();\r\n const quat = new THREE.Quaternion(\r\n rotation.x,\r\n rotation.y,\r\n rotation.z,\r\n rotation.w,\r\n );\r\n const forward = new THREE.Vector3(1, 0, 0).applyQuaternion(quat);\r\n const slopeAngle = Math.asin(forward.y);\r\n let factor = 1;\r\n if (slopeAngle < -0.05 && this.fwdPressed) factor = -Math.sin(slopeAngle) * 10;\r\n\r\n const accelerateForce = this.vehicleParams.power.accelerateForce * v.speedMultiplier;\r\n const maxSpeed = this.vehicleParams.power.maxSpeed * v.speedMultiplier;\r\n const engineForce = (Number(this.fwdPressed) * accelerateForce - Number(this.bkdPressed) * accelerateForce) * factor;\r\n vehicleController.setWheelEngineForce(0, engineForce);\r\n vehicleController.setWheelEngineForce(1, engineForce);\r\n vehicleController.setWheelEngineForce(2, engineForce);\r\n vehicleController.setWheelEngineForce(3, engineForce);\r\n\r\n const wheelBrake = Number(this.spacePressed) * this.vehicleParams.power.brakeForce * delta;\r\n vehicleController.setWheelBrake(0, wheelBrake);\r\n vehicleController.setWheelBrake(1, wheelBrake);\r\n vehicleController.setWheelBrake(2, wheelBrake);\r\n vehicleController.setWheelBrake(3, wheelBrake);\r\n\r\n // 转向\r\n const currentSteering = vehicleController.wheelSteering(0) || 0;\r\n const steerDirection =\r\n Number(this.lftPressed) - Number(this.rgtPressed);\r\n let steerSpeed: number;\r\n if (steerDirection === 0) {\r\n steerSpeed = this.vehicleParams.steering.steerReturnSpeed || 0.15;\r\n } else {\r\n steerSpeed = this.vehicleParams.steering.steerSpeed || 0.08;\r\n }\r\n const steerLerpFactor = 1.0 - Math.pow(1.0 - steerSpeed, delta);\r\n const targetSteering =\r\n this.vehicleParams.steering.maxSteerAngle * steerDirection;\r\n const steering = THREE.MathUtils.lerp(\r\n currentSteering,\r\n targetSteering,\r\n steerLerpFactor,\r\n );\r\n vehicleController.setWheelSteering(0, steering);\r\n vehicleController.setWheelSteering(1, steering);\r\n\r\n // 漂移\r\n if ((this.rgtPressed || this.lftPressed) && this.shiftPressed) {\r\n vehicleController.setWheelSideFrictionStiffness(2, 0.5);\r\n vehicleController.setWheelSideFrictionStiffness(3, 0.5);\r\n } else {\r\n vehicleController.setWheelSideFrictionStiffness(2, 2);\r\n vehicleController.setWheelSideFrictionStiffness(3, 2);\r\n }\r\n\r\n // 更新所有车辆物理和位置\r\n this.updateVehicleInertia(delta);\r\n\r\n // 相机跟随\r\n if (!this.isFirstPerson) {\r\n // 将相机跟随目标平移到车辆位置\r\n const lookTarget = vehicleGroup.position.clone();\r\n this.camera.position.sub(this.controls.target);\r\n this.controls.target.copy(lookTarget);\r\n this.camera.position.add(lookTarget);\r\n this.controls.update();\r\n\r\n // 根据速度比例动态调整相机距离\r\n const velocity = chassisBody.linvel();\r\n const currentSpeed = Math.sqrt(\r\n velocity.x * velocity.x +\r\n velocity.y * velocity.y +\r\n velocity.z * velocity.z,\r\n );\r\n\r\n const speedRatio = Math.min(currentSpeed / maxSpeed, 1.0);\r\n const baseCamDistance = v.size.l * 0.8;\r\n const maxCamDistanceLimit = v.size.l * 5;\r\n const targetDistance = THREE.MathUtils.lerp(\r\n baseCamDistance,\r\n maxCamDistanceLimit,\r\n speedRatio,\r\n );\r\n\r\n // 射线检测:防止相机穿入碰撞体\r\n this._personToCam.subVectors(\r\n this.camera.position,\r\n vehicleGroup.position,\r\n );\r\n const origin = vehicleGroup.position\r\n .clone()\r\n .add(new THREE.Vector3(0, 0, 0));\r\n const direction = this._personToCam.clone().normalize();\r\n const desiredDist = targetDistance;\r\n this._raycasterPersonToCam.set(origin, direction);\r\n this._raycasterPersonToCam.far = desiredDist;\r\n const intersects = this._raycasterPersonToCam.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n if (intersects.length > 0) {\r\n // 有遮挡:缩短到碰撞点前方安全距离\r\n const hit = intersects[0];\r\n const safeDist = Math.max(\r\n hit.distance - this._camEpsilon,\r\n this.minCamDistance,\r\n );\r\n const targetCamPos = origin\r\n .clone()\r\n .add(direction.clone().multiplyScalar(safeDist));\r\n this.camera.position.lerp(targetCamPos, this._camCollisionLerp);\r\n } else {\r\n // 无遮挡:扩展到最大距离再做一次检测\r\n this._raycasterPersonToCam.far = maxCamDistanceLimit;\r\n const intersectsMaxDis =\r\n this._raycasterPersonToCam.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n let safeDist = desiredDist;\r\n if (intersectsMaxDis.length) {\r\n const hitMax = intersectsMaxDis[0];\r\n safeDist = Math.min(\r\n desiredDist,\r\n hitMax.distance - this._camEpsilon,\r\n );\r\n }\r\n const targetCamPos = origin\r\n .clone()\r\n .add(direction.clone().multiplyScalar(safeDist));\r\n this.camera.position.lerp(targetCamPos, this._camCollisionLerp);\r\n }\r\n\r\n // 行驶且跟随车辆参数开启时:相机跟随速度方向平滑移到车辆正后方\r\n if (\r\n (this.fwdPressed || this.bkdPressed) &&\r\n this.vehicleParams.followVehicleDirection\r\n ) {\r\n const vel = chassisBody.linvel();\r\n const velHorizontal = new THREE.Vector3(vel.x, vel.y, vel.z);\r\n const velSpeed = velHorizontal.length();\r\n if (velSpeed > 0.3) {\r\n const targetBehindDir = velHorizontal\r\n .clone()\r\n .normalize()\r\n .negate();\r\n this.camBehindDir\r\n .lerp(targetBehindDir, this._camCollisionLerp)\r\n .normalize();\r\n const camHeightOffset = v.size.h;\r\n const targetCamPos = lookTarget\r\n .clone()\r\n .add(\r\n this.camBehindDir\r\n .clone()\r\n .multiplyScalar(desiredDist),\r\n )\r\n .add(new THREE.Vector3(0, camHeightOffset, 0));\r\n this.camera.position.lerp(\r\n targetCamPos,\r\n this._camCollisionLerp,\r\n );\r\n this.controls.update();\r\n }\r\n }\r\n }\r\n\r\n // 翻车检测\r\n const vehicleUp = this.upVector\r\n .clone()\r\n .applyQuaternion(vehicleGroup.quaternion);\r\n const angleWithUp = vehicleUp.angleTo(this.upVector);\r\n if (angleWithUp > Math.PI / 2) {\r\n const size = new THREE.Vector3();\r\n v.vehicleBBox?.getSize(size);\r\n const translation2 = chassisBody.translation();\r\n chassisBody.setTranslation(\r\n new this.RAPIER.Vector3(\r\n translation2.x,\r\n translation2.y + size.y,\r\n translation2.z,\r\n ),\r\n true,\r\n );\r\n chassisBody.setRotation(\r\n new this.RAPIER.Quaternion(0, 0, 0, 1),\r\n true,\r\n );\r\n chassisBody.setLinvel(new this.RAPIER.Vector3(0, 0, 0), true);\r\n chassisBody.setAngvel(new this.RAPIER.Vector3(0, 0, 0), true);\r\n }\r\n }\r\n\r\n /**\r\n * 更新所有车辆物理和位置\r\n */\r\n updateVehicleInertia(delta: number) {\r\n if (!this.world) return;\r\n\r\n // 更新所有车辆的物理\r\n this.world.timestep = delta;\r\n this.world.step();\r\n\r\n for (const v of this.vehicles) {\r\n const { vehicleController, chassisBody, vehicleGroup, updateWheelVisuals } = v;\r\n\r\n vehicleController.updateVehicle(delta);\r\n\r\n if (chassisBody.isSleeping()) continue;\r\n\r\n const velocity = chassisBody.linvel();\r\n const currentSpeed = Math.sqrt(\r\n velocity.x * velocity.x +\r\n velocity.y * velocity.y +\r\n velocity.z * velocity.z,\r\n );\r\n const maxSpeed = this.vehicleParams.power.maxSpeed * v.speedMultiplier;\r\n if (currentSpeed > maxSpeed) {\r\n const s = maxSpeed / currentSpeed;\r\n chassisBody.setLinvel(\r\n new this.RAPIER.Vector3(\r\n velocity.x * s,\r\n velocity.y * s,\r\n velocity.z * s,\r\n ),\r\n true,\r\n );\r\n }\r\n\r\n const translation = chassisBody.translation();\r\n const rotationSync = chassisBody.rotation();\r\n vehicleGroup.position.set(\r\n translation.x,\r\n translation.y,\r\n translation.z,\r\n );\r\n vehicleGroup.quaternion.set(\r\n rotationSync.x,\r\n rotationSync.y,\r\n rotationSync.z,\r\n rotationSync.w,\r\n );\r\n\r\n if (updateWheelVisuals) updateWheelVisuals();\r\n }\r\n }\r\n\r\n /**\r\n * 设置人物缩放\r\n */\r\n setPlayerScale(newScale: number) {\r\n if (newScale <= 0) return;\r\n const ratio = newScale / this.playerModel.scale;\r\n\r\n this.playerModel.scale = newScale;\r\n this.gravity *= ratio;\r\n this.jumpHeight *= ratio;\r\n this.playerSpeed *= ratio;\r\n this.playerFlySpeed *= ratio;\r\n this.curPlayerSpeed *= ratio;\r\n this._camEpsilon *= ratio;\r\n this.minCamDistance *= ratio;\r\n this.maxCamDistance *= ratio;\r\n this.orginMaxCamDistance *= ratio;\r\n\r\n if (this.isFirstPerson) this.scene.attach(this.camera);\r\n this.player?.scale.multiplyScalar(ratio);\r\n if (this.player?.capsuleInfo) this.player.capsuleInfo.radius *= ratio;\r\n if (this.isFirstPerson) this.setFirstPersonCamera();\r\n }\r\n\r\n /**\r\n * 更新人物\r\n */\r\n updatePlayer(delta: number) {\r\n if (this.isMovingToBoardingPoint) {\r\n this.updateMoveToBoardingPoint(delta);\r\n }\r\n\r\n if (!this.isFlying) {\r\n this.player.position.addScaledVector(this.playerVelocity, delta);\r\n }\r\n\r\n // 上车衔接关门动画\r\n if (this.isBoardingAnimPlaying) {\r\n const action = this.personActions?.get(\"enterCar\");\r\n const duration = action.getClip().duration;\r\n const timeScale = action.getEffectiveTimeScale();\r\n const remaining = ((duration - action.time) / timeScale) * 1000;\r\n\r\n // 剩余500ms执行关门动画\r\n if (!this.closeDoorTriggered && remaining <= 500) {\r\n this.closeDoorTriggered = true;\r\n this.openVehicleDoor(false);\r\n }\r\n\r\n // 动画结束\r\n if (action.time >= duration) {\r\n this.isBoardingAnimPlaying = false;\r\n this.closeDoorTriggered = false;\r\n this.onEnterCarAnimFinished();\r\n return;\r\n }\r\n }\r\n // 下车衔接关门动画\r\n if (this.isExitAnimPlaying) {\r\n const action = this.personActions?.get(\"exitCar\");\r\n if (action) {\r\n const duration = action.getClip().duration;\r\n const timeScale = action.getEffectiveTimeScale();\r\n const remaining = ((duration - action.time) / timeScale) * 1000;\r\n\r\n // 剩余 500ms 时关门\r\n if (!this.closeExitDoorTriggered && remaining <= 500) {\r\n this.closeExitDoorTriggered = true;\r\n this.openVehicleDoor(false);\r\n }\r\n\r\n // 动画结束\r\n if (action.time >= duration) {\r\n this.isExitAnimPlaying = false;\r\n this.closeExitDoorTriggered = false;\r\n }\r\n }\r\n }\r\n\r\n this.updateMixers(delta);\r\n if (this.controllerMode === 1) return;\r\n\r\n this.camera.getWorldDirection(this.camDir);\r\n let angle = Math.atan2(this.camDir.z, this.camDir.x) + Math.PI / 2;\r\n angle = 2 * Math.PI - angle;\r\n\r\n this.moveDir.set(0, 0, 0);\r\n if (this.fwdPressed) this.moveDir.add(this.DIR_FWD);\r\n if (this.bkdPressed) this.moveDir.add(this.DIR_BKD);\r\n if (this.lftPressed) this.moveDir.add(this.DIR_LFT);\r\n if (this.rgtPressed) this.moveDir.add(this.DIR_RGT);\r\n\r\n if (this.isFlying) {\r\n if (this.fwdPressed) this.moveDir.y = this.camDir.y;\r\n else this.moveDir.y = 0;\r\n if (this.spacePressed) this.moveDir.add(this.DIR_UP);\r\n }\r\n\r\n if (this.isFlying && this.fwdPressed) {\r\n this.curPlayerSpeed = this.shiftPressed ? this.playerFlySpeed * 2 : this.playerFlySpeed\r\n } else {\r\n this.curPlayerSpeed = this.shiftPressed ? this.playerSpeed * 2 : this.playerSpeed;\r\n }\r\n\r\n this.moveDir.normalize().applyAxisAngle(this.upVector, angle);\r\n this.player.position.addScaledVector(\r\n this.moveDir,\r\n this.curPlayerSpeed * delta,\r\n );\r\n\r\n // 向下射线检测地面\r\n let playerDistanceFromGround = Infinity;\r\n this._originTmp.set(\r\n this.player.position.x,\r\n this.player.position.y,\r\n this.player.position.z,\r\n );\r\n this._raycaster.ray.origin.copy(this._originTmp);\r\n const intersects = this._raycaster.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n\r\n if (intersects.length > 0) {\r\n playerDistanceFromGround =\r\n this.player.position.y - intersects[0].point.y;\r\n const maxH = this.playerHeight * this.playerModel.scale * 0.9;\r\n const h = this.playerHeight * this.playerModel.scale * 0.75;\r\n const minH = this.playerHeight * this.playerModel.scale * 0.7;\r\n\r\n if (!this.isFlying) {\r\n if (playerDistanceFromGround >= maxH) {\r\n this.playerVelocity.y += delta * this.gravity;\r\n this.player.position.addScaledVector(\r\n this.playerVelocity,\r\n delta,\r\n );\r\n this.playerIsOnGround = false;\r\n } else if (\r\n playerDistanceFromGround >= h &&\r\n playerDistanceFromGround < maxH\r\n ) {\r\n if (!this.spacePressed) {\r\n this.playerVelocity.set(0, 0, 0);\r\n this.playerIsOnGround = true;\r\n this.player.position.y = intersects[0].point.y + h;\r\n }\r\n } else if (\r\n playerDistanceFromGround >= minH &&\r\n playerDistanceFromGround < h\r\n ) {\r\n this.playerVelocity.set(0, 0, 0);\r\n this.playerIsOnGround = true;\r\n this.player.position.y = intersects[0].point.y + h;\r\n } else if (playerDistanceFromGround < minH) {\r\n this.playerVelocity.set(0, 0, 0);\r\n this.player.position.set(\r\n this.player.position.x,\r\n intersects[0].point.y + h,\r\n this.player.position.z,\r\n );\r\n this.playerIsOnGround = true;\r\n }\r\n }\r\n }\r\n\r\n this.player.updateMatrixWorld();\r\n\r\n // BVH 碰撞检测\r\n const capsuleInfo = this.player.capsuleInfo;\r\n this.tempBox.makeEmpty();\r\n this.tempMat.copy(this.collider!.matrixWorld).invert();\r\n this.tempSegment.copy(capsuleInfo.segment);\r\n this.tempSegment.start\r\n .applyMatrix4(this.player.matrixWorld)\r\n .applyMatrix4(this.tempMat);\r\n this.tempSegment.end\r\n .applyMatrix4(this.player.matrixWorld)\r\n .applyMatrix4(this.tempMat);\r\n this.tempBox.expandByPoint(this.tempSegment.start);\r\n this.tempBox.expandByPoint(this.tempSegment.end);\r\n this.tempBox.expandByScalar(capsuleInfo.radius);\r\n\r\n if (!this.isMovingToBoardingPoint) {\r\n (this.collider?.geometry as any)?.boundsTree?.shapecast({\r\n intersectsBounds: (box: THREE.Box3) =>\r\n box.intersectsBox(this.tempBox),\r\n intersectsTriangle: (tri: any) => {\r\n const triPoint = this.tempVector;\r\n const capsulePoint = this.tempVector2;\r\n const distance = tri.closestPointToSegment(\r\n this.tempSegment,\r\n triPoint,\r\n capsulePoint,\r\n );\r\n if (distance < capsuleInfo.radius) {\r\n const normal = tri.getNormal(new THREE.Vector3());\r\n if (normal.y > 0.5 && !this.isFlying) return;\r\n const depth = capsuleInfo.radius - distance;\r\n const direction = capsulePoint\r\n .sub(triPoint)\r\n .normalize();\r\n this.tempSegment.start.addScaledVector(\r\n direction,\r\n depth,\r\n );\r\n this.tempSegment.end.addScaledVector(direction, depth);\r\n }\r\n },\r\n });\r\n\r\n (this.dynamicCollider?.geometry as any)?.boundsTree?.shapecast({\r\n intersectsBounds: (box: THREE.Box3) =>\r\n box.intersectsBox(this.tempBox),\r\n intersectsTriangle: (tri: any) => {\r\n const triPoint = this.tempVector;\r\n const capsulePoint = this.tempVector2;\r\n const distance = tri.closestPointToSegment(\r\n this.tempSegment,\r\n triPoint,\r\n capsulePoint,\r\n );\r\n if (distance < capsuleInfo.radius) {\r\n const depth = capsuleInfo.radius - distance;\r\n const direction = capsulePoint\r\n .sub(triPoint)\r\n .normalize();\r\n this.tempSegment.start.addScaledVector(\r\n direction,\r\n depth,\r\n );\r\n this.tempSegment.end.addScaledVector(direction, depth);\r\n }\r\n },\r\n });\r\n }\r\n\r\n const newPosition = this.tempVector\r\n .copy(this.tempSegment.start)\r\n .applyMatrix4(this.collider!.matrixWorld);\r\n const deltaVector = this.tempVector2.subVectors(\r\n newPosition,\r\n this.player.position,\r\n );\r\n const offset = Math.max(0, deltaVector.length() - 1e-5);\r\n deltaVector.normalize().multiplyScalar(offset);\r\n this.player.position.add(deltaVector);\r\n\r\n // 第三人称-朝向\r\n if (!this.isFirstPerson && !this.isFlying) {\r\n this.camDir.y = 0;\r\n this.camDir.normalize();\r\n this.camDir.negate();\r\n this.moveDir.normalize();\r\n this.moveDir.negate();\r\n\r\n let lookTarget: THREE.Vector3;\r\n if (this.thirdMouseMode === 0 || this.thirdMouseMode === 2) {\r\n if (this.moveDir.lengthSq() > 0) {\r\n lookTarget = this.player.position.clone().add(this.moveDir);\r\n } else {\r\n lookTarget = this.player.position.clone().add(this.camDir);\r\n }\r\n this.targetMat.lookAt(\r\n this.player.position,\r\n lookTarget,\r\n this.player.up,\r\n );\r\n this.targetQuat.setFromRotationMatrix(this.targetMat);\r\n const alpha = Math.min(1, this.rotationSpeed * delta);\r\n this.player.quaternion.slerp(this.targetQuat, alpha);\r\n }\r\n if (\r\n (this.thirdMouseMode === 1 || this.thirdMouseMode === 3) &&\r\n this.moveDir.lengthSq() > 0\r\n ) {\r\n lookTarget = this.player.position.clone().add(this.moveDir);\r\n this.targetMat.lookAt(\r\n this.player.position,\r\n lookTarget,\r\n this.player.up,\r\n );\r\n this.targetQuat.setFromRotationMatrix(this.targetMat);\r\n const alpha = Math.min(1, this.rotationSpeed * delta);\r\n this.player.quaternion.slerp(this.targetQuat, alpha);\r\n }\r\n }\r\n\r\n // 飞行模式朝向\r\n if (this.isFlying) {\r\n if (!this.isFirstPerson) {\r\n this.camDir.y = 0;\r\n this.camDir.normalize();\r\n this.camDir.negate();\r\n this.moveDir.normalize();\r\n this.moveDir.negate();\r\n const lookTarget = this.player.position\r\n .clone()\r\n .add(this.fwdPressed ? this.moveDir : this.camDir);\r\n this.targetMat.lookAt(\r\n this.player.position,\r\n lookTarget,\r\n this.player.up,\r\n );\r\n this.targetQuat.setFromRotationMatrix(this.targetMat);\r\n const alpha = Math.min(1, this.rotationSpeed * delta);\r\n this.player.quaternion.slerp(this.targetQuat, alpha);\r\n }\r\n }\r\n\r\n // 第三人称-相机跟随\r\n if (!this.isFirstPerson) {\r\n const lookTarget = this.player.position.clone();\r\n lookTarget.y += (this.playerHeight / 8) * this.playerModel.scale;\r\n this.camera.position.sub(this.controls.target);\r\n this.controls.target.copy(lookTarget);\r\n this.camera.position.add(lookTarget);\r\n this.controls.update();\r\n\r\n // 当视线被遮挡时的处理\r\n if (!this.enableZoom) {\r\n this._personToCam.subVectors(\r\n this.camera.position,\r\n this.player.position,\r\n );\r\n const origin = this.player.position.clone();\r\n const direction = this._personToCam.clone().normalize();\r\n const desiredDist = this._personToCam.length();\r\n this._raycasterPersonToCam.set(origin, direction);\r\n this._raycasterPersonToCam.far = desiredDist;\r\n\r\n const intersectsCamera =\r\n this._raycasterPersonToCam.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n\r\n if (intersectsCamera.length > 0) {\r\n const hit = intersectsCamera[0];\r\n const safeDist = Math.max(\r\n hit.distance - this._camEpsilon,\r\n this.minCamDistance,\r\n );\r\n const targetCamPos = origin\r\n .clone()\r\n .add(direction.clone().multiplyScalar(safeDist));\r\n this.camera.position.lerp(\r\n targetCamPos,\r\n this._camCollisionLerp,\r\n );\r\n } else {\r\n this._raycasterPersonToCam.far = this.maxCamDistance;\r\n const intersectsMaxDis =\r\n this._raycasterPersonToCam.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n let safeDist = this.maxCamDistance;\r\n if (intersectsMaxDis.length) {\r\n const hitMax = intersectsMaxDis[0];\r\n safeDist = hitMax.distance - this._camEpsilon;\r\n }\r\n const targetCamPos = origin\r\n .clone()\r\n .add(direction.clone().multiplyScalar(safeDist));\r\n this.camera.position.lerp(\r\n targetCamPos,\r\n this._camCollisionLerp,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // 掉出场景重置\r\n if (this.player.position.y < this.boundingBoxMinY - 1) {\r\n this._originTmp.set(\r\n this.player.position.x,\r\n 10000,\r\n this.player.position.z,\r\n );\r\n this._raycaster.ray.origin.copy(this._originTmp);\r\n const intersectsFall = this._raycaster.intersectObject(\r\n this.collider as THREE.Object3D,\r\n false,\r\n );\r\n\r\n if (intersectsFall.length > 0) {\r\n console.log(\"玩家为bug意外掉落\");\r\n this.reset(\r\n new THREE.Vector3(\r\n this.player.position.x,\r\n intersectsFall[0].point.y + 5,\r\n this.player.position.z,\r\n ),\r\n );\r\n } else {\r\n console.log(\"玩家正常掉落\");\r\n this.reset(\r\n new THREE.Vector3(\r\n this.player.position.x,\r\n this.player.position.y + 15,\r\n this.player.position.z,\r\n ),\r\n );\r\n }\r\n }\r\n\r\n // 显示移动端按钮时检测\r\n if (this.isShowMobileControls) {\r\n if (this.vehicles.length) {\r\n let near = false;\r\n for (const v of this.vehicles) {\r\n this.nearCheckLocal\r\n .copy(v.boardingPoint)\r\n .multiplyScalar(v.scale);\r\n v.vehicleGroup.localToWorld(\r\n this.nearCheckWorld.copy(this.nearCheckLocal),\r\n );\r\n\r\n if (\r\n this.player.position.distanceTo(this.nearCheckWorld) <\r\n 800 * this.playerModel.scale\r\n ) {\r\n near = true;\r\n this.syncVehicleBtnEl(near);\r\n break;\r\n }\r\n }\r\n if (near !== this.isNearVehicle) {\r\n this.isNearVehicle = near;\r\n this.syncVehicleBtnEl(near);\r\n }\r\n } else {\r\n this.isNearVehicle = false;\r\n this.syncVehicleBtnEl(false);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 获取屏幕中心点向前射线与碰撞体的交点\r\n */\r\n getCenterScreenRaycastHit(): THREE.Intersection | undefined {\r\n this.camera.updateMatrixWorld();\r\n this.centerRay.setFromCamera(this.centerMouse, this.camera);\r\n const intersects = this.centerRay.intersectObject(this.collider, false);\r\n return intersects[0];\r\n }\r\n\r\n /**\r\n * 更新模型动画\r\n */\r\n private updateMixers(delta: number) {\r\n if (this.personMixer) this.personMixer.update(delta);\r\n // 更新所有车辆动画\r\n for (const v of this.vehicles) {\r\n v.vehicleMixer?.update(delta);\r\n }\r\n }\r\n\r\n reset(position?: THREE.Vector3) {\r\n if (!this.player) return;\r\n this.playerVelocity.set(0, 0, 0);\r\n this.player.position.copy(position ?? this.initPos);\r\n }\r\n\r\n getPosition() {\r\n return this.player?.position;\r\n }\r\n\r\n // ==================== 输入处理 ====================\r\n\r\n setInput(\r\n input: Partial<{\r\n moveX: 1 | 0 | -1;\r\n moveY: 1 | 0 | -1;\r\n lookDeltaX: number;\r\n lookDeltaY: number;\r\n jump: boolean;\r\n shift: boolean;\r\n toggleView: boolean;\r\n toggleFly: boolean;\r\n toggleVehicle: boolean;\r\n }>,\r\n ) {\r\n if (typeof input.moveX === \"number\") {\r\n this.lftPressed = input.moveX === -1;\r\n this.rgtPressed = input.moveX === 1;\r\n this.setAnimationByPressed();\r\n }\r\n if (typeof input.moveY === \"number\") {\r\n this.fwdPressed = input.moveY === 1;\r\n this.bkdPressed = input.moveY === -1;\r\n this.setAnimationByPressed();\r\n }\r\n\r\n if (\r\n typeof input.lookDeltaX === \"number\" &&\r\n typeof input.lookDeltaY === \"number\"\r\n ) {\r\n this.setToward(input.lookDeltaX, input.lookDeltaY, 0.002);\r\n }\r\n\r\n if (typeof input.jump === \"boolean\") {\r\n if (input.jump) {\r\n if (this.isMovingToBoardingPoint) {\r\n this.isMovingToBoardingPoint = false;\r\n this.boardingWaypoints = [];\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = null;\r\n }\r\n this.spacePressed = true;\r\n if (this.controllerMode == 1) return;\r\n if (!this.playerIsOnGround || this.isFlying) return;\r\n this.playPersonAnimationByName(\"jumping\");\r\n this.playerVelocity.y = this.jumpHeight;\r\n this.playerIsOnGround = false;\r\n } else {\r\n this.spacePressed = false;\r\n }\r\n }\r\n\r\n if (typeof input.shift === \"boolean\") {\r\n this.shiftPressed = input.shift;\r\n }\r\n\r\n if (input.toggleView) {\r\n this.changeView();\r\n }\r\n\r\n if (input.toggleFly && this.playerFlyEnabled && this.controllerMode == 0) {\r\n this.isFlying = !this.isFlying;\r\n this.setAnimationByPressed();\r\n if (!this.isFlying && !this.playerIsOnGround) {\r\n this.playPersonAnimationByName(\"jumping\");\r\n }\r\n }\r\n\r\n if (input.toggleVehicle) {\r\n if (this.controllerMode == 0) {\r\n this.enterVehicle();\r\n } else {\r\n this.exitVehicle();\r\n }\r\n }\r\n }\r\n\r\n private setAnimationByPressed = () => {\r\n this.maxCamDistance = this.orginMaxCamDistance;\r\n // 重置标志位\r\n if (this.isMovingToBoardingPoint) {\r\n this.isMovingToBoardingPoint = false;\r\n this.boardingWaypoints = [];\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = null;\r\n }\r\n if (this.isExitAnimPlaying) {\r\n this.isExitAnimPlaying = false;\r\n this.closeExitDoorTriggered = false;\r\n }\r\n if (this.isBoardingAnimPlaying) {\r\n this.isBoardingAnimPlaying = false;\r\n this.closeDoorTriggered = false;\r\n }\r\n\r\n if (this.closeVehicleDoorTimer) {\r\n clearTimeout(this.closeVehicleDoorTimer);\r\n this.closeVehicleDoorTimer = null;\r\n }\r\n\r\n if (this.isFlying) {\r\n if (!this.fwdPressed) {\r\n this.playPersonAnimationByName(\"flyidle\");\r\n return;\r\n }\r\n this.playPersonAnimationByName(\"flying\");\r\n this.maxCamDistance = this.orginMaxCamDistance * 2;\r\n return;\r\n }\r\n\r\n if (this.playerIsOnGround) {\r\n if (\r\n !this.fwdPressed &&\r\n !this.bkdPressed &&\r\n !this.lftPressed &&\r\n !this.rgtPressed\r\n ) {\r\n this.playPersonAnimationByName(\"idle\");\r\n return;\r\n }\r\n\r\n if (this.fwdPressed) {\r\n this.playPersonAnimationByName(\r\n this.shiftPressed ? \"running\" : \"walking\",\r\n );\r\n return;\r\n }\r\n\r\n if (\r\n !this.isFirstPerson &&\r\n (this.lftPressed || this.rgtPressed || this.bkdPressed)\r\n ) {\r\n this.playPersonAnimationByName(\r\n this.shiftPressed ? \"running\" : \"walking\",\r\n );\r\n return;\r\n }\r\n\r\n if (this.lftPressed) {\r\n this.playPersonAnimationByName(\"left_walking\");\r\n return;\r\n }\r\n if (this.rgtPressed) {\r\n this.playPersonAnimationByName(\"right_walking\");\r\n return;\r\n }\r\n if (this.bkdPressed) {\r\n this.playPersonAnimationByName(\"walking_backward\");\r\n return;\r\n }\r\n }\r\n\r\n if (this.recheckAnimTimer !== null) {\r\n clearTimeout(this.recheckAnimTimer);\r\n }\r\n this.recheckAnimTimer = setTimeout(() => {\r\n this.setAnimationByPressed();\r\n this.recheckAnimTimer = null;\r\n }, 200);\r\n };\r\n\r\n // ==================== 事件处理 ====================\r\n\r\n private _boundOnKeydown = async (e: KeyboardEvent) => {\r\n if (e.ctrlKey && [\"KeyW\", \"KeyA\", \"KeyS\", \"KeyD\"].includes(e.code)) {\r\n e.preventDefault();\r\n }\r\n switch (e.code) {\r\n case \"KeyW\":\r\n case \"ArrowUp\":\r\n this.fwdPressed = true;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyS\":\r\n case \"ArrowDown\":\r\n this.bkdPressed = true;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyD\":\r\n case \"ArrowRight\":\r\n this.rgtPressed = true;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyA\":\r\n case \"ArrowLeft\":\r\n this.lftPressed = true;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"ShiftLeft\":\r\n case \"ShiftRight\":\r\n this.shiftPressed = true;\r\n this.setAnimationByPressed();\r\n this.controls.mouseButtons = { LEFT: 2, MIDDLE: 1, RIGHT: 0 };\r\n break;\r\n case \"Space\":\r\n if (this.isMovingToBoardingPoint) {\r\n this.isMovingToBoardingPoint = false;\r\n this.boardingWaypoints = [];\r\n this.currentWaypointIndex = 0;\r\n this.boardingTargetDir = null;\r\n }\r\n this.spacePressed = true;\r\n if (this.controllerMode == 1) return;\r\n if (!this.playerIsOnGround || this.isFlying) return;\r\n const next = this.personActions?.get(\"jumping\");\r\n if (next && this.actionState === next) return;\r\n this.playPersonAnimationByName(\"jumping\");\r\n this.playerVelocity.y = this.jumpHeight;\r\n this.playerIsOnGround = false;\r\n break;\r\n case \"ControlLeft\":\r\n this.ctPressed = true;\r\n break;\r\n case \"KeyV\":\r\n this.changeView();\r\n break;\r\n case \"KeyF\":\r\n if (this.controllerMode == 0 && this.playerFlyEnabled) {\r\n this.isFlying = !this.isFlying;\r\n this.setAnimationByPressed();\r\n if (!this.isFlying && !this.playerIsOnGround) {\r\n this.playPersonAnimationByName(\"jumping\");\r\n }\r\n }\r\n break;\r\n case \"KeyE\":\r\n if (this.isFlying) return;\r\n if (this.controllerMode == 0) {\r\n this.enterVehicle();\r\n } else {\r\n this.exitVehicle();\r\n }\r\n break;\r\n }\r\n };\r\n\r\n private _boundOnKeyup = (e: KeyboardEvent) => {\r\n switch (e.code) {\r\n case \"KeyW\":\r\n case \"ArrowUp\":\r\n this.fwdPressed = false;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyS\":\r\n case \"ArrowDown\":\r\n this.bkdPressed = false;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyD\":\r\n case \"ArrowRight\":\r\n this.rgtPressed = false;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"KeyA\":\r\n case \"ArrowLeft\":\r\n this.lftPressed = false;\r\n this.setAnimationByPressed();\r\n break;\r\n case \"ShiftLeft\":\r\n case \"ShiftRight\":\r\n this.shiftPressed = false;\r\n this.setAnimationByPressed();\r\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\r\n break;\r\n case \"Space\":\r\n this.spacePressed = false;\r\n break;\r\n case \"ControlLeft\":\r\n this.ctPressed = false;\r\n break;\r\n }\r\n };\r\n\r\n private _mouseMove = (e: MouseEvent) => {\r\n if (document.pointerLockElement !== document.body) return;\r\n this.setToward(e.movementX, e.movementY, 0.0001);\r\n };\r\n\r\n private _mouseClick = (_e: MouseEvent) => {\r\n this.setPointerLock();\r\n };\r\n\r\n onAllEvent() {\r\n this.isupdate = true;\r\n this.setPointerLock();\r\n window.addEventListener(\"keydown\", this._boundOnKeydown);\r\n window.addEventListener(\"keyup\", this._boundOnKeyup);\r\n window.addEventListener(\"mousemove\", this._mouseMove);\r\n window.addEventListener(\"click\", this._mouseClick);\r\n }\r\n\r\n offAllEvent() {\r\n this.isupdate = false;\r\n document.exitPointerLock();\r\n window.removeEventListener(\"keydown\", this._boundOnKeydown);\r\n window.removeEventListener(\"keyup\", this._boundOnKeyup);\r\n window.removeEventListener(\"mousemove\", this._mouseMove);\r\n window.removeEventListener(\"click\", this._mouseClick);\r\n }\r\n\r\n // ==================== 移动端控制 ====================\r\n\r\n onPointerDown = (e: PointerEvent) => {\r\n if (e.pointerType !== \"touch\") return;\r\n this.isLookDown = true;\r\n this.lookPointerId = e.pointerId;\r\n this.lastTouchX = e.clientX;\r\n this.lastTouchY = e.clientY;\r\n this.lookAreaEl?.setPointerCapture?.(e.pointerId);\r\n e.preventDefault();\r\n };\r\n\r\n onPointerMove = (e: PointerEvent) => {\r\n if (!this.isLookDown || e.pointerId !== this.lookPointerId) return;\r\n const dx = e.clientX - this.lastTouchX;\r\n const dy = e.clientY - this.lastTouchY;\r\n this.lastTouchX = e.clientX;\r\n this.lastTouchY = e.clientY;\r\n this.setInput({ lookDeltaX: dx, lookDeltaY: dy });\r\n e.preventDefault();\r\n };\r\n\r\n onPointerUp = (e: PointerEvent) => {\r\n if (e.pointerId !== this.lookPointerId) return;\r\n this.isLookDown = false;\r\n this.lookPointerId = null;\r\n this.lookAreaEl?.releasePointerCapture?.(e.pointerId);\r\n };\r\n\r\n async initMobileControls() {\r\n this.controls.maxPolarAngle = Math.PI * (300 / 360);\r\n this.controls.touches = { ONE: null as any, TWO: null as any };\r\n this.nippleModule = await import(\"nipplejs\");\r\n const nipple = this.nippleModule?.default;\r\n const JOY_SIZE = 120;\r\n const container = document.body;\r\n\r\n this.joystickZoneEl = document.createElement(\"div\");\r\n this.joystickZoneEl.id = \"joy-zone\";\r\n Object.assign(this.joystickZoneEl.style, {\r\n position: \"absolute\",\r\n left: \"16px\",\r\n bottom: \"16px\",\r\n width: `${JOY_SIZE + 40}px`,\r\n height: `${JOY_SIZE + 40}px`,\r\n touchAction: \"none\",\r\n zIndex: \"999\",\r\n pointerEvents: \"auto\",\r\n WebkitUserSelect: \"none\",\r\n userSelect: \"none\",\r\n });\r\n container.appendChild(this.joystickZoneEl);\r\n\r\n [\"touchstart\", \"touchmove\", \"touchend\", \"touchcancel\"].forEach(\r\n (evtName) => {\r\n this.joystickZoneEl?.addEventListener(\r\n evtName,\r\n (e) => e.preventDefault(),\r\n {\r\n passive: false,\r\n },\r\n );\r\n },\r\n );\r\n\r\n this.joystickManager = nipple.create({\r\n zone: this.joystickZoneEl,\r\n mode: \"static\",\r\n position: {\r\n left: `${(JOY_SIZE + 40) / 2}px`,\r\n bottom: `${(JOY_SIZE + 40) / 2}px`,\r\n },\r\n color: \"#ffffff\",\r\n size: JOY_SIZE,\r\n multitouch: true,\r\n maxNumberOfNipples: 1,\r\n });\r\n\r\n this.joystickManager.on(\"move\", (_evt: any, data: any) => {\r\n if (!data) return;\r\n const rawX = data.vector?.x ?? 0;\r\n const rawY = data.vector?.y ?? 0;\r\n const distance = data.distance ?? 0;\r\n const deadzone = 0.5;\r\n const dirX = rawX > deadzone ? 1 : rawX < -deadzone ? -1 : 0;\r\n const dirY = rawY > deadzone ? 1 : rawY < -deadzone ? -1 : 0;\r\n const sprintThreshold = JOY_SIZE / 2;\r\n const isSprinting = distance >= sprintThreshold;\r\n const prev = this.prevJoyState || {\r\n dirX: 0,\r\n dirY: 0,\r\n shift: false,\r\n };\r\n if (\r\n dirX === prev.dirX &&\r\n dirY === prev.dirY &&\r\n isSprinting === prev.shift\r\n )\r\n return;\r\n this.prevJoyState = { dirX, dirY, shift: isSprinting };\r\n this.setInput({ moveX: dirX, moveY: dirY, shift: isSprinting });\r\n });\r\n\r\n this.joystickManager.on(\"end\", () => {\r\n const prev = this.prevJoyState || {\r\n dirX: 0,\r\n dirY: 0,\r\n shift: false,\r\n };\r\n if (prev.dirX !== 0 || prev.dirY !== 0 || prev.shift !== false) {\r\n this.prevJoyState = { dirX: 0, dirY: 0, shift: false };\r\n this.setInput({ moveX: 0, moveY: 0, shift: false });\r\n }\r\n });\r\n\r\n this.lookAreaEl = document.createElement(\"div\");\r\n Object.assign(this.lookAreaEl.style, {\r\n position: \"absolute\",\r\n right: \"0\",\r\n bottom: \"0\",\r\n width: \"50%\",\r\n height: \"100%\",\r\n zIndex: \"998\",\r\n touchAction: \"none\",\r\n WebkitUserSelect: \"none\",\r\n userSelect: \"none\",\r\n });\r\n container.appendChild(this.lookAreaEl);\r\n\r\n [\"touchstart\", \"touchmove\", \"touchend\", \"touchcancel\"].forEach(\r\n (evtName) => {\r\n this.lookAreaEl?.addEventListener(\r\n evtName,\r\n (e) => e.preventDefault(),\r\n {\r\n passive: false,\r\n },\r\n );\r\n },\r\n );\r\n\r\n this.lookAreaEl.addEventListener(\"pointerdown\", this.onPointerDown, {\r\n passive: false,\r\n });\r\n this.lookAreaEl.addEventListener(\"pointermove\", this.onPointerMove, {\r\n passive: false,\r\n });\r\n this.lookAreaEl.addEventListener(\"pointerup\", this.onPointerUp, {\r\n passive: false,\r\n });\r\n this.lookAreaEl.addEventListener(\"pointercancel\", this.onPointerUp, {\r\n passive: false,\r\n });\r\n\r\n const createBtn = (\r\n rightPx: number,\r\n bottomPx: number,\r\n bgUrl?: string,\r\n ) => {\r\n const btn = document.createElement(\"button\");\r\n const styles: Partial<CSSStyleDeclaration> = {\r\n position: \"absolute\",\r\n right: `${rightPx}px`,\r\n bottom: `${bottomPx}px`,\r\n width: \"56px\",\r\n height: \"56px\",\r\n zIndex: \"1000\",\r\n borderRadius: \"50%\",\r\n border: \"2px solid black\",\r\n background: \"rgba(0,0,0)\",\r\n padding: \"20px\",\r\n opacity: \"0.95\",\r\n touchAction: \"none\",\r\n fontSize: \"14px\",\r\n userSelect: \"none\",\r\n overflow: \"hidden\",\r\n boxSizing: \"border-box\",\r\n backgroundColor: \"transparent\",\r\n backgroundRepeat: \"no-repeat, no-repeat\",\r\n backgroundPosition: \"center center, center center\",\r\n backgroundSize: \"100% 100%, 80% 80%\",\r\n };\r\n\r\n if (bgUrl) {\r\n const overlayColor = \"rgba(0,0,0,0.5)\";\r\n styles.backgroundImage = `linear-gradient(${overlayColor}, ${overlayColor}), url(\"${bgUrl}\")`;\r\n }\r\n\r\n Object.assign(btn.style, styles);\r\n container.appendChild(btn);\r\n [\"touchstart\", \"touchend\", \"touchcancel\"].forEach((evtName) => {\r\n btn.addEventListener(evtName, (e) => e.preventDefault(), {\r\n passive: false,\r\n });\r\n });\r\n return btn;\r\n };\r\n\r\n this.jumpBtnEl = createBtn(14, 14, jumpIconModule);\r\n this.jumpBtnEl.addEventListener(\r\n \"touchstart\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ jump: true });\r\n },\r\n { passive: false },\r\n );\r\n this.jumpBtnEl.addEventListener(\r\n \"touchend\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ jump: false });\r\n },\r\n { passive: false },\r\n );\r\n this.jumpBtnEl.addEventListener(\r\n \"touchcancel\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ jump: false });\r\n },\r\n { passive: false },\r\n );\r\n\r\n this.flyBtnEl = createBtn(14, 14 + 80, flyIconModule);\r\n this.flyBtnEl.addEventListener(\r\n \"touchstart\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ toggleFly: true });\r\n },\r\n { passive: false },\r\n );\r\n\r\n this.viewBtnEl = createBtn(14, 14 + 200, viewIconModule);\r\n this.viewBtnEl.addEventListener(\r\n \"touchstart\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ toggleView: true });\r\n },\r\n { passive: false },\r\n );\r\n\r\n this.vehicleBtnEl = createBtn(14 + 100, 14 + 120, vehicleIconModule);\r\n this.vehicleBtnEl.addEventListener(\r\n \"touchstart\",\r\n (e) => {\r\n e.preventDefault();\r\n this.setInput({ toggleVehicle: true });\r\n },\r\n { passive: false },\r\n );\r\n }\r\n\r\n destroyMobileControls() {\r\n try {\r\n if (this.joystickManager && this.joystickManager.destroy) {\r\n this.joystickManager.destroy();\r\n this.joystickManager = null;\r\n }\r\n if (this.joystickZoneEl?.parentElement) {\r\n this.joystickZoneEl.parentElement.removeChild(\r\n this.joystickZoneEl,\r\n );\r\n this.joystickZoneEl = null;\r\n }\r\n if (this.lookAreaEl?.parentElement) {\r\n this.lookAreaEl.parentElement.removeChild(this.lookAreaEl);\r\n this.lookAreaEl = null;\r\n }\r\n if (this.jumpBtnEl?.parentElement) {\r\n this.jumpBtnEl.parentElement.removeChild(this.jumpBtnEl);\r\n this.jumpBtnEl = null;\r\n }\r\n if (this.flyBtnEl?.parentElement) {\r\n this.flyBtnEl.parentElement.removeChild(this.flyBtnEl);\r\n this.flyBtnEl = null;\r\n }\r\n if (this.viewBtnEl?.parentElement) {\r\n this.viewBtnEl.parentElement.removeChild(this.viewBtnEl);\r\n this.viewBtnEl = null;\r\n }\r\n if (this.vehicleBtnEl?.parentElement) {\r\n this.vehicleBtnEl.parentElement.removeChild(this.vehicleBtnEl);\r\n this.vehicleBtnEl = null;\r\n }\r\n this.lookAreaEl?.removeEventListener(\r\n \"pointerdown\",\r\n this.onPointerDown,\r\n );\r\n this.lookAreaEl?.removeEventListener(\r\n \"pointermove\",\r\n this.onPointerMove,\r\n );\r\n this.lookAreaEl?.removeEventListener(\"pointerup\", this.onPointerUp);\r\n this.lookAreaEl?.removeEventListener(\r\n \"pointercancel\",\r\n this.onPointerUp,\r\n );\r\n } catch (e) {\r\n console.warn(\"销毁移动端摇杆控制时出错:\", e);\r\n }\r\n }\r\n\r\n syncVehicleBtnEl(show: boolean) {\r\n if (!this.vehicleBtnEl) return;\r\n this.vehicleBtnEl.style.display = show ? \"block\" : \"none\";\r\n }\r\n\r\n syncControllerModeBtnEl() {\r\n if (!this.isShowMobileControls) return;\r\n if (this.controllerMode == 0) {\r\n // 人物控制\r\n this.flyBtnEl.style.display = \"block\";\r\n const overlayColor = \"rgba(0,0,0,0.5)\";\r\n this.jumpBtnEl.style.backgroundImage = `linear-gradient(${overlayColor}, ${overlayColor}), url(\"${jumpIconModule}\")`;\r\n } else {\r\n // 车辆控制\r\n this.flyBtnEl.style.display = \"none\";\r\n const overlayColor = \"rgba(0,0,0,0.5)\";\r\n this.jumpBtnEl.style.backgroundImage = `linear-gradient(${overlayColor}, ${overlayColor}), url(\"${breakIconModule}\")`;\r\n this.jumpBtnEl.style.backgroundImage = `url(${breakIconModule})`;\r\n }\r\n }\r\n\r\n // ==================== 更新参数 ====================\r\n\r\n setMouseSensitivity(mouseSensity: number) {\r\n this.mouseSensity = mouseSensity;\r\n this.controls.rotateSpeed = this.mouseSensity * 0.05;\r\n }\r\n\r\n setGravity(gravity: number) {\r\n this.gravity = gravity * this.playerModel.scale;\r\n }\r\n\r\n setJumpHeight(jumpHeight: number) {\r\n this.jumpHeight = jumpHeight * this.playerModel.scale;\r\n }\r\n\r\n setPlayerSpeed(playerSpeed: number) {\r\n this.playerSpeed = playerSpeed * this.playerModel.scale;\r\n this.curPlayerSpeed = this.playerSpeed;\r\n }\r\n\r\n setPlayerFlySpeed(playerFlySpeed: number) {\r\n this.playerFlySpeed = playerFlySpeed * this.playerModel.scale;\r\n }\r\n\r\n setMinCamDistance(minCamDistance: number) {\r\n this.minCamDistance = minCamDistance * this.playerModel.scale;\r\n }\r\n\r\n setMaxCamDistance(maxCamDistance: number) {\r\n this.maxCamDistance = maxCamDistance * this.playerModel.scale;\r\n this.orginMaxCamDistance = this.maxCamDistance;\r\n }\r\n\r\n setThirdMouseMode(thirdMouseMode: 0 | 1 | 2 | 3) {\r\n this.thirdMouseMode = thirdMouseMode;\r\n this.setPointerLock();\r\n }\r\n\r\n setEnableZoom(enableZoom: boolean) {\r\n this.enableZoom = enableZoom;\r\n this.controls.enableZoom = this.enableZoom;\r\n }\r\n\r\n setDebug(debug: boolean) {\r\n if (this.collider) this.scene.remove(this.collider);\r\n if (debug) {\r\n this.scene.add(this.collider);\r\n (this.player.material as THREE.Material).opacity = 0.5;\r\n } else {\r\n (this.player.material as THREE.Material).opacity = 0;\r\n }\r\n }\r\n\r\n // ==================== 销毁 ====================\r\n\r\n destroy() {\r\n this.offAllEvent();\r\n if (this.player) {\r\n this.player.remove(this.camera);\r\n this.scene.remove(this.player);\r\n }\r\n (this.player as any) = null;\r\n if (this.person) {\r\n this.scene.remove(this.person);\r\n this.person = null;\r\n }\r\n\r\n this.resetControls();\r\n\r\n if (this.visualizer) {\r\n this.scene.remove(this.visualizer);\r\n this.visualizer = null;\r\n }\r\n if (this.collider) {\r\n this.scene.remove(this.collider);\r\n this.collider = null;\r\n }\r\n\r\n this.destroyMobileControls();\r\n\r\n // 清理所有车辆\r\n for (const v of this.vehicles) {\r\n this.scene.remove(v.vehicleGroup);\r\n v.pathPlanner?.dispose();\r\n }\r\n this.vehicles = [];\r\n this.activeVehicle = null;\r\n\r\n controllerInstance = null;\r\n }\r\n}\r\n\r\n// ==================== 导出API ====================\r\n\r\nexport function playerController() {\r\n if (!controllerInstance) controllerInstance = new PlayerController();\r\n const c = controllerInstance;\r\n return {\r\n init: (opts: PlayerControllerOptions, callback?: () => void) => c.init(opts, callback),\r\n loadVehicleModel: (params: VehicleOptions) => c.loadVehicleModel(params),\r\n changeView: () => c.changeView(),\r\n reset: (pos?: THREE.Vector3) => c.reset(pos),\r\n update: (dt?: number) => c.update(dt),\r\n destroy: () => c.destroy(),\r\n setInput: (i: any) => c.setInput(i),\r\n getPosition: () => c.getPosition(),\r\n getCenterScreenRaycastHit: () => c.getCenterScreenRaycastHit(),\r\n getPerson: () => c.person,\r\n getActiveVehicle: () => c.activeVehicle,\r\n getAllVehicles: () => c.vehicles,\r\n switchPlayerModel: (model: PlayerControllerOptions[\"playerModel\"]) => c.switchPlayerModel(model),\r\n setMouseSensitivity: (mouseSensity: number) => c.setMouseSensitivity(mouseSensity),\r\n setGravity: (gravity: number) => c.setGravity(gravity),\r\n setJumpHeight: (jumpHeight: number) => c.setJumpHeight(jumpHeight),\r\n setPlayerSpeed: (playerSpeed: number) => c.setPlayerSpeed(playerSpeed),\r\n setPlayerFlySpeed: (playerFlySpeed: number) => c.setPlayerFlySpeed(playerFlySpeed),\r\n setMinCamDistance: (minCamDistance: number) => c.setMinCamDistance(minCamDistance),\r\n setMaxCamDistance: (maxCamDistance: number) => c.setMaxCamDistance(maxCamDistance),\r\n setThirdMouseMode: (thirdMouseMode: 0 | 1 | 2 | 3) => c.setThirdMouseMode(thirdMouseMode),\r\n setEnableZoom: (enableZoom: boolean) => c.setEnableZoom(enableZoom),\r\n setDebug: (debug: boolean) => c.setDebug(debug),\r\n setOverShoulderView: (enable: boolean) => c.setOverShoulderView(enable),\r\n setPlayerScale: (scale: number) => c.setPlayerScale(scale),\r\n };\r\n}\r\n\r\nexport type playerController = ReturnType<typeof playerController>;\r\n\r\nexport function onAllEvent(): void {\r\n if (!controllerInstance) controllerInstance = new PlayerController();\r\n controllerInstance.onAllEvent();\r\n}\r\n\r\nexport function offAllEvent(): void {\r\n if (!controllerInstance) return;\r\n controllerInstance.offAllEvent();\r\n}\r\n","import * as THREE from \"three\";\r\n\r\n/**\r\n * 路径规划节点\r\n */\r\nclass PathNode {\r\n position: THREE.Vector3;\r\n g: number = Infinity; // 实际代价\r\n h: number = 0; // 估计代价\r\n f: number = Infinity; // f = g + h\r\n parent: PathNode | null = null;\r\n\r\n constructor(position: THREE.Vector3) {\r\n this.position = position.clone();\r\n }\r\n\r\n equals(other: PathNode): boolean {\r\n return this.position.distanceTo(other.position) < 0.01;\r\n }\r\n}\r\n\r\n/**\r\n * 优先队列(用于A*开放列表)\r\n */\r\nclass PriorityQueue<T> {\r\n private elements: Array<{ priority: number; item: T }> = [];\r\n\r\n enqueue(item: T, priority: number) {\r\n this.elements.push({ priority, item });\r\n this.elements.sort((a, b) => a.priority - b.priority);\r\n }\r\n\r\n dequeue(): T | undefined {\r\n return this.elements.shift()?.item;\r\n }\r\n\r\n isEmpty(): boolean {\r\n return this.elements.length === 0;\r\n }\r\n\r\n contains(item: T, compareFn: (a: T, b: T) => boolean): boolean {\r\n return this.elements.some((e) => compareFn(e.item, item));\r\n }\r\n\r\n update(item: T, newPriority: number, compareFn: (a: T, b: T) => boolean) {\r\n const index = this.elements.findIndex((e) => compareFn(e.item, item));\r\n if (index !== -1) {\r\n this.elements[index].priority = newPriority;\r\n this.elements.sort((a, b) => a.priority - b.priority);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * 障碍物检测接口\r\n */\r\nexport interface ObstacleChecker {\r\n /**\r\n * 检查两点之间的线段是否被障碍物阻挡\r\n */\r\n isBlocked(start: THREE.Vector3, end: THREE.Vector3): boolean;\r\n\r\n /**\r\n * 获取障碍物周围的导航节点\r\n */\r\n getNavigationNodes(start: THREE.Vector3, goal: THREE.Vector3): THREE.Vector3[];\r\n}\r\n\r\n/**\r\n * 路径规划器配置\r\n */\r\nexport interface PathPlannerConfig {\r\n // 路径可视化\r\n debugEnabled?: boolean;\r\n //场景对象(用于可视化)\r\n scene?: THREE.Scene;\r\n //缩放系数\r\n scale?: number;\r\n}\r\n\r\n/**\r\n * A*路径规划器\r\n */\r\nexport class PathPlanner {\r\n private obstacleChecker: ObstacleChecker;\r\n private config: PathPlannerConfig;\r\n private debugLines: THREE.Line[] = [];\r\n private debugPoints: THREE.Mesh[] = [];\r\n\r\n constructor(obstacleChecker: ObstacleChecker, config: PathPlannerConfig = {}) {\r\n this.obstacleChecker = obstacleChecker;\r\n this.config = {\r\n debugEnabled: false,\r\n scale: 1,\r\n ...config,\r\n };\r\n }\r\n\r\n // 计算启发式距离\r\n\r\n private heuristic(a: THREE.Vector3, b: THREE.Vector3): number {\r\n return a.distanceTo(b);\r\n }\r\n\r\n // A*路径规划算法\r\n findPath(start: THREE.Vector3, goal: THREE.Vector3): THREE.Vector3[] {\r\n // console.log(\"开始A*路径规划...\");\r\n const startTime = performance.now();\r\n\r\n // 首先检查直线路径是否可行\r\n if (!this.obstacleChecker.isBlocked(start, goal)) {\r\n // console.log(\"直线路径可行,无需绕行\");\r\n return [goal];\r\n }\r\n\r\n // 生成导航节点\r\n const navigationPoints = this.obstacleChecker.getNavigationNodes(start, goal);\r\n const allNodes = [new PathNode(start), new PathNode(goal), ...navigationPoints.map((p) => new PathNode(p))];\r\n\r\n if (allNodes.length < 2) {\r\n console.warn(\"导航节点不足,返回直线路径\");\r\n return [goal];\r\n }\r\n\r\n const startNode = allNodes[0];\r\n const goalNode = allNodes[1];\r\n\r\n // 初始化起点\r\n startNode.g = 0;\r\n startNode.h = this.heuristic(startNode.position, goalNode.position);\r\n startNode.f = startNode.h;\r\n\r\n // 开放列表和关闭列表\r\n const openList = new PriorityQueue<PathNode>();\r\n const closedSet = new Set<PathNode>();\r\n\r\n openList.enqueue(startNode, startNode.f);\r\n\r\n const nodeEquals = (a: PathNode, b: PathNode) => a.equals(b);\r\n\r\n // A*主循环\r\n while (!openList.isEmpty()) {\r\n const current = openList.dequeue();\r\n if (!current) break;\r\n\r\n // 到达目标\r\n if (current.equals(goalNode)) {\r\n const path = this.reconstructPath(current);\r\n const endTime = performance.now();\r\n // console.log(`A*路径规划完成,耗时: ${(endTime - startTime).toFixed(2)}ms`);\r\n // console.log(`路径点数量: ${path.length}`);\r\n\r\n // 可视化路径\r\n if (this.config.debugEnabled) {\r\n this.visualizePath([start, ...path]);\r\n }\r\n\r\n return path;\r\n }\r\n\r\n closedSet.add(current);\r\n\r\n // 检查所有邻居节点\r\n for (const neighbor of allNodes) {\r\n if (closedSet.has(neighbor)) continue;\r\n\r\n // 检查从当前节点到邻居节点的路径是否被阻挡\r\n if (this.obstacleChecker.isBlocked(current.position, neighbor.position)) {\r\n continue;\r\n }\r\n\r\n // 计算新的g值\r\n const tentativeG = current.g + current.position.distanceTo(neighbor.position);\r\n\r\n // 如果找到更好的路径\r\n if (tentativeG < neighbor.g) {\r\n neighbor.parent = current;\r\n neighbor.g = tentativeG;\r\n neighbor.h = this.heuristic(neighbor.position, goalNode.position);\r\n neighbor.f = neighbor.g + neighbor.h;\r\n\r\n // 更新或添加到开放列表\r\n if (openList.contains(neighbor, nodeEquals)) {\r\n openList.update(neighbor, neighbor.f, nodeEquals);\r\n } else {\r\n openList.enqueue(neighbor, neighbor.f);\r\n }\r\n }\r\n }\r\n }\r\n\r\n console.warn(\"A*未找到路径,使用直线路径\");\r\n return [goal];\r\n }\r\n\r\n /**\r\n * 重建路径\r\n */\r\n private reconstructPath(endNode: PathNode): THREE.Vector3[] {\r\n const path: THREE.Vector3[] = [];\r\n let current: PathNode | null = endNode;\r\n\r\n while (current !== null) {\r\n path.unshift(current.position.clone());\r\n current = current.parent;\r\n }\r\n\r\n // 移除起点\r\n if (path.length > 0) {\r\n path.shift();\r\n }\r\n\r\n // 路径平滑优化\r\n return this.smoothPath(path);\r\n }\r\n\r\n /**\r\n * 路径平滑\r\n */\r\n private smoothPath(path: THREE.Vector3[]): THREE.Vector3[] {\r\n if (path.length <= 2) return path;\r\n\r\n const smoothed: THREE.Vector3[] = [path[0]];\r\n let current = 0;\r\n\r\n while (current < path.length - 1) {\r\n // 尝试跳过中间点\r\n let farthest = current + 1;\r\n\r\n for (let i = path.length - 1; i > current + 1; i--) {\r\n if (!this.obstacleChecker.isBlocked(path[current], path[i])) {\r\n farthest = i;\r\n break;\r\n }\r\n }\r\n\r\n smoothed.push(path[farthest]);\r\n current = farthest;\r\n }\r\n\r\n return smoothed;\r\n }\r\n\r\n /**\r\n * 可视化路径\r\n */\r\n private visualizePath(path: THREE.Vector3[]) {\r\n if (!this.config.scene || !this.config.debugEnabled) return;\r\n\r\n // 清除之前的可视化\r\n this.clearVisualization();\r\n\r\n const scale = this.config.scale || 1;\r\n\r\n // 绘制路径线\r\n if (path.length > 1) {\r\n const points = path.map((p) => p.clone());\r\n const geometry = new THREE.BufferGeometry().setFromPoints(points);\r\n const material = new THREE.LineBasicMaterial({\r\n color: 0x00ff00,\r\n linewidth: 3,\r\n });\r\n const line = new THREE.Line(geometry, material);\r\n this.config.scene.add(line);\r\n this.debugLines.push(line);\r\n }\r\n\r\n // 绘制路径点\r\n path.forEach((point, index) => {\r\n const geometry = new THREE.SphereGeometry(20 * scale);\r\n const material = new THREE.MeshBasicMaterial({\r\n color: index === path.length - 1 ? 0xff0000 : 0x00ff00,\r\n });\r\n const sphere = new THREE.Mesh(geometry, material);\r\n sphere.position.copy(point);\r\n this.config.scene!.add(sphere);\r\n this.debugPoints.push(sphere);\r\n });\r\n }\r\n\r\n /**\r\n * 清除路径可视化\r\n */\r\n clearVisualization() {\r\n if (!this.config.scene) return;\r\n\r\n this.debugLines.forEach((line) => {\r\n this.config.scene!.remove(line);\r\n line.geometry.dispose();\r\n (line.material as THREE.Material).dispose();\r\n });\r\n this.debugLines = [];\r\n\r\n this.debugPoints.forEach((point) => {\r\n this.config.scene!.remove(point);\r\n point.geometry.dispose();\r\n (point.material as THREE.Material).dispose();\r\n });\r\n this.debugPoints = [];\r\n }\r\n\r\n /**\r\n * 更新配置\r\n */\r\n updateConfig(config: Partial<PathPlannerConfig>) {\r\n this.config = { ...this.config, ...config };\r\n }\r\n\r\n /**\r\n * 销毁\r\n */\r\n dispose() {\r\n this.clearVisualization();\r\n }\r\n}\r\n","import type { World } from \"@dimforge/rapier3d-compat\";\r\nimport * as THREE from \"three\";\r\n\r\nexport type WheelInfo = {\r\n axleCs: THREE.Vector3;\r\n suspensionRestLength: number;\r\n position: THREE.Vector3;\r\n radius: number;\r\n};\r\n\r\nexport function createVehicleController(world: World, chassisBody: any, wheels: (THREE.Object3D | null)[], wheelsInfo: WheelInfo[]) {\r\n if (!world || !chassisBody) return { vehicle: null, updateWheelVisuals: () => {} };\r\n\r\n const vehicle = world.createVehicleController(chassisBody);\r\n const suspensionDirection = new THREE.Vector3(0, -1, 0);\r\n wheelsInfo.forEach((wheel, index) => {\r\n vehicle.addWheel(wheel.position, suspensionDirection, wheel.axleCs, wheel.suspensionRestLength, wheel.radius);\r\n // 轮子相对车身的连接点\r\n vehicle.setWheelChassisConnectionPointCs(index, wheel.position);\r\n // 悬挂方向\r\n vehicle.setWheelDirectionCs(index, suspensionDirection);\r\n // 轮轴方向\r\n vehicle.setWheelAxleCs(index, wheel.axleCs);\r\n // 悬挂静止长度\r\n vehicle.setWheelSuspensionRestLength(index, wheel.suspensionRestLength);\r\n // 轮胎半径\r\n vehicle.setWheelRadius(index, wheel.radius);\r\n // 悬挂最大行程\r\n vehicle.setWheelMaxSuspensionTravel(index, wheel.suspensionRestLength * 1);\r\n // 悬挂刚度\r\n vehicle.setWheelSuspensionStiffness(index, 250);\r\n // 悬挂压缩阻尼\r\n vehicle.setWheelSuspensionCompression(index, 6);\r\n // 悬挂回弹阻尼\r\n vehicle.setWheelSuspensionRelaxation(index, 6);\r\n // 悬挂最大作用力\r\n vehicle.setWheelMaxSuspensionForce(index, 10000);\r\n // 制动\r\n vehicle.setWheelBrake(index, 0);\r\n // 转向角\r\n vehicle.setWheelSteering(index, 0);\r\n // 发动机驱动力\r\n vehicle.setWheelEngineForce(index, 0);\r\n // 纵向抓地参数\r\n vehicle.setWheelFrictionSlip(index, 20);\r\n // 侧向摩擦刚度倍率\r\n vehicle.setWheelSideFrictionStiffness(index, 2);\r\n });\r\n\r\n const up = new THREE.Vector3(0, 1, 0);\r\n const _wheelSteeringQuat = new THREE.Quaternion();\r\n const _wheelRotationQuat = new THREE.Quaternion();\r\n\r\n function updateWheelVisuals() {\r\n for (const [index, wheelObj] of wheels.entries()) {\r\n if (!wheelObj) continue;\r\n try {\r\n const wheelAxleCs = vehicle.wheelAxleCs(index) ?? new THREE.Vector3(1, 0, 0);\r\n const connection = vehicle.wheelChassisConnectionPointCs(index)?.y ?? 0;\r\n const suspension = vehicle.wheelSuspensionLength(index) ?? 0;\r\n const steering = vehicle.wheelSteering(index) ?? 0;\r\n const rotationRad = vehicle.wheelRotation(index) ?? 0;\r\n\r\n wheelObj.position.y = connection - suspension;\r\n\r\n _wheelSteeringQuat.setFromAxisAngle(up, steering);\r\n _wheelRotationQuat.setFromAxisAngle(wheelAxleCs, rotationRad);\r\n\r\n wheelObj.quaternion.copy(_wheelSteeringQuat).multiply(_wheelRotationQuat);\r\n } catch (e) {}\r\n }\r\n }\r\n\r\n function destroy() {\r\n try {\r\n world.removeVehicleController(vehicle);\r\n } catch {}\r\n }\r\n\r\n return {\r\n vehicle: vehicle,\r\n updateWheelVisuals,\r\n destroy,\r\n };\r\n}\r\n"],"mappings":"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","names":["THREE","THREE","v","attrNames"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/playerController.ts","../src/utils/mobileControls.ts","../src/utils/vehicleLoader.ts","../src/utils/pathPlanner.ts","../src/utils/useVehicleController.ts"],"sourcesContent":["export * from \"./playerController\";\r\n","import * as THREE from \"three\";\nimport { acceleratedRaycast, MeshBVH, MeshBVHHelper } from \"three-mesh-bvh\";\nimport type { GLTF } from \"three/examples/jsm/Addons.js\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\nimport { RoundedBoxGeometry } from \"three/examples/jsm/geometries/RoundedBoxGeometry.js\";\nimport { DRACOLoader } from \"three/examples/jsm/loaders/DRACOLoader.js\";\nimport { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport * as BufferGeometryUtils from \"three/examples/jsm/utils/BufferGeometryUtils.js\";\nimport type { World } from \"@dimforge/rapier3d-compat\";\n\nimport { MobileControls } from \"./utils/mobileControls\";\nimport { loadVehicleModel } from \"./utils/vehicleLoader\";\nimport type { PlayerControllerOptions, PlayerModelOptions, VehicleOptions, VehicleInstance } from \"./types\";\n\nTHREE.Mesh.prototype.raycast = acceleratedRaycast;\n\nlet controllerInstance: PlayerController | null = null;\nconst clock = new THREE.Clock();\n\nfunction isMobileDevice() {\n return /Android|iPhone|iPad|iPod|Mobile/i.test(navigator.userAgent);\n}\n\nclass PlayerController {\n\n // ==================== 场景引用 ====================\n loader: GLTFLoader = new GLTFLoader();\n scene!: THREE.Scene;\n camera!: THREE.PerspectiveCamera;\n controls!: OrbitControls;\n\n // ==================== 玩家配置 ====================\n // 基础引用(由 init 注入)\n playerModel!: PlayerModelOptions;\n initPos!: THREE.Vector3;\n // 物理参数\n gravity: number = -2400;\n jumpHeight: number = 600;\n playerSpeed: number = 300;\n playerFlySpeed: number = 2100;\n curPlayerSpeed: number = 0;\n // 交互参数\n mouseSensitivity: number = 5;\n thirdMouseMode: 0 | 1 | 2 | 3 = 1;\n enableZoom: boolean = false;\n playerFlyEnabled: boolean = true;\n isShowMobileControls: boolean = true;\n enableOverShoulderView: boolean = false;\n\n // ==================== 玩家胶囊体 ====================\n playerCapsuleRadius: number = 45;\n playerCapsuleHeight: number = 180;\n playerCapsuleRadiusRatio: number = 1;\n isFirstPerson: boolean = false;\n boundingBoxMinY: number = 0;\n\n // ==================== 运行状态 ====================\n controllerMode: 0 | 1 = 0; // 0:人物 1:车辆\n playerIsOnGround: boolean = false;\n isupdate: boolean = true;\n isFlying: boolean = false;\n isChangeControllerTransitionTimer: any = null;\n\n // ==================== 输入按键 ====================\n fwdPressed: boolean = false;\n bkdPressed: boolean = false;\n lftPressed: boolean = false;\n rgtPressed: boolean = false;\n spacePressed: boolean = false;\n ctPressed: boolean = false;\n shiftPressed: boolean = false;\n\n // ==================== 相机参数 ====================\n camCollisionLerp: number = 0.18;\n camEpsilon: number = 35;\n minCamDistance: number = 100;\n maxCamDistance: number = 440;\n orginMaxCamDistance: number = 440;\n\n // ==================== 场景碰撞体 ====================\n collider: THREE.Mesh | null = null;\n visualizer: MeshBVHHelper | null = null;\n player!: THREE.Mesh & { capsuleInfo?: any };\n person: THREE.Object3D | null = null;\n personHead: THREE.Object3D | null = null;\n collected: THREE.BufferGeometry[] = [];\n dynamicCollider: THREE.Mesh | null = null;\n dynamicCollected: THREE.BufferGeometry[] = [];\n\n // ==================== 车辆系统 ====================\n vehicles: VehicleInstance[] = [];\n activeVehicle: VehicleInstance | null = null;\n vehicleLength: number = 6;\n RAPIER: any | null = null;\n world: World | null = null;\n wheelSteeringQuat = new THREE.Quaternion();\n wheelRotationQuat = new THREE.Quaternion();\n camBehindDir = new THREE.Vector3(0, 0, 1);\n vehicleParams = {\n debug: { showPhysicsBox: false },\n chassis: { linearDamping: 0.5, angularDamping: 0.5 },\n model: { rotation: -Math.PI / 2 },\n power: { accelerateForce: 50, brakeForce: 200, maxSpeed: 10000 },\n steering: { maxSteerAngle: Math.PI / 4, steerSpeed: 0.5, steerReturnSpeed: 1 },\n followVehicleDirection: true,\n };\n\n // ==================== 上车流程 ====================\n isMovingToBoardingPoint: boolean = false;\n boardingWaypoints: THREE.Vector3[] = [];\n currentWaypointIndex: number = 0;\n boardingTargetDir: THREE.Vector3 | null = null;\n boardingMoveSpeed: number = 300;\n boardingRotateSpeed: number = 10;\n boardingPointWorld: THREE.Vector3 | null = null;\n isBoardingAnimPlaying: boolean = false;\n closeDoorTriggered: boolean = false;\n isExitAnimPlaying: boolean = false;\n closeExitDoorTriggered: boolean = false;\n closeVehicleDoorTimer: any | null = null;\n flip180Quat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), Math.PI);\n\n // ==================== 动画系统 ====================\n personMixer?: THREE.AnimationMixer;\n personActions?: Map<string, THREE.AnimationAction>;\n actionState!: THREE.AnimationAction;\n recheckAnimTimer: any | null = null;\n allAnimations: THREE.AnimationClip[] = [];\n\n // ==================== 移动端控制 ====================\n mobileControls: MobileControls | null = null;\n nearCheckLocal = new THREE.Vector3();\n nearCheckWorld = new THREE.Vector3();\n isNearVehicle = false;\n\n // ==================== 调试显示 ====================\n displayPlayer: boolean = false;\n displayCollider: boolean = false;\n displayVisualizer: boolean = false;\n\n // ==================== 方向常量 ====================\n rotationSpeed = 10;\n DIR_FWD = new THREE.Vector3(0, 0, -1);\n DIR_BKD = new THREE.Vector3(0, 0, 1);\n DIR_LFT = new THREE.Vector3(-1, 0, 0);\n DIR_RGT = new THREE.Vector3(1, 0, 0);\n DIR_UP = new THREE.Vector3(0, 1, 0);\n\n // ==================== 复用向量 ====================\n upVector = new THREE.Vector3(0, 1, 0);\n playerVelocity = new THREE.Vector3();\n camDir = new THREE.Vector3();\n moveDir = new THREE.Vector3();\n targetQuat = new THREE.Quaternion();\n targetMat = new THREE.Matrix4();\n tempVector = new THREE.Vector3();\n tempVector2 = new THREE.Vector3();\n tempBox = new THREE.Box3();\n tempMat = new THREE.Matrix4();\n tempSegment = new THREE.Line3();\n\n // ==================== 射线检测 ====================\n personToCam = new THREE.Vector3();\n originTmp = new THREE.Vector3();\n raycaster = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3(0, -1, 0));\n raycasterPersonToCam = new THREE.Raycaster(new THREE.Vector3(), new THREE.Vector3());\n centerRay = new THREE.Raycaster();\n centerMouse = new THREE.Vector2();\n\n constructor() {\n (this.raycaster as any).firstHitOnly = true;\n (this.raycasterPersonToCam as any).firstHitOnly = true;\n }\n\n // ==================== 初始化 ====================\n\n // 初始化控制器\n async init(opts: PlayerControllerOptions, callback?: () => void) {\n const m = opts.playerModel;\n const s = m.scale ?? 1;\n\n // 场景引用赋值\n this.scene = opts.scene;\n this.camera = opts.camera;\n this.camera.rotation.order = \"YXZ\";\n this.controls = opts.controls;\n\n // 玩家模型配置\n this.playerModel = m;\n this.initPos = opts.initPos\n ? new THREE.Vector3(opts.initPos.x, opts.initPos.y, opts.initPos.z)\n : new THREE.Vector3(0, 0, 0);\n\n // 物理运行时值 传入值/字段默认值 * scale\n const pm = this.playerModel;\n this.gravity = (pm.gravity ?? this.gravity) * s;\n this.jumpHeight = (pm.jumpHeight ?? this.jumpHeight) * s;\n this.playerSpeed = (pm.speed ?? this.playerSpeed) * s;\n this.playerFlySpeed = (pm.flySpeed ?? this.playerFlySpeed) * s;\n this.curPlayerSpeed = this.playerSpeed;\n this.playerFlyEnabled = pm.flyEnabled ?? this.playerFlyEnabled;\n this.playerCapsuleRadiusRatio = pm.capsuleRadiusRatio ?? this.playerCapsuleRadiusRatio;\n\n // 相机参数\n this.mouseSensitivity = opts.mouseSensitivity ?? this.mouseSensitivity;\n this.thirdMouseMode = opts.thirdMouseMode ?? this.thirdMouseMode;\n this.enableZoom = opts.enableZoom ?? this.enableZoom;\n this.minCamDistance = (opts.minCamDistance ?? this.minCamDistance) * s;\n this.maxCamDistance = (opts.maxCamDistance ?? this.maxCamDistance) * s;\n this.orginMaxCamDistance = this.maxCamDistance;\n this.camEpsilon = this.camEpsilon * s;\n\n // UI 参数\n this.isShowMobileControls = (opts.isShowMobileControls ?? this.isShowMobileControls) && isMobileDevice();\n this.enableOverShoulderView = opts.enableOverShoulderView ?? this.enableOverShoulderView;\n\n // 移动端控制\n if (this.isShowMobileControls) {\n this.mobileControls = new MobileControls(i => this.setInput(i), this.controls);\n await this.mobileControls.init();\n }\n\n await this.createBVH(opts.colliderMeshUrl);\n await this.loadPersonGLB();\n\n this.onAllEvent();\n this.setCameraPos();\n this.setControls();\n this.setOverShoulderView(this.enableOverShoulderView);\n callback?.();\n }\n\n // 过肩视角切换\n setOverShoulderView(enable: boolean) {\n if (!enable || this.controllerMode === 1) { this.camera.clearViewOffset(); return; }\n const w = window.innerWidth;\n const h = window.innerHeight;\n this.camera.setViewOffset(w, h, -w * -0.15, 0, w, h);\n }\n\n // 初始化加载器\n async initLoader() {\n const dracoLoader = new DRACOLoader();\n dracoLoader.setDecoderPath(\"https://unpkg.com/three@0.180.0/examples/jsm/libs/draco/gltf/\");\n dracoLoader.setDecoderConfig({ type: \"js\" });\n this.loader.setDRACOLoader(dracoLoader);\n }\n\n // 初始化物理引擎\n async initRapier() {\n if (this.RAPIER) return;\n this.RAPIER = await import(\"@dimforge/rapier3d-compat\");\n await this.RAPIER.init();\n\n this.world = new this.RAPIER.World(new this.RAPIER.Vector3(0, -9.81, 0)) as World;\n (this.world as any).maxCcdSubsteps = 2;\n\n const addTrimesh = (RAPIER: any, world: any, geom: THREE.BufferGeometry) => {\n let g = geom.index ? geom.clone().toNonIndexed() : geom.clone();\n const pos = g.attributes.position;\n const count = pos.count;\n const verts = new Float32Array(count * 3);\n const tmp = new THREE.Vector3();\n for (let i = 0; i < count; i++) {\n tmp.fromBufferAttribute(pos, i);\n verts[i * 3] = tmp.x; verts[i * 3 + 1] = tmp.y; verts[i * 3 + 2] = tmp.z;\n }\n const indices = count > 65535 ? new Uint32Array(count) : new Uint16Array(count);\n for (let i = 0; i < count; i++) indices[i] = i;\n\n const body = world.createRigidBody(RAPIER.RigidBodyDesc.fixed());\n world.createCollider(\n RAPIER.ColliderDesc.trimesh(verts, indices).setRestitution(0).setFriction(0.8),\n body,\n );\n };\n\n for (const g of this.collected) addTrimesh(this.RAPIER, this.world, g);\n\n const groundBody = this.world.createRigidBody(this.RAPIER.RigidBodyDesc.fixed());\n groundBody.userData = { outOfBounds: true };\n }\n\n // ==================== 玩家模型 ====================\n\n // 加载玩家模型\n async loadPersonGLB() {\n try {\n const gltf = await this.loader.loadAsync(this.playerModel.url) as GLTF;\n this.person = gltf.scene;\n\n // 绑定动画\n this.personMixer = new THREE.AnimationMixer(this.person);\n const animations = gltf.animations ?? [];\n // console.log('animations', animations)\n this.allAnimations = animations;\n this.personActions = new Map();\n\n const mappings: [string, string][] = [\n [this.playerModel.idleAnim, \"idle\"],\n [this.playerModel.walkAnim, \"walking\"],\n [this.playerModel.leftWalkAnim || this.playerModel.walkAnim, \"left_walking\"],\n [this.playerModel.rightWalkAnim || this.playerModel.walkAnim, \"right_walking\"],\n [this.playerModel.backwardAnim || this.playerModel.walkAnim, \"walking_backward\"],\n [this.playerModel.jumpAnim, \"jumping\"],\n [this.playerModel.runAnim, \"running\"],\n [this.playerModel.flyIdleAnim || this.playerModel.idleAnim, \"flyidle\"],\n [this.playerModel.flyAnim || this.playerModel.idleAnim, \"flying\"],\n [this.playerModel.enterCarAnim || this.playerModel.idleAnim, \"enterCar\"],\n [this.playerModel.exitCarAnim || this.playerModel.idleAnim, \"exitCar\"],\n ];\n\n for (const [clipName, actionName] of mappings) {\n const clip = animations.find(a => a.name === clipName);\n if (!clip) continue;\n const action = this.personMixer.clipAction(clip);\n if (actionName === \"jumping\") {\n action.setLoop(THREE.LoopOnce, 1);\n action.clampWhenFinished = true;\n action.setEffectiveTimeScale(1.2);\n } else {\n action.setLoop(THREE.LoopRepeat, Infinity);\n action.setEffectiveTimeScale(1);\n }\n action.enabled = true;\n action.setEffectiveWeight(0);\n this.personActions.set(actionName, action);\n }\n\n // 执行idle动画\n this.personActions.get(\"idle\").setEffectiveWeight(1);\n this.personActions.get(\"idle\").play();\n this.actionState = this.personActions.get(\"idle\");\n\n // 动画结束回调\n this.personMixer.addEventListener(\"finished\", (ev: any) => {\n const done: THREE.AnimationAction = ev.action;\n if (done === this.personActions.get(\"jumping\")) {\n if (this.fwdPressed) { this.playPersonAnimationByName(this.shiftPressed ? \"running\" : \"walking\"); return; }\n if (this.bkdPressed) { this.playPersonAnimationByName(\"walking_backward\"); return; }\n if (this.rgtPressed || this.lftPressed) { this.playPersonAnimationByName(\"walking\"); return; }\n this.playPersonAnimationByName(\"idle\");\n }\n if (done === this.personActions?.get(\"enterCar\")) this.onEnterCarAnimFinished();\n });\n\n // 步进到第一帧,让骨骼更新到idle姿态\n this.personMixer.update(0);\n // 强制更新世界矩阵\n this.person.updateMatrixWorld(true);\n\n // 计算胶囊体尺寸\n const { size } = this.getBbox(this.person);\n const modelScale = this.playerCapsuleHeight / size.y;\n this.playerCapsuleRadius = Number(Math.min(size.x, size.z).toFixed(0)) * modelScale * this.playerCapsuleRadiusRatio;\n this.playerCapsuleHeight = Number(size.y.toFixed(0)) * modelScale;\n\n const s = this.playerModel.scale;\n const r = this.playerCapsuleRadius * s;\n const h = this.playerCapsuleHeight * s;\n\n // 创建碰撞胶囊体\n this.player = new THREE.Mesh(\n new RoundedBoxGeometry(r * 2, h, r * 2, 1, 75),\n new THREE.MeshStandardMaterial({\n color: new THREE.Color(1, 0, 0),\n shadowSide: THREE.DoubleSide,\n depthTest: false, transparent: true,\n opacity: this.displayPlayer ? 0.5 : 0,\n wireframe: true, depthWrite: false,\n }),\n );\n this.player.geometry.translate(0, -h * 0.25, 0);\n this.player.capsuleInfo = {\n radius: r,\n segment: new THREE.Line3(new THREE.Vector3(), new THREE.Vector3(0, -h * 0.5, 0)),\n };\n this.player.name = \"capsule\";\n this.scene.add(this.player);\n this.reset();\n this.player.rotateY(this.playerModel.rotateY ?? 0);\n\n // 摆放视觉模型\n this.person.scale.multiplyScalar(modelScale * s);\n this.person.position.set(0, -h * 0.75, 0);\n this.person.traverse((child: any) => {\n if (child.name === this.playerModel?.headObjName) this.personHead = child;\n });\n this.player.add(this.person);\n this.reset();\n\n\n } catch (e) {\n console.error(\"加载玩家模型失败:\", e);\n }\n }\n\n // 切换玩家模型\n async switchPlayerModel(newPlayerModel: PlayerModelOptions) {\n const savedPos = this.player.position.clone();\n const savedQuat = this.player.quaternion.clone();\n const wasFirstPerson = this.isFirstPerson;\n\n // 清理旧模型\n if (wasFirstPerson) this.scene.attach(this.camera);\n if (this.player) this.scene.remove(this.player);\n if (this.person) { this.player.remove(this.person); this.person = null; this.personHead = null; }\n\n if (this.personMixer) {\n this.personMixer.stopAllAction();\n this.personMixer.uncacheRoot(this.personMixer.getRoot());\n this.personMixer = undefined;\n this.personActions = undefined;\n }\n\n // 等比缩放物理参数\n const ratio = newPlayerModel.scale / this.playerModel.scale;\n this.playerModel = { ...this.playerModel, ...newPlayerModel };\n\n this.gravity *= ratio;\n this.jumpHeight *= ratio;\n this.playerSpeed *= ratio;\n this.playerFlySpeed *= ratio;\n this.curPlayerSpeed *= ratio;\n this.camEpsilon *= ratio;\n this.minCamDistance *= ratio;\n this.maxCamDistance *= ratio;\n this.orginMaxCamDistance *= ratio;\n\n // 重新加载\n await this.loadPersonGLB();\n this.player.position.copy(savedPos);\n this.player.quaternion.copy(savedQuat);\n if (wasFirstPerson) this.setFirstPersonCamera();\n this.setDebug(this.displayCollider);\n }\n\n // 播放动画\n playPersonAnimationByName(name: string, fade = 0.18) {\n if (!this.personActions || this.ctPressed) return;\n const next = this.personActions.get(name);\n if (!next || this.actionState === next) return;\n\n const prev = this.actionState;\n next.reset();\n next.setEffectiveWeight(1);\n\n // 上下车动画单次播放\n if (name === \"enterCar\" || name === \"exitCar\") {\n const duration = next.getClip().duration;\n const enterTime = this.activeVehicle?.enterVehicleTime ?? 1.5;\n next.setEffectiveTimeScale(duration / enterTime);\n next.setLoop(THREE.LoopOnce, 1);\n next.clampWhenFinished = true;\n }\n\n next.play();\n if (prev && prev !== next) { prev.fadeOut(fade); next.fadeIn(fade); }\n else next.fadeIn(fade);\n\n this.actionState = next;\n }\n\n // 注册自定义动画\n registerAnimation(key: string, clipName: string, opts?: {\n loop?: boolean;\n timeScale?: number;\n duration?: number;\n clampWhenFinished?: boolean;\n onFinished?: () => void; // 播完回调\n }) {\n if (!this.personMixer || !this.personActions) return;\n\n const mixer = this.personMixer;\n const clip = this.allAnimations.find(c => c.name === clipName);\n if (!clip) { console.warn(`找不到 \"${clipName}\" 动画`); return; }\n\n const action = mixer.clipAction(clip);\n\n const timeScale = opts?.duration\n ? clip.duration / opts.duration\n : (opts?.timeScale ?? 1);\n action.setLoop(opts?.loop === false ? THREE.LoopOnce : THREE.LoopRepeat, Infinity);\n action.clampWhenFinished = opts?.clampWhenFinished ?? false;\n action.setEffectiveTimeScale(timeScale);\n action.enabled = true;\n action.setEffectiveWeight(0);\n\n this.personActions.set(key, action);\n\n // 注册回调\n if (opts?.onFinished) {\n this.personMixer.addEventListener(\"finished\", (ev: any) => {\n if (ev.action === action) opts.onFinished!();\n });\n }\n }\n\n // 外部播放动画\n playAnimation(key: string, opts?: {\n fade?: number; // 过渡时间\n force?: boolean; // 强制重置重播\n }) {\n if (!this.personActions) return;\n if (!this.personActions.has(key)) {\n console.warn(`playAnimation: \"${key}\" 未注册`); return;\n }\n if (opts?.force) {\n const action = this.personActions.get(key)!;\n action.reset();\n }\n this.playPersonAnimationByName(key, opts?.fade ?? 0.18);\n }\n\n // ==================== 车辆 ====================\n\n // 加载车辆模型\n async loadVehicleModel(opts: VehicleOptions) {\n try {\n if (!this.playerModel.enterCarAnim) {\n return console.warn(\"未配置上车动画,不执行车辆相关逻辑\");\n }\n await this.initRapier();\n if (!this.world) return;\n\n const instance = await loadVehicleModel(opts, {\n loader: this.loader,\n scene: this.scene,\n world: this.world,\n RAPIER: this.RAPIER,\n vehicleParams: this.vehicleParams,\n vehicleLength: this.vehicleLength,\n playerScale: this.playerModel.scale,\n });\n\n this.vehicles.push(instance);\n this.setControllerTransition();\n } catch (e) {\n console.error(\"加载车辆模型失败:\", e);\n }\n }\n\n // 获取包围盒\n getBbox(object: THREE.Object3D) {\n const bbox = new THREE.Box3().setFromObject(object);\n const center = new THREE.Vector3();\n const size = new THREE.Vector3();\n bbox.getCenter(center);\n bbox.getSize(size);\n return { bbox, center, size };\n }\n\n // 开关车门动画\n openVehicleDoor(isOpen = true) {\n const v = this.activeVehicle;\n if (!v?.vehicleActions) return;\n const next = v.vehicleActions.get(\"openDoor\");\n if (!next) return;\n\n const duration = next.getClip().duration;\n next.reset();\n next.setEffectiveWeight(1);\n\n if (isOpen) {\n next.setEffectiveTimeScale(duration * 2);\n next.time = 0;\n v.vehiclIsOpenDoor = true;\n } else {\n next.setEffectiveTimeScale(-duration * 2);\n next.time = duration;\n v.vehiclIsOpenDoor = false;\n }\n\n next.setLoop(THREE.LoopOnce, 1);\n next.clampWhenFinished = true;\n next.play();\n }\n\n // 触发上车流程\n enterVehicle() {\n if (!this.vehicles.length || this.isMovingToBoardingPoint) return;\n\n // 寻找最近可上车辆\n let nearestVehicle: VehicleInstance | null = null;\n let nearestDist = Infinity;\n let nearBoardingPointWorld: THREE.Vector3 | null = null;\n\n for (const v of this.vehicles) {\n const boardingLocal = v.boardingPoint.clone().multiplyScalar(v.scale);\n const boardingWorld = v.vehicleGroup.localToWorld(boardingLocal);\n const dist = this.player.position.distanceTo(boardingWorld);\n if (dist < 800 * this.playerModel.scale && dist < nearestDist) {\n nearestDist = dist;\n nearestVehicle = v;\n nearBoardingPointWorld = boardingWorld;\n }\n }\n\n if (!nearestVehicle || !nearBoardingPointWorld) return;\n\n this.activeVehicle = nearestVehicle;\n const v = nearestVehicle;\n const vel = v.chassisBody.linvel();\n if (Math.sqrt(vel.x ** 2 + vel.z ** 2) > 0.1) return;\n\n // 启动寻路\n this.boardingPointWorld = nearBoardingPointWorld;\n this.boardingWaypoints = v.pathPlanner.findPath(this.player.position.clone(), nearBoardingPointWorld);\n this.currentWaypointIndex = 0;\n this.boardingTargetDir = new THREE.Vector3(0, 0, 1).applyQuaternion(v.vehicleGroup.quaternion).normalize();\n this.isMovingToBoardingPoint = true;\n this.playPersonAnimationByName(\"walking\");\n }\n\n // 寻路移动到上车点\n updateMoveToBoardingPoint(delta: number) {\n if (!this.isMovingToBoardingPoint || !this.boardingTargetDir || !this.boardingWaypoints.length) return;\n\n if (this.currentWaypointIndex >= this.boardingWaypoints.length) {\n this.finalizeBoarding(delta);\n return;\n }\n\n const waypoint = this.boardingWaypoints[this.currentWaypointIndex];\n const currentPos = this.player.position.clone();\n const isLast = this.currentWaypointIndex === this.boardingWaypoints.length - 1;\n const threshold = isLast ? 0 : 10 * this.playerModel.scale;\n const horizDist = new THREE.Vector2(waypoint.x - currentPos.x, waypoint.z - currentPos.z).length();\n\n if (horizDist > threshold) {\n const moveDir = new THREE.Vector3(waypoint.x - currentPos.x, 0, waypoint.z - currentPos.z).normalize();\n this.player.position.add(moveDir.clone().multiplyScalar(Math.min(this.boardingMoveSpeed * this.playerModel.scale * delta, horizDist)));\n this.targetMat.lookAt(this.player.position, this.player.position.clone().add(moveDir), this.player.up);\n this.targetQuat.setFromRotationMatrix(this.targetMat).multiply(this.flip180Quat);\n this.player.quaternion.slerp(this.targetQuat, Math.min(1, this.boardingRotateSpeed * delta));\n } else {\n this.currentWaypointIndex++;\n }\n }\n\n // 最终对齐朝向\n finalizeBoarding(delta: number) {\n const v = this.activeVehicle;\n if (!this.boardingTargetDir || !v || !this.isMovingToBoardingPoint) return;\n\n const currentDir = new THREE.Vector3(0, 0, -1).applyQuaternion(this.player.quaternion).normalize();\n if (currentDir.angleTo(this.boardingTargetDir) > 0.01) {\n // 持续旋转对齐\n const lookTarget = this.player.position.clone().add(this.boardingTargetDir);\n this.targetMat.lookAt(this.player.position, lookTarget, this.player.up);\n this.targetQuat.setFromRotationMatrix(this.targetMat);\n this.player.quaternion.slerp(this.targetQuat, Math.min(1, this.boardingRotateSpeed * delta));\n } else {\n // 对齐完成,播放上车动画\n this.boardingWaypoints = [];\n this.currentWaypointIndex = 0;\n this.boardingTargetDir = null;\n v.pathPlanner?.clearVisualization();\n\n this.playPersonAnimationByName(\"enterCar\");\n this.isBoardingAnimPlaying = true;\n this.closeDoorTriggered = false;\n if (!v.vehiclIsOpenDoor) this.openVehicleDoor();\n this.player.rotation.copy(v.vehicleGroup.rotation);\n this.player.quaternion.multiply(this.flip180Quat);\n }\n }\n\n // 上车动画完成\n onEnterCarAnimFinished() {\n const v = this.activeVehicle;\n if (!v || !this.isMovingToBoardingPoint) return;\n this.player.updateMatrixWorld(true);\n const offsetY = this.boardingPointWorld!.y - this.player.position.y;\n this.controllerMode = 1;\n this.syncMobileControllerMode();\n this.setOverShoulderView(false);\n v.vehicleGroup.attach(this.player);\n this.player.position.add(v.seatOffset.clone().multiplyScalar(v.scale).add(new THREE.Vector3(0, offsetY, 0)));\n this.isMovingToBoardingPoint = false;\n }\n\n // 触发下车流程\n exitVehicle() {\n const v = this.activeVehicle;\n if (!v) return;\n\n // 重置上车状态\n this.isMovingToBoardingPoint = false;\n this.boardingWaypoints = [];\n this.currentWaypointIndex = 0;\n this.boardingTargetDir = null;\n\n // 播放下车动画\n const vel = v.chassisBody.linvel();\n if (Math.sqrt(vel.x ** 2 + vel.z ** 2) < 0.1) {\n this.playPersonAnimationByName(\"exitCar\");\n this.isExitAnimPlaying = true;\n this.closeExitDoorTriggered = false;\n } else {\n this.playPersonAnimationByName(\"idle\");\n }\n\n this.openVehicleDoor(true);\n this.controllerMode = 0;\n this.syncMobileControllerMode();\n this.setOverShoulderView(this.enableOverShoulderView);\n this.scene.attach(this.player);\n if (this.isFirstPerson) this.setFirstPersonCamera();\n this.setControllerTransition();\n }\n\n // ==================== 相机与视角 ====================\n\n // 切换第一/三人称\n changeView() {\n this.isFirstPerson = !this.isFirstPerson;\n if (this.isFirstPerson) {\n // 读取相机当前世界朝向,对齐到第一人称控制轴\n const camWorldDir = new THREE.Vector3();\n this.camera.getWorldDirection(camWorldDir);\n\n // 水平分量\n const flatDir = new THREE.Vector3(camWorldDir.x, 0, camWorldDir.z).normalize();\n if (flatDir.lengthSq() > 0.001) {\n const yAngle = Math.atan2(flatDir.x, flatDir.z);\n this.player.rotation.set(0, yAngle + Math.PI, 0);\n }\n // 垂直分量\n const vertAngle = Math.asin(THREE.MathUtils.clamp(-camWorldDir.y, -1, 1));\n\n this.setFirstPersonCamera(vertAngle);\n this.setOverShoulderView(false);\n } else {\n this.controls.enabled = true;\n this.scene.attach(this.camera);\n const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(this.player.quaternion);\n const angle = Math.atan2(dir.z, dir.x);\n const s = this.playerModel.scale;\n this.camera.position.copy(this.player.position).add(new THREE.Vector3(Math.cos(angle) * 400 * s, 200 * s, Math.sin(angle) * 400 * s));\n this.controls.target.copy(this.player.position);\n this.controls.enableZoom = this.enableZoom;\n this.setOverShoulderView(this.enableOverShoulderView);\n }\n this.setPointerLock();\n }\n\n // 设置第一人称相机\n setFirstPersonCamera(vertAngle = 0) {\n this.controls.enabled = false;\n if (this.personHead) {\n this.personHead.attach(this.camera);\n this.camera.position.set(0, 10, 20);\n } else {\n this.player.attach(this.camera);\n this.camera.position.set(0, 40 * this.playerModel.scale, 30 * this.playerModel.scale);\n }\n // Y固定π,X保留垂直角度\n this.camera.rotation.set(\n THREE.MathUtils.clamp(vertAngle, -1.1, 1.4),\n Math.PI,\n 0,\n );\n this.controls.enableZoom = false;\n }\n\n // 设置鼠标锁定\n setPointerLock() {\n if (!document.body.requestPointerLock) return;\n if (((this.thirdMouseMode === 0 || this.thirdMouseMode === 1) && !this.isFirstPerson) || this.isFirstPerson) {\n document.body.requestPointerLock();\n } else {\n document.exitPointerLock();\n }\n }\n\n // 初始相机位置\n setCameraPos() {\n requestAnimationFrame(() => {\n if (!this.isFirstPerson) {\n const dir = new THREE.Vector3(0, 0, -1).applyQuaternion(this.player.quaternion);\n const angle = Math.atan2(dir.z, dir.x);\n const s = this.playerModel.scale;\n this.camera.position.copy(this.player.position)\n .add(new THREE.Vector3(Math.cos(angle) * 400 * s, 200 * s, Math.sin(angle) * 400 * s));\n this.controls.enableZoom = this.enableZoom;\n } else {\n this.person!.add(this.camera);\n this.camera.position.set(0, 40 * this.playerModel.scale, 30 * this.playerModel.scale);\n }\n this.camera.updateProjectionMatrix();\n });\n }\n\n // 初始化轨道控制\n setControls() {\n this.controls.enableZoom = this.enableZoom;\n this.controls.rotateSpeed = this.mouseSensitivity * 0.05;\n this.controls.maxPolarAngle = Math.PI * (300 / 360);\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\n }\n\n // 重置轨道控制\n resetControls() {\n if (!this.controls) return;\n this.controls.enabled = true;\n this.controls.enablePan = true;\n this.controls.maxPolarAngle = Math.PI / 2;\n this.controls.rotateSpeed = 1;\n this.controls.enableZoom = true;\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\n }\n\n // 视角旋转处理\n setToward(dx: number, dy: number, speed: number) {\n const sens = this.mouseSensitivity;\n if (this.controllerMode === 0) {\n // 人物模式\n if (this.isFirstPerson) {\n if (this.isMovingToBoardingPoint) return;\n this.player.rotateY(-dx * speed * sens);\n this.camera.rotation.x = THREE.MathUtils.clamp(this.camera.rotation.x + (-dy * speed * sens), -1.1, 1.4);\n } else {\n this.orbitCamera(this.player.position, -dx * speed * sens, -dy * speed * sens);\n }\n } else {\n // 车辆模式\n const v = this.activeVehicle;\n if (!v) return;\n if (this.isFirstPerson) {\n this.camera.rotation.y = THREE.MathUtils.clamp(this.camera.rotation.y + (-dx * speed * sens), Math.PI * (3 / 4), Math.PI * (5 / 4));\n this.camera.rotation.x = THREE.MathUtils.clamp(this.camera.rotation.x + (-dy * speed * sens), 0, Math.PI * (1 / 3));\n } else {\n this.orbitCamera(v.vehicleGroup.position, -dx * speed * sens, -dy * speed * sens);\n }\n }\n }\n\n // 球面轨道旋转\n private orbitCamera(target: THREE.Vector3, deltaX: number, deltaY: number) {\n const distance = this.camera.position.distanceTo(target);\n const cur = this.camera.position.clone().sub(target);\n let theta = Math.atan2(cur.x, cur.z) + deltaX;\n let phi = Math.acos(THREE.MathUtils.clamp(cur.y / distance, -1, 1)) + deltaY;\n phi = Math.max(0.1, Math.min(Math.PI - 0.1, phi));\n this.camera.position.set(\n target.x + distance * Math.sin(phi) * Math.sin(theta),\n target.y + distance * Math.cos(phi),\n target.z + distance * Math.sin(phi) * Math.cos(theta),\n );\n this.camera.lookAt(target);\n }\n\n // ==================== 碰撞体构建 ====================\n\n // 补全几何属性\n ensureAttributesMinimal(geom: THREE.BufferGeometry): THREE.BufferGeometry | null {\n if (!geom.attributes.position) return null;\n if (!geom.attributes.normal) geom.computeVertexNormals();\n if (!geom.attributes.uv) {\n const count = geom.attributes.position.count;\n geom.setAttribute(\"uv\", new THREE.BufferAttribute(new Float32Array(count * 2), 2));\n }\n return geom;\n }\n\n // 统一几何属性格式\n unifiedAttribute(collected: THREE.BufferGeometry[]) {\n type AttrMeta = { itemSize: number; arrayCtor: any; examples: number; normalized: boolean };\n const attrMap = new Map<string, AttrMeta>();\n const attrConflict = new Set<string>();\n const required = new Set([\"position\", \"normal\", \"uv\"]);\n\n // 剔除非必要属性\n for (const g of collected)\n for (const name of Object.keys(g.attributes))\n if (!required.has(name)) g.deleteAttribute(name);\n\n // 统计属性元信息\n for (const g of collected) {\n for (const name of Object.keys(g.attributes)) {\n const attr = g.attributes[name] as THREE.BufferAttribute;\n const ctor = (attr.array as any).constructor;\n if (!attrMap.has(name)) {\n attrMap.set(name, { itemSize: attr.itemSize, arrayCtor: ctor, examples: 1, normalized: attr.normalized });\n } else {\n const m = attrMap.get(name)!;\n if (m.itemSize !== attr.itemSize || m.arrayCtor !== ctor || m.normalized !== attr.normalized) attrConflict.add(name);\n else m.examples++;\n }\n }\n }\n\n // 移除冲突属性\n for (const name of attrConflict) {\n for (const g of collected) if (g.attributes[name]) g.deleteAttribute(name);\n attrMap.delete(name);\n }\n\n // 补全缺失属性\n for (const [name, meta] of attrMap) {\n for (const g of collected) {\n if (!g.attributes[name]) {\n const count = g.attributes.position.count;\n g.setAttribute(name, new THREE.BufferAttribute(new meta.arrayCtor(count * meta.itemSize), meta.itemSize, meta.normalized));\n }\n }\n }\n\n return collected;\n }\n\n // 构建静态 BVH\n async createBVH(meshUrl = \"\"): Promise<void> {\n await this.initLoader();\n\n const collectMesh = (mesh: THREE.Mesh) => {\n try {\n let geom = (mesh.geometry as THREE.BufferGeometry).clone();\n geom.applyMatrix4(mesh.matrixWorld);\n if (geom.index) geom = geom.toNonIndexed();\n const safe = this.ensureAttributesMinimal(geom);\n if (safe) this.collected.push(safe);\n } catch (e) {\n console.warn(\"处理网格时出错:\", mesh, e);\n }\n };\n\n // 收集网格\n if (meshUrl === \"\") {\n if (this.collider) { this.scene.remove(this.collider); this.collider = null; }\n this.scene.traverse(c => {\n const m = c as THREE.Mesh;\n if (m?.isMesh && m.geometry && c.name !== \"capsule\") collectMesh(m);\n });\n } else {\n const gltf = await this.loader.loadAsync(meshUrl);\n const root = gltf.scene.children[0] as any;\n if (root?.geometry) {\n collectMesh(root);\n } else {\n root?.traverse((c: any) => {\n if (c?.isMesh && c.geometry && c.name !== \"capsule\") collectMesh(c);\n });\n }\n }\n\n if (!this.collected.length) return;\n this.collected = this.unifiedAttribute(this.collected);\n\n // 合并并生成 BVH\n const merged = BufferGeometryUtils.mergeGeometries(this.collected, false);\n if (!merged) { console.error(\"合并几何失败\"); return; }\n\n (merged as any).boundsTree = new MeshBVH(merged, { maxDepth: 100 });\n this.collider = new THREE.Mesh(merged, new THREE.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true }));\n\n if (this.displayCollider) this.scene.add(this.collider);\n if (this.displayVisualizer) {\n if (this.visualizer) this.scene.remove(this.visualizer);\n this.visualizer = new MeshBVHHelper(this.collider, 0);\n this.scene.add(this.visualizer);\n }\n this.boundingBoxMinY = (this.collider as any).geometry.boundingBox.min.y;\n }\n\n // 构建动态 BVH\n createDynamicBVH(objects: THREE.Object3D[] = []) {\n if (this.dynamicCollider) { this.scene.remove(this.dynamicCollider); this.dynamicCollider = null; }\n this.dynamicCollected = [];\n\n objects.forEach(obj => obj.traverse(c => {\n const m = c as THREE.Mesh;\n if (m?.isMesh && m.geometry && c.name !== \"capsule\") {\n try {\n let geom = (m.geometry as THREE.BufferGeometry).clone();\n geom.applyMatrix4(m.matrixWorld);\n if (geom.index) geom = geom.toNonIndexed();\n const safe = this.ensureAttributesMinimal(geom);\n if (safe) this.dynamicCollected.push(safe);\n } catch (e) {\n console.warn(\"处理网格时出错:\", m, e);\n }\n }\n }));\n\n if (!this.dynamicCollected.length) return;\n this.dynamicCollected = this.unifiedAttribute(this.dynamicCollected);\n const merged = BufferGeometryUtils.mergeGeometries(this.dynamicCollected, false);\n if (!merged) { console.error(\"合并几何失败\"); return; }\n (merged as any).boundsTree = new MeshBVH(merged);\n this.dynamicCollider = new THREE.Mesh(merged, new THREE.MeshBasicMaterial({ opacity: 0.5, transparent: true, wireframe: true, depthTest: true }));\n if (this.displayCollider) this.scene.add(this.dynamicCollider);\n }\n\n // ==================== 控制器过渡 ====================\n\n // 车辆切换过渡\n setControllerTransition() {\n if (this.isChangeControllerTransitionTimer) {\n clearTimeout(this.isChangeControllerTransitionTimer);\n this.isChangeControllerTransitionTimer = null;\n }\n const vGroups = this.vehicles.map(v => v.vehicleGroup);\n this.createDynamicBVH(vGroups);\n this.isChangeControllerTransitionTimer = setTimeout(() => {\n this.isChangeControllerTransitionTimer = null;\n this.vehicles.forEach(v => this.clearVehicleVelocity(v));\n this.createDynamicBVH(vGroups);\n }, 3000);\n }\n\n // 清零车辆速度\n private clearVehicleVelocity(v: VehicleInstance) {\n if (!v || !this.world || !this.RAPIER) return;\n const { chassisBody, vehicleController } = v;\n const ZERO = new this.RAPIER.Vector3(0, 0, 0);\n chassisBody.setLinvel(ZERO, true);\n chassisBody.setAngvel(ZERO, true);\n for (let i = 0; i < 4; i++) { vehicleController.setWheelEngineForce(i, 0); vehicleController.setWheelBrake(i, 1e6); }\n vehicleController.updateVehicle(1 / 60);\n this.world.timestep = 1 / 60;\n this.world.step();\n chassisBody.setLinvel(ZERO, true);\n chassisBody.setAngvel(ZERO, true);\n for (let i = 0; i < 4; i++) vehicleController.setWheelBrake(i, 0);\n }\n\n // ==================== 循环更新 ====================\n\n // 主循环更新\n async update(delta: number = clock.getDelta()) {\n if (!this.isupdate || !this.player || !this.collider) return;\n delta = Math.min(delta, 1 / 40);\n if (this.controllerMode === 1) {\n this.updateVehicle(delta);\n } else {\n this.updatePlayer(delta);\n if (this.isChangeControllerTransitionTimer) this.updateVehicleInertia(delta);\n }\n }\n\n // 车辆帧更新\n updateVehicle(delta: number) {\n const v = this.activeVehicle;\n if (!v || !this.world) return;\n const { vehicleController, chassisBody, vehicleGroup } = v;\n\n // 上坡补偿\n const rotation = chassisBody.rotation();\n const quat = new THREE.Quaternion(rotation.x, rotation.y, rotation.z, rotation.w);\n const forward = new THREE.Vector3(1, 0, 0).applyQuaternion(quat);\n const slopeAngle = Math.asin(forward.y);\n const factor = (slopeAngle < -0.05 && this.fwdPressed) ? -Math.sin(slopeAngle) * 10 : 1;\n\n // 驱动力\n const accelerateForce = this.vehicleParams.power.accelerateForce * v.speedMultiplier;\n const maxSpeed = this.vehicleParams.power.maxSpeed * v.speedMultiplier;\n const engineForce = (Number(this.fwdPressed) - Number(this.bkdPressed)) * accelerateForce * factor;\n for (let i = 0; i < 4; i++) vehicleController.setWheelEngineForce(i, engineForce);\n\n // 刹车\n const wheelBrake = Number(this.spacePressed) * this.vehicleParams.power.brakeForce * delta;\n for (let i = 0; i < 4; i++) vehicleController.setWheelBrake(i, wheelBrake);\n\n // 转向\n const currentSteering = vehicleController.wheelSteering(0) || 0;\n const steerDir = Number(this.lftPressed) - Number(this.rgtPressed);\n const steerSpeed = steerDir === 0 ? this.vehicleParams.steering.steerReturnSpeed : this.vehicleParams.steering.steerSpeed;\n const steering = THREE.MathUtils.lerp(currentSteering, this.vehicleParams.steering.maxSteerAngle * steerDir, 1 - Math.pow(1 - steerSpeed, delta));\n vehicleController.setWheelSteering(0, steering);\n vehicleController.setWheelSteering(1, steering);\n\n // 漂移\n const driftFriction = ((this.rgtPressed || this.lftPressed) && this.shiftPressed) ? 0.5 : 2;\n vehicleController.setWheelSideFrictionStiffness(2, driftFriction);\n vehicleController.setWheelSideFrictionStiffness(3, driftFriction);\n\n this.updateVehicleInertia(delta);\n\n // 第三人称相机\n if (!this.isFirstPerson) {\n const lookTarget = vehicleGroup.position.clone();\n this.camera.position.sub(this.controls.target);\n this.controls.target.copy(lookTarget);\n this.camera.position.add(lookTarget);\n this.controls.update();\n\n // 以车辆包围盒为基准计算相机距离\n const velocity = chassisBody.linvel();\n const currentSpeed = new THREE.Vector3(velocity.x, velocity.y, velocity.z).length();\n const speedRatio = Math.min(currentSpeed / maxSpeed, 1);\n const baseDist = v.size.l * 0.8;\n const maxDist = v.size.l * 5;\n const desiredDist = THREE.MathUtils.lerp(baseDist, maxDist, speedRatio);\n const minSafeDist = baseDist;\n\n // 相机碰撞检测\n this.personToCam.subVectors(this.camera.position, vehicleGroup.position);\n const direction = this.personToCam.clone().normalize();\n this.raycasterPersonToCam.set(vehicleGroup.position, direction);\n this.raycasterPersonToCam.far = desiredDist;\n\n const hits = this.raycasterPersonToCam.intersectObject(this.collider!, false);\n if (hits.length > 0) {\n const safeDist = Math.max(hits[0].distance - this.camEpsilon, minSafeDist);\n this.camera.position.lerp(vehicleGroup.position.clone().add(direction.clone().multiplyScalar(safeDist)), this.camCollisionLerp);\n } else {\n this.raycasterPersonToCam.far = maxDist;\n const maxHits = this.raycasterPersonToCam.intersectObject(this.collider!, false);\n const safeDist = maxHits.length > 0\n ? Math.min(desiredDist, maxHits[0].distance - this.camEpsilon)\n : desiredDist;\n this.camera.position.lerp(vehicleGroup.position.clone().add(direction.clone().multiplyScalar(safeDist)), this.camCollisionLerp);\n }\n\n // 行驶时跟随车辆后方\n if ((this.fwdPressed || this.bkdPressed) && this.vehicleParams.followVehicleDirection) {\n const vel = chassisBody.linvel();\n const velVec = new THREE.Vector3(vel.x, vel.y, vel.z);\n if (velVec.length() > 0.3) {\n this.camBehindDir.lerp(velVec.normalize().negate(), this.camCollisionLerp).normalize();\n const targetCamPos = lookTarget.clone()\n .add(this.camBehindDir.clone().multiplyScalar(desiredDist))\n .add(new THREE.Vector3(0, v.size.h, 0));\n this.camera.position.lerp(targetCamPos, this.camCollisionLerp);\n this.controls.update();\n }\n }\n }\n\n // 翻车检测\n const vehicleUp = this.upVector.clone().applyQuaternion(vehicleGroup.quaternion);\n if (vehicleUp.angleTo(this.upVector) > Math.PI / 2) {\n const size = new THREE.Vector3();\n v.vehicleBBox?.getSize(size);\n const t = chassisBody.translation();\n chassisBody.setTranslation(new this.RAPIER.Vector3(t.x, t.y + size.y, t.z), true);\n chassisBody.setRotation(new this.RAPIER.Quaternion(0, 0, 0, 1), true);\n chassisBody.setLinvel(new this.RAPIER.Vector3(0, 0, 0), true);\n chassisBody.setAngvel(new this.RAPIER.Vector3(0, 0, 0), true);\n }\n }\n\n // 物理步进 & 同步\n updateVehicleInertia(delta: number) {\n if (!this.world) return;\n this.world.timestep = delta;\n this.world.step();\n\n for (const v of this.vehicles) {\n const { vehicleController, chassisBody, vehicleGroup, updateWheelVisuals } = v;\n vehicleController.updateVehicle(delta);\n if (chassisBody.isSleeping()) continue;\n\n // 限速\n const vel = chassisBody.linvel();\n const speed = new THREE.Vector3(vel.x, vel.y, vel.z).length();\n const max = this.vehicleParams.power.maxSpeed * v.speedMultiplier;\n if (speed > max) {\n const s = max / speed;\n chassisBody.setLinvel(new this.RAPIER.Vector3(vel.x * s, vel.y * s, vel.z * s), true);\n }\n\n // 同步视觉位置\n const t = chassisBody.translation();\n const r = chassisBody.rotation();\n vehicleGroup.position.set(t.x, t.y, t.z);\n vehicleGroup.quaternion.set(r.x, r.y, r.z, r.w);\n updateWheelVisuals?.();\n }\n }\n\n // 缩放玩家比例\n setPlayerScale(newScale: number) {\n if (newScale <= 0) return;\n const ratio = newScale / this.playerModel.scale;\n this.playerModel.scale = newScale;\n\n // 等比缩放所有物理参数\n this.gravity *= ratio;\n this.jumpHeight *= ratio;\n this.playerSpeed *= ratio;\n this.playerFlySpeed *= ratio;\n this.curPlayerSpeed *= ratio;\n this.camEpsilon *= ratio;\n this.minCamDistance *= ratio;\n this.maxCamDistance *= ratio;\n this.orginMaxCamDistance *= ratio;\n\n // 缩放碰撞体\n if (this.isFirstPerson) this.scene.attach(this.camera);\n this.player?.scale.multiplyScalar(ratio);\n if (this.player?.capsuleInfo) this.player.capsuleInfo.radius *= ratio;\n if (this.isFirstPerson) this.setFirstPersonCamera();\n }\n\n // 玩家帧更新\n updatePlayer(delta: number) {\n if (this.isMovingToBoardingPoint) this.updateMoveToBoardingPoint(delta);\n if (!this.isFlying) this.player.position.addScaledVector(this.playerVelocity, delta);\n\n // 上车关门计时\n if (this.isBoardingAnimPlaying) {\n const action = this.personActions?.get(\"enterCar\");\n if (action) {\n const duration = action.getClip().duration;\n const remaining = ((duration - action.time) / action.getEffectiveTimeScale()) * 1000;\n if (!this.closeDoorTriggered && remaining <= 500) { this.closeDoorTriggered = true; this.openVehicleDoor(false); }\n if (action.time >= duration) {\n this.isBoardingAnimPlaying = false;\n this.closeDoorTriggered = false;\n this.onEnterCarAnimFinished();\n return;\n }\n }\n }\n\n // 下车关门计时\n if (this.isExitAnimPlaying) {\n const action = this.personActions?.get(\"exitCar\");\n if (action) {\n const duration = action.getClip().duration;\n const remaining = ((duration - action.time) / action.getEffectiveTimeScale()) * 1000;\n if (!this.closeExitDoorTriggered && remaining <= 500) { this.closeExitDoorTriggered = true; this.openVehicleDoor(false); }\n if (action.time >= duration) { this.isExitAnimPlaying = false; this.closeExitDoorTriggered = false; }\n }\n }\n\n this.updateMixers(delta);\n if (this.controllerMode === 1) return;\n\n // 计算移动方向\n this.camera.getWorldDirection(this.camDir);\n const angle = 2 * Math.PI - (Math.atan2(this.camDir.z, this.camDir.x) + Math.PI / 2);\n\n this.moveDir.set(0, 0, 0);\n if (this.fwdPressed) this.moveDir.add(this.DIR_FWD);\n if (this.bkdPressed) this.moveDir.add(this.DIR_BKD);\n if (this.lftPressed) this.moveDir.add(this.DIR_LFT);\n if (this.rgtPressed) this.moveDir.add(this.DIR_RGT);\n\n // 飞行 / 地面速度\n if (this.isFlying) {\n this.moveDir.y = this.fwdPressed ? this.camDir.y : 0;\n if (this.spacePressed) this.moveDir.add(this.DIR_UP);\n this.curPlayerSpeed = this.shiftPressed ? this.playerFlySpeed * 2 : this.playerFlySpeed;\n } else {\n this.curPlayerSpeed = this.shiftPressed ? this.playerSpeed * 2 : this.playerSpeed;\n }\n\n this.moveDir.normalize().applyAxisAngle(this.upVector, angle);\n this.player.position.addScaledVector(this.moveDir, this.curPlayerSpeed * delta);\n\n // 地面检测\n this.raycaster.ray.origin.copy(this.player.position);\n const hits = this.raycaster.intersectObject(this.collider!, false);\n if (hits.length > 0 && !this.isFlying) {\n const dist = this.player.position.y - hits[0].point.y;\n const s = this.playerModel.scale;\n const maxH = this.playerCapsuleHeight * s * 0.9;\n const h = this.playerCapsuleHeight * s * 0.75;\n const minH = this.playerCapsuleHeight * s * 0.7;\n\n if (dist >= maxH) {\n this.playerVelocity.y += delta * this.gravity;\n this.player.position.addScaledVector(this.playerVelocity, delta);\n this.playerIsOnGround = false;\n } else if (dist >= h && dist < maxH) {\n if (!this.spacePressed) { this.playerVelocity.set(0, 0, 0); this.playerIsOnGround = true; this.player.position.y = hits[0].point.y + h; }\n } else if (dist >= minH) {\n this.playerVelocity.set(0, 0, 0); this.playerIsOnGround = true; this.player.position.y = hits[0].point.y + h;\n } else {\n this.playerVelocity.set(0, 0, 0); this.player.position.y = hits[0].point.y + h; this.playerIsOnGround = true;\n }\n }\n\n this.player.updateMatrixWorld();\n\n // BVH 胶囊体碰撞\n const capsuleInfo = this.player.capsuleInfo;\n this.tempBox.makeEmpty();\n this.tempMat.copy(this.collider!.matrixWorld).invert();\n this.tempSegment.copy(capsuleInfo.segment);\n this.tempSegment.start.applyMatrix4(this.player.matrixWorld).applyMatrix4(this.tempMat);\n this.tempSegment.end.applyMatrix4(this.player.matrixWorld).applyMatrix4(this.tempMat);\n this.tempBox.expandByPoint(this.tempSegment.start).expandByPoint(this.tempSegment.end);\n this.tempBox.expandByScalar(capsuleInfo.radius);\n\n if (!this.isMovingToBoardingPoint) {\n const resolveCollision = (collider: THREE.Mesh | null) => {\n if (!collider) return;\n (collider.geometry as any)?.boundsTree?.shapecast({\n intersectsBounds: (box: THREE.Box3) => box.intersectsBox(this.tempBox),\n intersectsTriangle: (tri: any) => {\n const distance = tri.closestPointToSegment(this.tempSegment, this.tempVector, this.tempVector2);\n if (distance < capsuleInfo.radius) {\n const normal = tri.getNormal(new THREE.Vector3());\n if (normal.y > 0.5 && !this.isFlying) return;\n const dir = this.tempVector2.sub(this.tempVector).normalize();\n const depth = capsuleInfo.radius - distance;\n this.tempSegment.start.addScaledVector(dir, depth);\n this.tempSegment.end.addScaledVector(dir, depth);\n }\n },\n });\n };\n resolveCollision(this.collider);\n resolveCollision(this.dynamicCollider);\n }\n\n // 应用碰撞偏移\n const newPos = this.tempVector.copy(this.tempSegment.start).applyMatrix4(this.collider!.matrixWorld);\n const deltaVec = this.tempVector2.subVectors(newPos, this.player.position);\n const offset = Math.max(0, deltaVec.length() - 1e-5);\n this.player.position.add(deltaVec.normalize().multiplyScalar(offset));\n\n // 玩家朝向\n if (!this.isFirstPerson) {\n const camDirFlat = this.camDir.clone().setY(0).normalize().negate();\n const moveDirFlat = this.moveDir.clone().normalize().negate();\n\n if (!this.isFlying) {\n if (this.thirdMouseMode === 0 || this.thirdMouseMode === 2) {\n const lookTarget = this.player.position.clone().add(moveDirFlat.lengthSq() > 0 ? moveDirFlat : camDirFlat);\n this.targetMat.lookAt(this.player.position, lookTarget, this.player.up);\n this.player.quaternion.slerp(this.targetQuat.setFromRotationMatrix(this.targetMat), Math.min(1, this.rotationSpeed * delta));\n } else if (moveDirFlat.lengthSq() > 0) {\n this.targetMat.lookAt(this.player.position, this.player.position.clone().add(moveDirFlat), this.player.up);\n this.player.quaternion.slerp(this.targetQuat.setFromRotationMatrix(this.targetMat), Math.min(1, this.rotationSpeed * delta));\n }\n } else {\n const lookTarget = this.player.position.clone().add(this.fwdPressed ? moveDirFlat : camDirFlat);\n this.targetMat.lookAt(this.player.position, lookTarget, this.player.up);\n this.player.quaternion.slerp(this.targetQuat.setFromRotationMatrix(this.targetMat), Math.min(1, this.rotationSpeed * delta));\n }\n }\n\n // 第三人称相机跟随\n if (!this.isFirstPerson) {\n const lookTarget = this.player.position.clone();\n lookTarget.y += (this.playerCapsuleHeight / 8) * this.playerModel.scale;\n this.camera.position.sub(this.controls.target);\n this.controls.target.copy(lookTarget);\n this.camera.position.add(lookTarget);\n this.controls.update();\n\n if (!this.enableZoom) {\n this.updateCameraWithRaycast(\n this.player.position,\n this.personToCam.subVectors(this.camera.position, this.player.position).length(),\n this.maxCamDistance,\n );\n }\n }\n\n // 掉落重置\n if (this.player.position.y < this.boundingBoxMinY - 1) {\n this.raycaster.ray.origin.set(this.player.position.x, 10000, this.player.position.z);\n const fallHits = this.raycaster.intersectObject(this.collider!, false);\n this.reset(new THREE.Vector3(\n this.player.position.x,\n fallHits.length > 0 ? fallHits[0].point.y + 5 : this.player.position.y + 15,\n this.player.position.z,\n ));\n }\n\n // 移动端车辆按钮检测\n if (this.isShowMobileControls && this.vehicles.length) {\n let near = false;\n for (const v of this.vehicles) {\n this.nearCheckLocal.copy(v.boardingPoint).multiplyScalar(v.scale);\n v.vehicleGroup.localToWorld(this.nearCheckWorld.copy(this.nearCheckLocal));\n if (this.player.position.distanceTo(this.nearCheckWorld) < 800 * this.playerModel.scale) { near = true; break; }\n }\n if (near !== this.isNearVehicle) {\n this.isNearVehicle = near;\n this.mobileControls?.syncVehicleBtn(near);\n }\n }\n }\n\n // 相机碰撞射线\n private updateCameraWithRaycast(origin: THREE.Vector3, desiredDist: number, maxDist: number) {\n this.personToCam.subVectors(this.camera.position, origin);\n const direction = this.personToCam.clone().normalize();\n this.raycasterPersonToCam.set(origin, direction);\n this.raycasterPersonToCam.far = desiredDist;\n\n const hits = this.raycasterPersonToCam.intersectObject(this.collider!, false);\n if (hits.length > 0) {\n // 有遮挡,缩短距离\n const safeDist = Math.max(hits[0].distance - this.camEpsilon, this.minCamDistance);\n const targetCamPos = origin.clone().add(direction.multiplyScalar(safeDist));\n this.camera.position.lerp(targetCamPos, this.camCollisionLerp);\n } else {\n // 无遮挡,推到最大距离\n this.raycasterPersonToCam.far = maxDist;\n const maxHits = this.raycasterPersonToCam.intersectObject(this.collider!, false);\n const safeDist = maxHits.length > 0\n ? Math.min(maxDist, maxHits[0].distance - this.camEpsilon)\n : maxDist;\n const targetCamPos = origin.clone().add(direction.multiplyScalar(safeDist));\n this.camera.position.lerp(targetCamPos, this.camCollisionLerp);\n }\n }\n\n // 屏幕中心射线\n getCenterScreenRaycastHit(): THREE.Intersection | undefined {\n this.camera.updateMatrixWorld();\n this.centerRay.setFromCamera(this.centerMouse, this.camera);\n return this.centerRay.intersectObject(this.collider!, false)[0];\n }\n\n // 获取当前人物动画名称\n getCurrentPersonAnimationName(): string | null {\n return (this.actionState as any)._clip.name;\n }\n\n // 更新动画混合器\n private updateMixers(delta: number) {\n this.personMixer?.update(delta);\n for (const v of this.vehicles) v.vehicleMixer?.update(delta);\n }\n\n // 重置玩家位置\n reset(position?: THREE.Vector3) {\n if (!this.player) return;\n this.playerVelocity.set(0, 0, 0);\n this.player.position.copy(position ?? this.initPos);\n }\n\n // 获取玩家位置\n getPosition() { return this.player?.position; }\n\n // ==================== 输入处理 ====================\n\n // 外部输入接口\n setInput(input: Partial<{\n moveX: 1 | 0 | -1; moveY: 1 | 0 | -1;\n lookDeltaX: number; lookDeltaY: number;\n jump: boolean; shift: boolean;\n toggleView: boolean; toggleFly: boolean; toggleVehicle: boolean;\n }>) {\n // 移动方向\n if (typeof input.moveX === \"number\") { this.lftPressed = input.moveX === -1; this.rgtPressed = input.moveX === 1; this.setAnimationByPressed(); }\n if (typeof input.moveY === \"number\") { this.fwdPressed = input.moveY === 1; this.bkdPressed = input.moveY === -1; this.setAnimationByPressed(); }\n\n // 视角旋转\n if (typeof input.lookDeltaX === \"number\" && typeof input.lookDeltaY === \"number\") {\n this.setToward(input.lookDeltaX, input.lookDeltaY, 0.002);\n }\n\n // 跳跃\n if (typeof input.jump === \"boolean\") {\n if (input.jump) {\n this.cancelBoarding();\n this.spacePressed = true;\n if (this.controllerMode === 1) return;\n if (!this.playerIsOnGround || this.isFlying) return;\n this.playPersonAnimationByName(\"jumping\");\n this.playerVelocity.y = this.jumpHeight;\n this.playerIsOnGround = false;\n } else {\n this.spacePressed = false;\n }\n }\n\n // 其他按键\n if (typeof input.shift === \"boolean\") this.shiftPressed = input.shift;\n if (input.toggleView) this.changeView();\n\n if (input.toggleFly && this.playerFlyEnabled && this.controllerMode === 0) {\n this.isFlying = !this.isFlying;\n this.setAnimationByPressed();\n if (!this.isFlying && !this.playerIsOnGround) this.playPersonAnimationByName(\"jumping\");\n }\n\n if (input.toggleVehicle) {\n if (this.controllerMode === 0) this.enterVehicle(); else this.exitVehicle();\n }\n }\n\n // 取消上车寻路\n private cancelBoarding() {\n this.isMovingToBoardingPoint = false;\n this.boardingWaypoints = [];\n this.currentWaypointIndex = 0;\n this.boardingTargetDir = null;\n }\n\n // 按键动画同步\n private setAnimationByPressed = () => {\n this.maxCamDistance = this.orginMaxCamDistance;\n this.cancelBoarding();\n\n // 清理上下车动画状态\n if (this.isExitAnimPlaying) { this.isExitAnimPlaying = false; this.closeExitDoorTriggered = false; }\n if (this.isBoardingAnimPlaying) { this.isBoardingAnimPlaying = false; this.closeDoorTriggered = false; }\n if (this.closeVehicleDoorTimer) { clearTimeout(this.closeVehicleDoorTimer); this.closeVehicleDoorTimer = null; }\n\n // 飞行动画\n if (this.isFlying) {\n if (!this.fwdPressed) { this.playPersonAnimationByName(\"flyidle\"); return; }\n this.playPersonAnimationByName(\"flying\");\n this.maxCamDistance = this.orginMaxCamDistance * 2;\n return;\n }\n\n // 地面动画\n if (this.playerIsOnGround) {\n if (!this.fwdPressed && !this.bkdPressed && !this.lftPressed && !this.rgtPressed) {\n this.playPersonAnimationByName(\"idle\"); return;\n }\n if (this.fwdPressed) { this.playPersonAnimationByName(this.shiftPressed ? \"running\" : \"walking\"); return; }\n if (!this.isFirstPerson && (this.lftPressed || this.rgtPressed || this.bkdPressed)) {\n this.playPersonAnimationByName(this.shiftPressed ? \"running\" : \"walking\"); return;\n }\n if (this.lftPressed) { this.playPersonAnimationByName(\"left_walking\"); return; }\n if (this.rgtPressed) { this.playPersonAnimationByName(\"right_walking\"); return; }\n if (this.bkdPressed) { this.playPersonAnimationByName(\"walking_backward\"); return; }\n }\n\n if (this.recheckAnimTimer !== null) clearTimeout(this.recheckAnimTimer);\n this.recheckAnimTimer = setTimeout(() => { this.setAnimationByPressed(); this.recheckAnimTimer = null; }, 200);\n };\n\n // ==================== 事件处理 ====================\n\n // 键盘按下事件\n private boundOnKeydown = async (e: KeyboardEvent) => {\n if (e.ctrlKey && [\"KeyW\", \"KeyA\", \"KeyS\", \"KeyD\"].includes(e.code)) e.preventDefault();\n switch (e.code) {\n case \"KeyW\": case \"ArrowUp\": this.fwdPressed = true; this.setAnimationByPressed(); break;\n case \"KeyS\": case \"ArrowDown\": this.bkdPressed = true; this.setAnimationByPressed(); break;\n case \"KeyD\": case \"ArrowRight\": this.rgtPressed = true; this.setAnimationByPressed(); break;\n case \"KeyA\": case \"ArrowLeft\": this.lftPressed = true; this.setAnimationByPressed(); break;\n case \"ShiftLeft\": case \"ShiftRight\":\n this.shiftPressed = true;\n this.setAnimationByPressed();\n this.controls.mouseButtons = { LEFT: 2, MIDDLE: 1, RIGHT: 0 };\n break;\n case \"Space\":\n this.cancelBoarding();\n this.spacePressed = true;\n if (this.controllerMode === 1) return;\n if (!this.playerIsOnGround || this.isFlying) return;\n if (this.personActions?.get(\"jumping\") === this.actionState) return;\n this.playPersonAnimationByName(\"jumping\");\n this.playerVelocity.y = this.jumpHeight;\n this.playerIsOnGround = false;\n break;\n case \"ControlLeft\": this.ctPressed = true; break;\n case \"KeyV\": this.changeView(); break;\n case \"KeyF\":\n if (this.controllerMode === 0 && this.playerFlyEnabled) {\n this.isFlying = !this.isFlying;\n this.setAnimationByPressed();\n if (!this.isFlying && !this.playerIsOnGround) this.playPersonAnimationByName(\"jumping\");\n }\n break;\n case \"KeyE\":\n if (this.isFlying) return;\n if (this.controllerMode === 0) this.enterVehicle(); else this.exitVehicle();\n break;\n }\n };\n\n // 键盘抬起事件\n private boundOnKeyup = (e: KeyboardEvent) => {\n switch (e.code) {\n case \"KeyW\": case \"ArrowUp\": this.fwdPressed = false; this.setAnimationByPressed(); break;\n case \"KeyS\": case \"ArrowDown\": this.bkdPressed = false; this.setAnimationByPressed(); break;\n case \"KeyD\": case \"ArrowRight\": this.rgtPressed = false; this.setAnimationByPressed(); break;\n case \"KeyA\": case \"ArrowLeft\": this.lftPressed = false; this.setAnimationByPressed(); break;\n case \"ShiftLeft\": case \"ShiftRight\":\n this.shiftPressed = false;\n this.setAnimationByPressed();\n this.controls.mouseButtons = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };\n break;\n case \"Space\": this.spacePressed = false; break;\n case \"ControlLeft\": this.ctPressed = false; break;\n }\n };\n\n private mouseMove = (e: MouseEvent) => { if (document.pointerLockElement === document.body) this.setToward(e.movementX, e.movementY, 0.0001); };\n private mouseClick = () => this.setPointerLock();\n\n // 注册所有事件\n onAllEvent() {\n this.isupdate = true;\n this.setPointerLock();\n window.addEventListener(\"keydown\", this.boundOnKeydown);\n window.addEventListener(\"keyup\", this.boundOnKeyup);\n window.addEventListener(\"mousemove\", this.mouseMove);\n window.addEventListener(\"click\", this.mouseClick);\n }\n\n // 注销所有事件\n offAllEvent() {\n this.isupdate = false;\n document.exitPointerLock();\n window.removeEventListener(\"keydown\", this.boundOnKeydown);\n window.removeEventListener(\"keyup\", this.boundOnKeyup);\n window.removeEventListener(\"mousemove\", this.mouseMove);\n window.removeEventListener(\"click\", this.mouseClick);\n }\n\n // ==================== 移动端同步 ====================\n\n // 同步移动端按钮\n private syncMobileControllerMode() {\n this.mobileControls?.syncControllerModeBtn(this.controllerMode);\n }\n\n // ==================== Setters ====================\n\n // 设置鼠标灵敏度\n setMouseSensitivity(value: number) {\n this.mouseSensitivity = value;\n this.controls.rotateSpeed = value * 0.05;\n }\n\n // 设置重力\n setGravity(gravity: number) { this.gravity = gravity * this.playerModel.scale; }\n // 设置跳跃高度\n setJumpHeight(jumpHeight: number) { this.jumpHeight = jumpHeight * this.playerModel.scale; }\n // 设置移动速度\n setPlayerSpeed(speed: number) { this.playerSpeed = speed * this.playerModel.scale; this.curPlayerSpeed = this.playerSpeed; }\n // 设置飞行速度\n setPlayerFlySpeed(flySpeed: number) { this.playerFlySpeed = flySpeed * this.playerModel.scale; }\n // 设置最小相机距离\n setMinCamDistance(dist: number) { this.minCamDistance = dist * this.playerModel.scale; }\n // 设置最大相机距离\n setMaxCamDistance(dist: number) { this.maxCamDistance = dist * this.playerModel.scale; this.orginMaxCamDistance = this.maxCamDistance; }\n // 设置鼠标模式\n setThirdMouseMode(mode: 0 | 1 | 2 | 3) { this.thirdMouseMode = mode; this.setPointerLock(); }\n // 设置滚轮缩放\n setEnableZoom(enable: boolean) { this.enableZoom = enable; this.controls.enableZoom = enable; }\n\n // 设置调试显示\n setDebug(debug: boolean) {\n if (this.collider) this.scene.remove(this.collider);\n if (debug) {\n this.scene.add(this.collider!);\n (this.player.material as THREE.Material).opacity = 0.5;\n } else {\n (this.player.material as THREE.Material).opacity = 0;\n }\n }\n\n // ==================== 销毁 ====================\n\n // 销毁控制器\n destroy() {\n // 注销事件\n this.offAllEvent();\n\n // 清理玩家\n if (this.player) { this.player.remove(this.camera); this.scene.remove(this.player); }\n (this.player as any) = null;\n if (this.person) { this.scene.remove(this.person); this.person = null; }\n\n // 清理场景\n this.resetControls();\n if (this.visualizer) { this.scene.remove(this.visualizer); this.visualizer = null; }\n if (this.collider) { this.scene.remove(this.collider); this.collider = null; }\n\n // 清理移动端\n this.mobileControls?.destroy();\n this.mobileControls = null;\n\n // 清理车辆\n for (const v of this.vehicles) { this.scene.remove(v.vehicleGroup); v.pathPlanner?.dispose(); }\n this.vehicles = [];\n this.activeVehicle = null;\n\n controllerInstance = null;\n }\n}\n\n// ==================== 导出 API ====================\n\nexport function playerController() {\n if (!controllerInstance) controllerInstance = new PlayerController();\n const c = controllerInstance;\n return {\n init: (opts: PlayerControllerOptions, cb?: () => void) => c.init(opts, cb),\n loadVehicleModel: (opts: VehicleOptions) => c.loadVehicleModel(opts),\n update: (dt?: number) => c.update(dt),\n destroy: () => c.destroy(),\n reset: (pos?: THREE.Vector3) => c.reset(pos),\n setInput: (i: any) => c.setInput(i),\n changeView: () => c.changeView(),\n getPosition: () => c.getPosition(),\n getCenterScreenRaycastHit: () => c.getCenterScreenRaycastHit(),\n getCurrentPersonAnimationName: () => c.getCurrentPersonAnimationName(),\n getPerson: () => c.person,\n getActiveVehicle: () => c.activeVehicle,\n getAllVehicles: () => c.vehicles,\n switchPlayerModel: (model: PlayerModelOptions) => c.switchPlayerModel(model),\n setPlayerScale: (scale: number) => c.setPlayerScale(scale),\n setMouseSensitivity: (v: number) => c.setMouseSensitivity(v),\n setGravity: (v: number) => c.setGravity(v),\n setJumpHeight: (v: number) => c.setJumpHeight(v),\n setPlayerSpeed: (v: number) => c.setPlayerSpeed(v),\n setPlayerFlySpeed: (v: number) => c.setPlayerFlySpeed(v),\n setMinCamDistance: (v: number) => c.setMinCamDistance(v),\n setMaxCamDistance: (v: number) => c.setMaxCamDistance(v),\n setThirdMouseMode: (v: 0 | 1 | 2 | 3) => c.setThirdMouseMode(v),\n setEnableZoom: (v: boolean) => c.setEnableZoom(v),\n setDebug: (v: boolean) => c.setDebug(v),\n setOverShoulderView: (v: boolean) => c.setOverShoulderView(v),\n registerAnimation: (key: string, clipName: string, opts?: {\n loop?: boolean;\n timeScale?: number;\n clampWhenFinished?: boolean;\n onFinished?: () => void;\n }) => c.registerAnimation(key, clipName, opts),\n playAnimation: (key: string, opts?: {\n fade?: number;\n force?: boolean;\n }) => c.playAnimation(key, opts),\n };\n}\n\nexport type playerController = ReturnType<typeof playerController>;\n\nexport function onAllEvent(): void { if (!controllerInstance) controllerInstance = new PlayerController(); controllerInstance.onAllEvent(); }\nexport function offAllEvent(): void { controllerInstance?.offAllEvent(); }\n\nexport type { PlayerControllerOptions, PlayerModelOptions, VehicleOptions, VehicleInstance } from \"./types\";","import type { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\nimport breakIconModule from \"../../assets/imgs/break.png\";\nimport flyIconModule from \"../../assets/imgs/fly.png\";\nimport jumpIconModule from \"../../assets/imgs/jump.png\";\nimport vehicleIconModule from \"../../assets/imgs/vehicle.png\";\nimport viewIconModule from \"../../assets/imgs/view.png\";\n\ntype SetInputFn = (input: Partial<{\n moveX: 1 | 0 | -1;\n moveY: 1 | 0 | -1;\n lookDeltaX: number;\n lookDeltaY: number;\n jump: boolean;\n shift: boolean;\n toggleView: boolean;\n toggleFly: boolean;\n toggleVehicle: boolean;\n}>) => void;\n\nexport class MobileControls {\n setInput: SetInputFn;\n controls: OrbitControls;\n\n // 摇杆状态\n nippleModule: any = null;\n joystickManager: any = null;\n prevJoyState = { dirX: 0, dirY: 0, shift: false };\n\n // DOM 元素\n joystickZoneEl: HTMLDivElement | null = null;\n lookAreaEl: HTMLDivElement | null = null;\n jumpBtnEl: HTMLButtonElement | null = null;\n flyBtnEl: HTMLButtonElement | null = null;\n viewBtnEl: HTMLButtonElement | null = null;\n vehicleBtnEl: HTMLButtonElement | null = null;\n\n // 触摸状态\n lookPointerId: number | null = null;\n isLookDown = false;\n lastTouchX = 0;\n lastTouchY = 0;\n\n constructor(setInput: SetInputFn, controls: OrbitControls) {\n this.setInput = setInput;\n this.controls = controls;\n }\n\n // 初始化移动端控制\n async init() {\n this.controls.maxPolarAngle = Math.PI * (300 / 360);\n this.controls.touches = { ONE: null as any, TWO: null as any };\n\n // 加载摇杆库\n this.nippleModule = await import(\"nipplejs\");\n const nipple = this.nippleModule?.default;\n const JOY_SIZE = 120;\n const container = document.body;\n\n // 创建摇杆区域\n this.joystickZoneEl = document.createElement(\"div\");\n this.joystickZoneEl.id = \"joy-zone\";\n Object.assign(this.joystickZoneEl.style, {\n position: \"absolute\",\n left: \"16px\",\n bottom: \"16px\",\n width: `${JOY_SIZE + 40}px`,\n height: `${JOY_SIZE + 40}px`,\n touchAction: \"none\",\n zIndex: \"999\",\n pointerEvents: \"auto\",\n WebkitUserSelect: \"none\",\n userSelect: \"none\",\n });\n container.appendChild(this.joystickZoneEl);\n this.blockTouch(this.joystickZoneEl);\n\n // 初始化摇杆\n this.joystickManager = nipple.create({\n zone: this.joystickZoneEl,\n mode: \"static\",\n position: { left: `${(JOY_SIZE + 40) / 2}px`, bottom: `${(JOY_SIZE + 40) / 2}px` },\n color: \"#ffffff\",\n size: JOY_SIZE,\n multitouch: true,\n maxNumberOfNipples: 1,\n });\n\n // 摇杆移动\n this.joystickManager.on(\"move\", (_evt: any, data: any) => {\n if (!data) return;\n const rawX = data.vector?.x ?? 0;\n const rawY = data.vector?.y ?? 0;\n const distance = data.distance ?? 0;\n // 死区过滤\n const deadzone = 0.5;\n const dirX = rawX > deadzone ? 1 : rawX < -deadzone ? -1 : 0;\n const dirY = rawY > deadzone ? 1 : rawY < -deadzone ? -1 : 0;\n // 推到边缘触发冲刺\n const isSprinting = distance >= JOY_SIZE / 2;\n const prev = this.prevJoyState;\n if (dirX === prev.dirX && dirY === prev.dirY && isSprinting === prev.shift) return;\n this.prevJoyState = { dirX, dirY, shift: isSprinting };\n this.setInput({ moveX: dirX as any, moveY: dirY as any, shift: isSprinting });\n });\n\n // 摇杆抬起\n this.joystickManager.on(\"end\", () => {\n const prev = this.prevJoyState;\n if (prev.dirX !== 0 || prev.dirY !== 0 || prev.shift) {\n this.prevJoyState = { dirX: 0, dirY: 0, shift: false };\n this.setInput({ moveX: 0, moveY: 0, shift: false });\n }\n });\n\n // 创建视角区域\n this.lookAreaEl = document.createElement(\"div\");\n Object.assign(this.lookAreaEl.style, {\n position: \"absolute\",\n right: \"0\",\n bottom: \"0\",\n width: \"50%\",\n height: \"100%\",\n zIndex: \"998\",\n touchAction: \"none\",\n WebkitUserSelect: \"none\",\n userSelect: \"none\",\n });\n container.appendChild(this.lookAreaEl);\n this.blockTouch(this.lookAreaEl);\n\n // 绑定视角触摸事件\n this.lookAreaEl.addEventListener(\"pointerdown\", this.onPointerDown, { passive: false });\n this.lookAreaEl.addEventListener(\"pointermove\", this.onPointerMove, { passive: false });\n this.lookAreaEl.addEventListener(\"pointerup\", this.onPointerUp, { passive: false });\n this.lookAreaEl.addEventListener(\"pointercancel\", this.onPointerUp, { passive: false });\n\n // 创建操作按钮\n this.jumpBtnEl = this.createBtn(container, 14, 14, jumpIconModule);\n this.flyBtnEl = this.createBtn(container, 14, 14 + 80, flyIconModule);\n this.viewBtnEl = this.createBtn(container, 14, 14 + 200, viewIconModule);\n this.vehicleBtnEl = this.createBtn(container, 14 + 100, 14 + 120, vehicleIconModule);\n this.vehicleBtnEl.style.display = \"none\";\n\n // 绑定按钮事件\n this.jumpBtnEl.addEventListener(\"touchstart\", (e) => { e.preventDefault(); this.setInput({ jump: true }); }, { passive: false });\n this.jumpBtnEl.addEventListener(\"touchend\", (e) => { e.preventDefault(); this.setInput({ jump: false }); }, { passive: false });\n this.jumpBtnEl.addEventListener(\"touchcancel\", (e) => { e.preventDefault(); this.setInput({ jump: false }); }, { passive: false });\n this.flyBtnEl.addEventListener(\"touchstart\", (e) => { e.preventDefault(); this.setInput({ toggleFly: true }); }, { passive: false });\n this.viewBtnEl.addEventListener(\"touchstart\", (e) => { e.preventDefault(); this.setInput({ toggleView: true }); }, { passive: false });\n this.vehicleBtnEl.addEventListener(\"touchstart\", (e) => { e.preventDefault(); this.setInput({ toggleVehicle: true }); }, { passive: false });\n }\n\n // 销毁移动端控制\n destroy() {\n try {\n this.joystickManager?.destroy?.();\n this.joystickManager = null;\n\n if (this.lookAreaEl) {\n this.lookAreaEl.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.lookAreaEl.removeEventListener(\"pointermove\", this.onPointerMove);\n this.lookAreaEl.removeEventListener(\"pointerup\", this.onPointerUp);\n this.lookAreaEl.removeEventListener(\"pointercancel\", this.onPointerUp);\n }\n\n // 移除所有 DOM 元素\n [this.joystickZoneEl, this.lookAreaEl, this.jumpBtnEl, this.flyBtnEl, this.viewBtnEl, this.vehicleBtnEl]\n .forEach(el => el?.parentElement?.removeChild(el));\n\n this.joystickZoneEl = this.lookAreaEl = this.jumpBtnEl =\n this.flyBtnEl = this.viewBtnEl = this.vehicleBtnEl = null;\n } catch (e) {\n console.warn(\"销毁移动端控制时出错:\", e);\n }\n }\n\n // 同步车辆按钮显隐\n syncVehicleBtn(show: boolean) {\n if (this.vehicleBtnEl) this.vehicleBtnEl.style.display = show ? \"block\" : \"none\";\n }\n\n // 同步控制模式按钮\n syncControllerModeBtn(mode: 0 | 1) {\n if (!this.flyBtnEl || !this.jumpBtnEl) return;\n if (mode === 0) {\n // 人物模式:恢复飞行键和跳跃键\n this.flyBtnEl.style.display = \"block\";\n this.jumpBtnEl.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)),url(\"${jumpIconModule}\")`;\n } else {\n // 车辆模式:隐藏飞行键,跳跃键变刹车\n this.flyBtnEl.style.display = \"none\";\n this.jumpBtnEl.style.backgroundImage = `url(${breakIconModule})`;\n }\n }\n\n // 触摸按下\n private onPointerDown = (e: PointerEvent) => {\n if (e.pointerType !== \"touch\") return;\n this.isLookDown = true;\n this.lookPointerId = e.pointerId;\n this.lastTouchX = e.clientX;\n this.lastTouchY = e.clientY;\n this.lookAreaEl?.setPointerCapture?.(e.pointerId);\n e.preventDefault();\n };\n\n // 触摸移动\n private onPointerMove = (e: PointerEvent) => {\n if (!this.isLookDown || e.pointerId !== this.lookPointerId) return;\n const dx = e.clientX - this.lastTouchX;\n const dy = e.clientY - this.lastTouchY;\n this.lastTouchX = e.clientX;\n this.lastTouchY = e.clientY;\n this.setInput({ lookDeltaX: dx, lookDeltaY: dy });\n e.preventDefault();\n };\n\n // 触摸抬起\n private onPointerUp = (e: PointerEvent) => {\n if (e.pointerId !== this.lookPointerId) return;\n this.isLookDown = false;\n this.lookPointerId = null;\n this.lookAreaEl?.releasePointerCapture?.(e.pointerId);\n };\n\n // 阻止默认触摸\n private blockTouch(el: HTMLElement) {\n [\"touchstart\", \"touchmove\", \"touchend\", \"touchcancel\"].forEach(name => {\n el.addEventListener(name, e => e.preventDefault(), { passive: false });\n });\n }\n\n // 创建圆形按钮\n private createBtn(container: HTMLElement, rightPx: number, bottomPx: number, bgUrl: string): HTMLButtonElement {\n const btn = document.createElement(\"button\");\n Object.assign(btn.style, {\n position: \"absolute\",\n right: `${rightPx}px`,\n bottom: `${bottomPx}px`,\n width: \"56px\",\n height: \"56px\",\n zIndex: \"1000\",\n borderRadius: \"50%\",\n border: \"2px solid black\",\n padding: \"20px\",\n opacity: \"0.95\",\n touchAction: \"none\",\n fontSize: \"14px\",\n userSelect: \"none\",\n overflow: \"hidden\",\n boxSizing: \"border-box\",\n backgroundColor: \"transparent\",\n backgroundRepeat: \"no-repeat, no-repeat\",\n backgroundPosition: \"center center, center center\",\n backgroundSize: \"100% 100%, 80% 80%\",\n backgroundImage: `linear-gradient(rgba(0,0,0,0.5),rgba(0,0,0,0.5)),url(\"${bgUrl}\")`,\n });\n container.appendChild(btn);\n // 阻止按钮默认触摸行为\n [\"touchstart\", \"touchend\", \"touchcancel\"].forEach(name => {\n btn.addEventListener(name, e => e.preventDefault(), { passive: false });\n });\n return btn;\n }\n}","import * as THREE from \"three\";\nimport type { GLTFLoader } from \"three/examples/jsm/loaders/GLTFLoader.js\";\nimport { PathPlanner, type ObstacleChecker } from \"./pathPlanner\";\nimport { createVehicleController } from \"./useVehicleController\";\nimport type { VehicleOptions, VehicleInstance } from \"../types\";\n\nexport type VehicleLoaderContext = {\n loader: GLTFLoader;\n scene: THREE.Scene;\n world: any;\n RAPIER: any;\n vehicleParams: {\n debug: { showPhysicsBox: boolean };\n chassis: { linearDamping: number; angularDamping: number };\n model: { rotation: number };\n power: { accelerateForce: number; brakeForce: number; maxSpeed: number };\n steering: { maxSteerAngle: number; steerSpeed: number; steerReturnSpeed: number };\n followVehicleDirection: boolean;\n };\n vehicleLength: number;\n playerScale: number;\n};\n\n// ==================== 工具函数 ====================\n\n// 获取包围盒\nfunction getBbox(object: THREE.Object3D) {\n const bbox = new THREE.Box3().setFromObject(object);\n const center = new THREE.Vector3();\n const size = new THREE.Vector3();\n bbox.getCenter(center);\n bbox.getSize(size);\n return { bbox, center, size };\n}\n\n// 创建障碍物检测器\nfunction createObstacleChecker(\n vehicleGroup: THREE.Group,\n bbox: THREE.Box3,\n scale: number,\n playerScale: number,\n): ObstacleChecker {\n return {\n // 射线检测路径是否被车辆遮挡\n isBlocked(start: THREE.Vector3, end: THREE.Vector3): boolean {\n const vehiclePos = vehicleGroup.position;\n const vehicleQuat = vehicleGroup.quaternion;\n const center = new THREE.Vector3();\n const size = new THREE.Vector3();\n bbox.getCenter(center);\n bbox.getSize(size);\n center.applyQuaternion(vehicleQuat).add(vehiclePos);\n\n // 构建旋转后的包围盒角点\n const halfSize = size.clone().multiplyScalar(0.5 * scale);\n const corners: THREE.Vector3[] = [];\n for (let x = -1; x <= 1; x += 2)\n for (let y = -1; y <= 1; y += 2)\n for (let z = -1; z <= 1; z += 2)\n corners.push(\n new THREE.Vector3(halfSize.x * x, halfSize.y * y, halfSize.z * z)\n .applyQuaternion(vehicleQuat)\n .add(center),\n );\n\n // 扩展包围盒并做射线检测\n const expandedBBox = new THREE.Box3();\n corners.forEach(c => expandedBBox.expandByPoint(c));\n expandedBBox.expandByScalar(100 * playerScale);\n\n const direction = new THREE.Vector3().subVectors(end, start);\n const length = direction.length();\n const ray = new THREE.Ray(start, direction.normalize());\n const intersects = ray.intersectBox(expandedBBox, new THREE.Vector3());\n return intersects !== null && start.distanceTo(intersects) < length;\n },\n\n // 生成绕行导航节点\n getNavigationNodes(start: THREE.Vector3, _goal: THREE.Vector3): THREE.Vector3[] {\n const nodes = [] as THREE.Vector3[];\n const vehiclePos = vehicleGroup.position;\n const vehicleQuat = vehicleGroup.quaternion;\n const bboxSize = new THREE.Vector3();\n bbox.getSize(bboxSize);\n\n const fwd = new THREE.Vector3(0, 0, 1).applyQuaternion(vehicleQuat);\n const right = new THREE.Vector3(1, 0, 0).applyQuaternion(vehicleQuat);\n const halfLen = (bboxSize.z / 2) * scale;\n const halfWidth = (bboxSize.x / 2) * scale;\n const groundY = start.y;\n\n // 两个距离层级各生成四个角点\n for (const margin of [300 * playerScale, 500 * playerScale]) {\n nodes.push(vehiclePos.clone().add(fwd.clone().multiplyScalar(halfLen + margin)).add(right.clone().multiplyScalar(-halfWidth - margin)).setY(groundY));\n nodes.push(vehiclePos.clone().add(fwd.clone().multiplyScalar(halfLen + margin)).add(right.clone().multiplyScalar(halfWidth + margin)).setY(groundY));\n nodes.push(vehiclePos.clone().add(fwd.clone().multiplyScalar(-halfLen - margin)).add(right.clone().multiplyScalar(-halfWidth - margin)).setY(groundY));\n nodes.push(vehiclePos.clone().add(fwd.clone().multiplyScalar(-halfLen - margin)).add(right.clone().multiplyScalar(halfWidth + margin)).setY(groundY));\n }\n return nodes;\n },\n };\n}\n\n// ==================== 主函数 ====================\n\n// 加载车辆模型\nexport async function loadVehicleModel(\n opts: VehicleOptions,\n ctx: VehicleLoaderContext,\n): Promise<VehicleInstance> {\n const { loader, scene, world, RAPIER, vehicleParams, vehicleLength, playerScale } = ctx;\n\n const scale = opts.scale ?? 1;\n const chassisRatio = opts.chassisRatio ?? 0.2;\n const suspensionRestLengthRatio = opts.suspensionRestLengthRatio ?? 0.2;\n const speedMultiplier = opts.speedMultiplier ?? 1;\n\n // 更新车辆物理参数\n vehicleParams.power.accelerateForce = 50 * scale;\n vehicleParams.power.brakeForce = 200 * scale;\n vehicleParams.power.maxSpeed = 10000 * scale;\n vehicleParams.followVehicleDirection = opts.followVehicleDirection ?? true;\n\n const vehicleModel = await loader.loadAsync(opts.url);\n\n // 计算模型缩放比\n const { size: originalSize } = getBbox(vehicleModel.scene);\n const modelScale = vehicleLength / Math.max(originalSize.x, originalSize.y, originalSize.z);\n\n // 绑定开门动画\n const vehicleMixer = new THREE.AnimationMixer(vehicleModel.scene);\n const vehicleActions = new Map<string, THREE.AnimationAction>();\n const animations = vehicleModel.animations ?? [];\n const openDoorClip = animations.find(a => a.name === (opts.animations?.openDoorAnim ?? \"\"));\n if (openDoorClip) {\n const action = vehicleMixer.clipAction(openDoorClip);\n action.setLoop(THREE.LoopOnce, 1);\n action.clampWhenFinished = true;\n action.setEffectiveTimeScale(openDoorClip.duration);\n action.enabled = true;\n action.setEffectiveWeight(0);\n vehicleActions.set(\"openDoor\", action);\n }\n\n // 查找轮子节点\n const wheelObjects: THREE.Object3D[] = [];\n for (const name of opts.wheelsNames) {\n let found = false;\n vehicleModel.scene.traverse(child => {\n if (child.name === name && !found) { wheelObjects.push(child); found = true; }\n });\n if (!found) console.warn(`未找到轮子: ${name}`);\n }\n\n // 临时挂载获取世界坐标\n const tempGroup = new THREE.Group();\n scene.add(tempGroup);\n vehicleModel.scene.scale.multiplyScalar(modelScale * scale);\n vehicleModel.scene.rotateY(vehicleParams.model.rotation);\n const { size, bbox, center } = getBbox(vehicleModel.scene);\n vehicleModel.scene.position.set(-center.x, -center.y, -center.z);\n tempGroup.add(vehicleModel.scene);\n tempGroup.updateMatrixWorld(true);\n\n // 收集轮子世界变换信息\n let wheelRadius = 0, wheelWidth = 0, suspensionRestLength = 0, chassisHeight = 0, wheelSizeInit = false;\n const wheelsInfo: any[] = [];\n\n for (const wheel of wheelObjects) {\n const worldPos = new THREE.Vector3();\n const worldQuat = new THREE.Quaternion();\n const worldScale = new THREE.Vector3();\n wheel.getWorldPosition(worldPos);\n wheel.getWorldQuaternion(worldQuat);\n wheel.getWorldScale(worldScale);\n\n // 只计算一次轮子尺寸\n if (!wheelSizeInit) {\n const { size: ws } = getBbox(wheel);\n wheelRadius = Number((Math.max(ws.x, ws.y, ws.z) / 2).toFixed(2));\n wheelWidth = Number(Math.min(ws.x, ws.y, ws.z).toFixed(2));\n suspensionRestLength = Number((wheelRadius * 2 * suspensionRestLengthRatio).toFixed(2));\n chassisHeight = Number((wheelRadius * 2 * chassisRatio).toFixed(2));\n wheelSizeInit = true;\n }\n\n wheelsInfo.push({ axleCs: new THREE.Vector3(0, 0, -1), position: worldPos, quaternion: worldQuat, scale: worldScale, radius: wheelRadius, width: wheelWidth, suspensionRestLength, object: wheel });\n }\n\n tempGroup.remove(vehicleModel.scene);\n scene.remove(tempGroup);\n\n // 创建车辆根节点\n const vehicleGroup = new THREE.Group();\n scene.add(vehicleGroup);\n vehicleGroup.add(vehicleModel.scene);\n vehicleGroup.updateMatrixWorld(true);\n\n // 轮子包装组(独立旋转)\n const wheelWrappers: THREE.Group[] = [];\n for (let i = 0; i < wheelsInfo.length; i++) {\n const wheel = wheelsInfo[i];\n const wheelWrapper = new THREE.Group();\n wheelWrapper.position.copy(vehicleGroup.worldToLocal(wheel.position.clone()));\n\n const wheelObj = wheel.object;\n wheelObj.parent?.remove(wheelObj);\n wheelObj.position.set(0, 0, 0);\n wheelObj.quaternion.copy(wheel.quaternion);\n wheelObj.scale.copy(wheel.scale);\n wheelObj.updateMatrixWorld();\n\n wheelWrapper.add(wheelObj);\n vehicleGroup.add(wheelWrapper);\n wheelWrappers.push(wheelWrapper);\n }\n\n // 创建车身物理碰撞体\n const halfExtents = size.clone().multiplyScalar(0.5);\n halfExtents.y -= chassisHeight / 2;\n vehicleModel.scene.position.y -= chassisHeight / 2;\n halfExtents.x *= 0.95;\n halfExtents.z *= 0.95;\n\n const chassisBody = world.createRigidBody(\n RAPIER.RigidBodyDesc.dynamic()\n .setTranslation(opts.position.x, opts.position.y, opts.position.z)\n .setLinearDamping(vehicleParams.chassis.linearDamping)\n .setAngularDamping(vehicleParams.chassis.angularDamping)\n .setCanSleep(true)\n .setAdditionalMass(10),\n );\n world.createCollider(RAPIER.ColliderDesc.cuboid(halfExtents.x, halfExtents.y, halfExtents.z), chassisBody);\n\n // 调试模式显示物理盒\n if (vehicleParams.debug.showPhysicsBox) {\n vehicleGroup.add(new THREE.Mesh(\n new THREE.BoxGeometry(halfExtents.x * 2, halfExtents.y * 2, halfExtents.z * 2),\n new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true, transparent: true, opacity: 0.3 }),\n ));\n }\n\n vehicleGroup.position.copy(opts.position);\n vehicleGroup.updateMatrixWorld(true);\n\n const { vehicle, updateWheelVisuals } = createVehicleController(world, chassisBody, wheelWrappers, wheelsInfo);\n\n return {\n vehicleGroup,\n chassisBody,\n vehicleController: vehicle,\n updateWheelVisuals,\n vehicleMixer,\n vehicleActions,\n vehiclIsOpenDoor: false,\n vehicleBBox: bbox.clone(),\n pathPlanner: new PathPlanner(\n createObstacleChecker(vehicleGroup, bbox, scale, playerScale),\n { debugEnabled: false, scene, scale: playerScale },\n ),\n scale,\n boardingPoint: opts.boardingPoint,\n seatOffset: opts.seatOffset ?? new THREE.Vector3(),\n enterVehicleTime: 1.5,\n chassisRatio,\n suspensionRestLengthRatio,\n size: { l: Math.max(size.x, size.z), w: Math.min(size.x, size.z), h: size.y },\n speedMultiplier,\n };\n}","import * as THREE from \"three\";\r\n\r\n// ==================== 路径节点 ====================\r\n\r\n// A* 路径节点\r\nclass PathNode {\r\n position: THREE.Vector3;\r\n g: number = Infinity; // 实际代价\r\n h: number = 0; // 估计代价\r\n f: number = Infinity; // f = g + h\r\n parent: PathNode | null = null;\r\n\r\n constructor(position: THREE.Vector3) {\r\n this.position = position.clone();\r\n }\r\n\r\n // 判断节点相等\r\n equals(other: PathNode): boolean {\r\n return this.position.distanceTo(other.position) < 0.01;\r\n }\r\n}\r\n\r\n// ==================== 优先队列 ====================\r\n\r\n// A* 开放列表用优先队列\r\nclass PriorityQueue<T> {\r\n elements: Array<{ priority: number; item: T }> = [];\r\n\r\n // 入队并排序\r\n enqueue(item: T, priority: number) {\r\n this.elements.push({ priority, item });\r\n this.elements.sort((a, b) => a.priority - b.priority);\r\n }\r\n\r\n // 出队最小优先级\r\n dequeue(): T | undefined {\r\n return this.elements.shift()?.item;\r\n }\r\n\r\n isEmpty(): boolean {\r\n return this.elements.length === 0;\r\n }\r\n\r\n contains(item: T, compareFn: (a: T, b: T) => boolean): boolean {\r\n return this.elements.some((e) => compareFn(e.item, item));\r\n }\r\n\r\n // 更新节点优先级\r\n update(item: T, newPriority: number, compareFn: (a: T, b: T) => boolean) {\r\n const index = this.elements.findIndex((e) => compareFn(e.item, item));\r\n if (index !== -1) {\r\n this.elements[index].priority = newPriority;\r\n this.elements.sort((a, b) => a.priority - b.priority);\r\n }\r\n }\r\n}\r\n\r\n// ==================== 接口定义 ====================\r\n\r\n// 障碍物检测接口\r\nexport interface ObstacleChecker {\r\n // 检查两点间是否被障碍物阻挡\r\n isBlocked(start: THREE.Vector3, end: THREE.Vector3): boolean;\r\n // 获取障碍物周围导航节点\r\n getNavigationNodes(start: THREE.Vector3, goal: THREE.Vector3): THREE.Vector3[];\r\n}\r\n\r\n// 路径规划器配置\r\nexport interface PathPlannerConfig {\r\n debugEnabled?: boolean; // 路径可视化开关\r\n scene?: THREE.Scene; // 用于可视化的场景\r\n scale?: number; // 缩放系数\r\n}\r\n\r\n// ==================== 路径规划器 ====================\r\n\r\n// A* 路径规划器\r\nexport class PathPlanner {\r\n obstacleChecker: ObstacleChecker;\r\n config: PathPlannerConfig;\r\n debugLines: THREE.Line[] = [];\r\n debugPoints: THREE.Mesh[] = [];\r\n\r\n constructor(obstacleChecker: ObstacleChecker, config: PathPlannerConfig = {}) {\r\n this.obstacleChecker = obstacleChecker;\r\n this.config = { debugEnabled: false, scale: 1, ...config };\r\n }\r\n\r\n // 启发式距离\r\n private heuristic(a: THREE.Vector3, b: THREE.Vector3): number {\r\n return a.distanceTo(b);\r\n }\r\n\r\n // A* 寻路主入口\r\n findPath(start: THREE.Vector3, goal: THREE.Vector3): THREE.Vector3[] {\r\n // 直线可达则直接返回\r\n if (!this.obstacleChecker.isBlocked(start, goal)) return [goal];\r\n\r\n // 生成候选导航节点\r\n const navigationPoints = this.obstacleChecker.getNavigationNodes(start, goal);\r\n const allNodes = [new PathNode(start), new PathNode(goal), ...navigationPoints.map((p) => new PathNode(p))];\r\n\r\n if (allNodes.length < 2) {\r\n console.warn(\"导航节点不足,返回直线路径\");\r\n return [goal];\r\n }\r\n\r\n const startNode = allNodes[0];\r\n const goalNode = allNodes[1];\r\n\r\n // 初始化起点代价\r\n startNode.g = 0;\r\n startNode.h = this.heuristic(startNode.position, goalNode.position);\r\n startNode.f = startNode.h;\r\n\r\n const openList = new PriorityQueue<PathNode>();\r\n const closedSet = new Set<PathNode>();\r\n const nodeEquals = (a: PathNode, b: PathNode) => a.equals(b);\r\n openList.enqueue(startNode, startNode.f);\r\n\r\n // A* 主循环\r\n while (!openList.isEmpty()) {\r\n const current = openList.dequeue();\r\n if (!current) break;\r\n\r\n // 到达目标,重建路径\r\n if (current.equals(goalNode)) {\r\n const path = this.reconstructPath(current);\r\n if (this.config.debugEnabled) this.visualizePath([start, ...path]);\r\n return path;\r\n }\r\n\r\n closedSet.add(current);\r\n\r\n // 遍历所有邻居节点\r\n for (const neighbor of allNodes) {\r\n if (closedSet.has(neighbor)) continue;\r\n if (this.obstacleChecker.isBlocked(current.position, neighbor.position)) continue;\r\n\r\n const tentativeG = current.g + current.position.distanceTo(neighbor.position);\r\n if (tentativeG < neighbor.g) {\r\n neighbor.parent = current;\r\n neighbor.g = tentativeG;\r\n neighbor.h = this.heuristic(neighbor.position, goalNode.position);\r\n neighbor.f = neighbor.g + neighbor.h;\r\n\r\n if (openList.contains(neighbor, nodeEquals)) openList.update(neighbor, neighbor.f, nodeEquals);\r\n else openList.enqueue(neighbor, neighbor.f);\r\n }\r\n }\r\n }\r\n\r\n console.warn(\"A* 未找到路径,使用直线路径\");\r\n return [goal];\r\n }\r\n\r\n // 重建路径\r\n private reconstructPath(endNode: PathNode): THREE.Vector3[] {\r\n const path: THREE.Vector3[] = [];\r\n let current: PathNode | null = endNode;\r\n while (current !== null) {\r\n path.unshift(current.position.clone());\r\n current = current.parent;\r\n }\r\n // 移除起点,再平滑\r\n if (path.length > 0) path.shift();\r\n return this.smoothPath(path);\r\n }\r\n\r\n // 路径平滑优化\r\n private smoothPath(path: THREE.Vector3[]): THREE.Vector3[] {\r\n if (path.length <= 2) return path;\r\n const smoothed: THREE.Vector3[] = [path[0]];\r\n let current = 0;\r\n while (current < path.length - 1) {\r\n // 尽量跳过中间节点\r\n let farthest = current + 1;\r\n for (let i = path.length - 1; i > current + 1; i--) {\r\n if (!this.obstacleChecker.isBlocked(path[current], path[i])) { farthest = i; break; }\r\n }\r\n smoothed.push(path[farthest]);\r\n current = farthest;\r\n }\r\n return smoothed;\r\n }\r\n\r\n // 可视化路径\r\n private visualizePath(path: THREE.Vector3[]) {\r\n if (!this.config.scene || !this.config.debugEnabled) return;\r\n this.clearVisualization();\r\n const scale = this.config.scale || 1;\r\n\r\n // 绘制路径连线\r\n if (path.length > 1) {\r\n const geometry = new THREE.BufferGeometry().setFromPoints(path.map(p => p.clone()));\r\n const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0x00ff00, linewidth: 3 }));\r\n this.config.scene.add(line);\r\n this.debugLines.push(line);\r\n }\r\n\r\n // 绘制路径节点球体\r\n path.forEach((point, index) => {\r\n const sphere = new THREE.Mesh(\r\n new THREE.SphereGeometry(20 * scale),\r\n new THREE.MeshBasicMaterial({ color: index === path.length - 1 ? 0xff0000 : 0x00ff00 }),\r\n );\r\n sphere.position.copy(point);\r\n this.config.scene!.add(sphere);\r\n this.debugPoints.push(sphere);\r\n });\r\n }\r\n\r\n // 清除路径可视化\r\n clearVisualization() {\r\n if (!this.config.scene) return;\r\n this.debugLines.forEach(line => {\r\n this.config.scene!.remove(line);\r\n line.geometry.dispose();\r\n (line.material as THREE.Material).dispose();\r\n });\r\n this.debugLines = [];\r\n this.debugPoints.forEach(point => {\r\n this.config.scene!.remove(point);\r\n point.geometry.dispose();\r\n (point.material as THREE.Material).dispose();\r\n });\r\n this.debugPoints = [];\r\n }\r\n\r\n // 更新配置\r\n updateConfig(config: Partial<PathPlannerConfig>) {\r\n this.config = { ...this.config, ...config };\r\n }\r\n\r\n // 销毁规划器\r\n dispose() {\r\n this.clearVisualization();\r\n }\r\n}","import type { World } from \"@dimforge/rapier3d-compat\";\r\nimport * as THREE from \"three\";\r\n\r\nexport type WheelInfo = {\r\n axleCs: THREE.Vector3;\r\n suspensionRestLength: number;\r\n position: THREE.Vector3;\r\n radius: number;\r\n};\r\n\r\n// 创建车辆控制器\r\nexport function createVehicleController(\r\n world: World,\r\n chassisBody: any,\r\n wheels: (THREE.Object3D | null)[],\r\n wheelsInfo: WheelInfo[],\r\n) {\r\n if (!world || !chassisBody) return { vehicle: null, updateWheelVisuals: () => {} };\r\n\r\n const vehicle = world.createVehicleController(chassisBody);\r\n const suspensionDirection = new THREE.Vector3(0, -1, 0);\r\n\r\n // 注册每个轮子的物理参数\r\n wheelsInfo.forEach((wheel, index) => {\r\n vehicle.addWheel(wheel.position, suspensionDirection, wheel.axleCs, wheel.suspensionRestLength, wheel.radius);\r\n vehicle.setWheelChassisConnectionPointCs(index, wheel.position); // 连接点\r\n vehicle.setWheelDirectionCs(index, suspensionDirection); // 悬挂方向\r\n vehicle.setWheelAxleCs(index, wheel.axleCs); // 轮轴方向\r\n vehicle.setWheelSuspensionRestLength(index, wheel.suspensionRestLength); // 静止长度\r\n vehicle.setWheelRadius(index, wheel.radius); // 轮胎半径\r\n vehicle.setWheelMaxSuspensionTravel(index, wheel.suspensionRestLength); // 最大行程\r\n vehicle.setWheelSuspensionStiffness(index, 250); // 悬挂刚度\r\n vehicle.setWheelSuspensionCompression(index, 6); // 压缩阻尼\r\n vehicle.setWheelSuspensionRelaxation(index, 6); // 回弹阻尼\r\n vehicle.setWheelMaxSuspensionForce(index, 10000); // 最大作用力\r\n vehicle.setWheelBrake(index, 0); // 制动\r\n vehicle.setWheelSteering(index, 0); // 转向角\r\n vehicle.setWheelEngineForce(index, 0); // 驱动力\r\n vehicle.setWheelFrictionSlip(index, 20); // 纵向抓地\r\n vehicle.setWheelSideFrictionStiffness(index, 2); // 侧向摩擦\r\n });\r\n\r\n const up = new THREE.Vector3(0, 1, 0);\r\n const wheelSteeringQuat = new THREE.Quaternion();\r\n const wheelRotationQuat = new THREE.Quaternion();\r\n\r\n // 同步轮子视觉旋转\r\n function updateWheelVisuals() {\r\n for (const [index, wheelObj] of wheels.entries()) {\r\n if (!wheelObj) continue;\r\n try {\r\n const wheelAxleCs = vehicle.wheelAxleCs(index) ?? new THREE.Vector3(1, 0, 0);\r\n const connection = vehicle.wheelChassisConnectionPointCs(index)?.y ?? 0;\r\n const suspension = vehicle.wheelSuspensionLength(index) ?? 0;\r\n const steering = vehicle.wheelSteering(index) ?? 0;\r\n const rotationRad = vehicle.wheelRotation(index) ?? 0;\r\n\r\n // 悬挂压缩偏移\r\n wheelObj.position.y = connection - suspension;\r\n // 转向 * 自转\r\n wheelSteeringQuat.setFromAxisAngle(up, steering);\r\n wheelRotationQuat.setFromAxisAngle(wheelAxleCs, rotationRad);\r\n wheelObj.quaternion.copy(wheelSteeringQuat).multiply(wheelRotationQuat);\r\n } catch (e) {}\r\n }\r\n }\r\n\r\n // 销毁车辆控制器\r\n function destroy() {\r\n try { world.removeVehicleController(vehicle); } catch { }\r\n }\r\n\r\n return { vehicle, updateWheelVisuals, destroy };\r\n}"],"mappings":"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","names":["THREE","THREE","THREE","v"]}