mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-30 22:19:50 +01:00
more robust contorls
This commit is contained in:
1 parent
39aeba0766
commit
59ef527967
3 files changed
+37
-26
No files matched your search
@@ -1,26 +1,22 @@
|
|||||||
import { J_HAT, K_HAT } from "@blitzkit/core";
|
import { I_HAT, J_HAT } from "@blitzkit/core";
|
||||||
import { invalidate, useThree } from "@react-three/fiber";
|
import { invalidate, useThree } from "@react-three/fiber";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { Vector2, Vector3 } from "three";
|
import { Quaternion, Vector2, Vector3 } from "three";
|
||||||
import { degToRad } from "three/src/math/MathUtils.js";
|
import { degToRad } from "three/src/math/MathUtils.js";
|
||||||
|
|
||||||
const initialDistance = 8;
|
|
||||||
const initialRotation = new Vector2(degToRad(45), degToRad(45));
|
|
||||||
|
|
||||||
const clientPosition = new Vector2();
|
const clientPosition = new Vector2();
|
||||||
const workingVector2 = new Vector2();
|
|
||||||
const workingVector3 = new Vector3();
|
const workingVector3 = new Vector3();
|
||||||
|
const workingQuaternion = new Quaternion();
|
||||||
|
|
||||||
const cameraCenter = new Vector3(0, 1, 0);
|
const cameraCenter = new Vector3(0, 1, 0);
|
||||||
|
|
||||||
const cameraRotation = initialRotation.clone();
|
|
||||||
let cameraDistance = initialDistance;
|
|
||||||
|
|
||||||
export function TankopediaControls() {
|
export function TankopediaControls() {
|
||||||
const canvas = useThree((state) => state.gl.domElement);
|
const canvas = useThree((state) => state.gl.domElement);
|
||||||
const camera = useThree((state) => state.camera);
|
const camera = useThree((state) => state.camera);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
setCameraPosition(15, degToRad(90 - 20), degToRad(90 + 25));
|
||||||
|
|
||||||
function handlePointerDown(event: PointerEvent) {
|
function handlePointerDown(event: PointerEvent) {
|
||||||
clientPosition.set(event.clientX, event.clientY);
|
clientPosition.set(event.clientX, event.clientY);
|
||||||
|
|
||||||
@@ -29,20 +25,24 @@ export function TankopediaControls() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handlePointerMove(event: PointerEvent) {
|
function handlePointerMove(event: PointerEvent) {
|
||||||
workingVector2.set(event.clientX, event.clientY).sub(clientPosition);
|
event.preventDefault();
|
||||||
|
|
||||||
workingVector2.x *= -(2 * Math.PI) / canvas.width;
|
workingVector3.copy(camera.position).sub(cameraCenter);
|
||||||
workingVector2.y *= (2 * Math.PI) / canvas.height;
|
|
||||||
|
|
||||||
cameraRotation.x += workingVector2.x;
|
const r = workingVector3.length();
|
||||||
|
const dx = event.movementX / window.innerWidth;
|
||||||
|
const dy = event.movementY / window.innerHeight;
|
||||||
|
|
||||||
if (cameraRotation.y + workingVector2.y < Math.PI / 2) {
|
const dTheta = -dx * Math.PI;
|
||||||
cameraRotation.y += workingVector2.y;
|
const dPhi = -dy * Math.PI;
|
||||||
}
|
|
||||||
|
|
||||||
clientPosition.set(event.clientX, event.clientY);
|
const theta = Math.atan2(workingVector3.x, workingVector3.z) + dTheta;
|
||||||
|
const phi0 = Math.acos(workingVector3.y / r);
|
||||||
|
let phi = phi0 + dPhi;
|
||||||
|
|
||||||
updateCameraPosition();
|
if (phi < 0 || phi > Math.PI) phi = phi0;
|
||||||
|
|
||||||
|
setCameraPosition(r, phi, theta);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePointerUp() {
|
function handlePointerUp() {
|
||||||
@@ -50,13 +50,20 @@ export function TankopediaControls() {
|
|||||||
window.removeEventListener("pointerup", handlePointerUp);
|
window.removeEventListener("pointerup", handlePointerUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCameraPosition() {
|
function setCameraPosition(r: number, phi: number, theta: number) {
|
||||||
camera.position
|
workingVector3
|
||||||
.set(cameraDistance, 0, 0)
|
.set(
|
||||||
.applyAxisAngle(J_HAT, cameraRotation.x)
|
Math.sin(phi) * Math.sin(theta),
|
||||||
.applyAxisAngle(K_HAT, cameraRotation.y)
|
Math.cos(phi),
|
||||||
.add(cameraCenter);
|
Math.sin(phi) * Math.cos(theta),
|
||||||
camera.lookAt(cameraCenter);
|
)
|
||||||
|
.multiplyScalar(r);
|
||||||
|
camera.position.copy(cameraCenter).add(workingVector3);
|
||||||
|
|
||||||
|
workingQuaternion.setFromAxisAngle(I_HAT, phi - Math.PI / 2);
|
||||||
|
camera.quaternion
|
||||||
|
.setFromAxisAngle(J_HAT, theta)
|
||||||
|
.multiply(workingQuaternion);
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -67,4 +74,6 @@ export function TankopediaControls() {
|
|||||||
canvas.removeEventListener("pointerdown", handlePointerDown);
|
canvas.removeEventListener("pointerdown", handlePointerDown);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { type StageParameters } from "@protos/blitz_static_tank_upgrade_single_stage";
|
import { type StageParameters } from "@protos/blitz_static_tank_upgrade_single_stage";
|
||||||
import { Canvas } from "@react-three/fiber";
|
import { Canvas } from "@react-three/fiber";
|
||||||
|
import { fov } from "../../config/fov";
|
||||||
import { useTankChassisModel } from "../../hooks/useTankChassisModel";
|
import { useTankChassisModel } from "../../hooks/useTankChassisModel";
|
||||||
import { useTankGunModel } from "../../hooks/useTankGunModel";
|
import { useTankGunModel } from "../../hooks/useTankGunModel";
|
||||||
import { useTankHullModel } from "../../hooks/useTankHullModel";
|
import { useTankHullModel } from "../../hooks/useTankHullModel";
|
||||||
@@ -18,7 +19,7 @@ export function TankopediaSandbox({ parameters }: TankopediaSandboxProps) {
|
|||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<div className={styles.sandbox}>
|
<div className={styles.sandbox}>
|
||||||
<Canvas
|
<Canvas
|
||||||
camera={{ fov: 40 }}
|
camera={{ fov }}
|
||||||
shadows
|
shadows
|
||||||
className={styles.canvas}
|
className={styles.canvas}
|
||||||
frameloop="demand"
|
frameloop="demand"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export const fov = 20;
|
||||||
Reference in new issue
Block a user