mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: gun pitch
This commit is contained in:
1 parent
0d5b2aedc7
commit
9bd26ef3bf
2 files changed
+122
-43
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
import { OrbitControls } from '@react-three/drei';
|
import { OrbitControls } from '@react-three/drei';
|
||||||
import { useThree } from '@react-three/fiber';
|
import { useThree } from '@react-three/fiber';
|
||||||
import { RefObject, useEffect, useRef } from 'react';
|
import { RefObject, memo, useEffect, useRef } from 'react';
|
||||||
import { Box3, Group, Vector3 } from 'three';
|
import { Box3, Group, Vector3 } from 'three';
|
||||||
import { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
|
import { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
|
||||||
|
|
||||||
@@ -9,23 +9,24 @@ interface TankAlignmentProps {
|
|||||||
orbit: boolean;
|
orbit: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TankAlignment({ model, orbit }: TankAlignmentProps) {
|
export const TankAlignment = memo(
|
||||||
const controls = useRef<OrbitControlsImpl>(null);
|
({ model, orbit }: TankAlignmentProps) => {
|
||||||
const camera = useThree((state) => state.camera);
|
const controls = useRef<OrbitControlsImpl>(null);
|
||||||
|
const camera = useThree((state) => state.camera);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const box = new Box3().setFromObject(model.current!);
|
const box = new Box3().setFromObject(model.current!);
|
||||||
const diameter = Math.max(box.max.x - box.min.x, box.max.z - box.min.z);
|
controls.current?.target.set(0, (2 * box.min.y + box.max.y) / 3, 0);
|
||||||
|
camera.position.set(-5, (box.min.y + box.max.y) / 2, -15);
|
||||||
|
}, []);
|
||||||
|
|
||||||
controls.current?.target.set(0, (2 * box.min.y + box.max.y) / 3, 0);
|
return (
|
||||||
camera.position.set(-5, (box.min.y + box.max.y) / 2, -15);
|
<OrbitControls
|
||||||
}, []);
|
ref={controls}
|
||||||
|
enabled={orbit}
|
||||||
return (
|
target={new Vector3(0, 2, 0)}
|
||||||
<OrbitControls
|
/>
|
||||||
ref={controls}
|
);
|
||||||
enabled={orbit}
|
},
|
||||||
target={new Vector3(0, 2, 0)}
|
() => false,
|
||||||
/>
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -74,6 +74,7 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
const turretRotationInput = useRef<HTMLInputElement>(null);
|
const turretRotationInput = useRef<HTMLInputElement>(null);
|
||||||
const hullRotationInput = useRef<HTMLInputElement>(null);
|
const hullRotationInput = useRef<HTMLInputElement>(null);
|
||||||
const gunRotationInput = useRef<HTMLInputElement>(null);
|
const gunRotationInput = useRef<HTMLInputElement>(null);
|
||||||
|
const mantletContainer = useRef<Group>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!turret.guns.some(({ id }) => gun.id === id)) {
|
if (!turret.guns.some(({ id }) => gun.id === id)) {
|
||||||
@@ -203,9 +204,8 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
const rotationSpeed =
|
const rotationSpeed =
|
||||||
(2 * Math.PI) / canvas.current!.width;
|
(2 * Math.PI) / canvas.current!.width;
|
||||||
const deltaTurretRotation =
|
const delta = event.movementX * rotationSpeed;
|
||||||
event.movementX * rotationSpeed;
|
draftTurretRotation += delta;
|
||||||
draftTurretRotation += deltaTurretRotation;
|
|
||||||
|
|
||||||
if (hullContainer.current) {
|
if (hullContainer.current) {
|
||||||
hullContainer.current.rotation.z =
|
hullContainer.current.rotation.z =
|
||||||
@@ -259,20 +259,7 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
`turret_${turret.model
|
`turret_${turret.model
|
||||||
.toString()
|
.toString()
|
||||||
.padStart(2, '0')}`;
|
.padStart(2, '0')}`;
|
||||||
const isMantlet =
|
const isVisible = isCurrentTurret;
|
||||||
child.name.startsWith('gun_') &&
|
|
||||||
child.name.endsWith('_mask');
|
|
||||||
const isCurrentMantlet =
|
|
||||||
child.name ===
|
|
||||||
`gun_${gun.model.toString().padStart(2, '0')}_mask`;
|
|
||||||
const isGun =
|
|
||||||
child.name.startsWith('gun_') && !isMantlet;
|
|
||||||
const isCurrentGun =
|
|
||||||
isGun &&
|
|
||||||
child.name ===
|
|
||||||
`gun_${gun.model.toString().padStart(2, '0')}`;
|
|
||||||
const isVisible =
|
|
||||||
isCurrentTurret || isCurrentGun || isCurrentMantlet;
|
|
||||||
let draftTurretRotation = 0;
|
let draftTurretRotation = 0;
|
||||||
|
|
||||||
if (!isVisible) return null;
|
if (!isVisible) return null;
|
||||||
@@ -302,17 +289,13 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
|
|
||||||
const rotationSpeed =
|
const rotationSpeed =
|
||||||
(2 * Math.PI) / canvas.current!.width;
|
(2 * Math.PI) / canvas.current!.width;
|
||||||
const deltaTurretRotation =
|
const delta = event.movementX * rotationSpeed;
|
||||||
event.movementX * rotationSpeed;
|
draftTurretRotation += delta;
|
||||||
draftTurretRotation += deltaTurretRotation;
|
|
||||||
|
|
||||||
if (turretContainer.current) {
|
if (turretContainer.current) {
|
||||||
turretContainer.current.position
|
turretContainer.current.position
|
||||||
.sub(turretOrigin)
|
.sub(turretOrigin)
|
||||||
.applyAxisAngle(
|
.applyAxisAngle(new Vector3(0, 0, 1), delta)
|
||||||
new Vector3(0, 0, 1),
|
|
||||||
deltaTurretRotation,
|
|
||||||
)
|
|
||||||
.add(turretOrigin);
|
.add(turretOrigin);
|
||||||
turretContainer.current.rotation.z =
|
turretContainer.current.rotation.z =
|
||||||
draftTurretRotation;
|
draftTurretRotation;
|
||||||
@@ -350,6 +333,101 @@ export default function Page({ params }: { params: { id: string } }) {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
|
<group
|
||||||
|
// position={new Vector3()
|
||||||
|
// .sub(turretOrigin)
|
||||||
|
// .applyAxisAngle(new Vector3(0, 0, 1), turretRotation)
|
||||||
|
// .add(turretOrigin)}
|
||||||
|
// rotation={[0, 0, turretRotation]}
|
||||||
|
ref={mantletContainer}
|
||||||
|
>
|
||||||
|
{gltf.scene.children[0].children.map((child) => {
|
||||||
|
const isMantlet =
|
||||||
|
child.name.startsWith('gun_') &&
|
||||||
|
child.name.endsWith('_mask');
|
||||||
|
const isCurrentMantlet =
|
||||||
|
child.name ===
|
||||||
|
`gun_${gun.model.toString().padStart(2, '0')}_mask`;
|
||||||
|
const isGun =
|
||||||
|
child.name.startsWith('gun_') && !isMantlet;
|
||||||
|
const isCurrentGun =
|
||||||
|
isGun &&
|
||||||
|
child.name ===
|
||||||
|
`gun_${gun.model.toString().padStart(2, '0')}`;
|
||||||
|
const isVisible = isCurrentGun || isCurrentMantlet;
|
||||||
|
let draftMantletPitch = 0;
|
||||||
|
|
||||||
|
if (!isVisible) return null;
|
||||||
|
|
||||||
|
function handlePointerDown(
|
||||||
|
event: ThreeEvent<PointerEvent>,
|
||||||
|
) {
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
draftMantletPitch = turretRotation;
|
||||||
|
|
||||||
|
setOrbitControlsEnabled(false);
|
||||||
|
window.addEventListener(
|
||||||
|
'pointermove',
|
||||||
|
handlePointerMove,
|
||||||
|
);
|
||||||
|
window.addEventListener(
|
||||||
|
'pointerup',
|
||||||
|
handlePointerUp,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function handlePointerMove(event: PointerEvent) {
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const rotationSpeed =
|
||||||
|
(2 * Math.PI) / canvas.current!.width;
|
||||||
|
const delta = -event.movementY * rotationSpeed;
|
||||||
|
draftMantletPitch += delta;
|
||||||
|
|
||||||
|
if (mantletContainer.current) {
|
||||||
|
mantletContainer.current.position
|
||||||
|
.sub(gunOrigin)
|
||||||
|
.applyAxisAngle(new Vector3(1, 0, 0), delta)
|
||||||
|
.add(gunOrigin);
|
||||||
|
mantletContainer.current.rotation.x =
|
||||||
|
draftMantletPitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handlePointerUp(event: PointerEvent) {
|
||||||
|
setOrbitControlsEnabled(true);
|
||||||
|
setTurretRotation(
|
||||||
|
normalizeAngle180(draftMantletPitch),
|
||||||
|
);
|
||||||
|
|
||||||
|
window.removeEventListener(
|
||||||
|
'pointermove',
|
||||||
|
handlePointerMove,
|
||||||
|
);
|
||||||
|
window.removeEventListener(
|
||||||
|
'pointerup',
|
||||||
|
handlePointerUp,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<mesh
|
||||||
|
visible={isVisible}
|
||||||
|
onPointerDown={handlePointerDown}
|
||||||
|
children={resolveJsxTree(child as Mesh)}
|
||||||
|
key={child.uuid}
|
||||||
|
castShadow
|
||||||
|
receiveShadow
|
||||||
|
geometry={(child as Mesh).geometry}
|
||||||
|
material={(child as Mesh).material}
|
||||||
|
position={child.position}
|
||||||
|
rotation={child.rotation}
|
||||||
|
scale={child.scale}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|||||||
Reference in new issue
Block a user