feat: gun pitch

This commit is contained in:
TrèsAbhi committed 2024-01-02 14:07:40 -06:00
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 { 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 { OrbitControls as OrbitControlsImpl } from 'three-stdlib';
@@ -9,23 +9,24 @@ interface TankAlignmentProps {
orbit: boolean;
}
export function TankAlignment({ model, orbit }: TankAlignmentProps) {
const controls = useRef<OrbitControlsImpl>(null);
const camera = useThree((state) => state.camera);
export const TankAlignment = memo(
({ model, orbit }: TankAlignmentProps) => {
const controls = useRef<OrbitControlsImpl>(null);
const camera = useThree((state) => state.camera);
useEffect(() => {
const box = new Box3().setFromObject(model.current!);
const diameter = Math.max(box.max.x - box.min.x, box.max.z - box.min.z);
useEffect(() => {
const box = new Box3().setFromObject(model.current!);
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);
camera.position.set(-5, (box.min.y + box.max.y) / 2, -15);
}, []);
return (
<OrbitControls
ref={controls}
enabled={orbit}
target={new Vector3(0, 2, 0)}
/>
);
}
return (
<OrbitControls
ref={controls}
enabled={orbit}
target={new Vector3(0, 2, 0)}
/>
);
},
() => false,
);
+102 -24
View File
@@ -74,6 +74,7 @@ export default function Page({ params }: { params: { id: string } }) {
const turretRotationInput = useRef<HTMLInputElement>(null);
const hullRotationInput = useRef<HTMLInputElement>(null);
const gunRotationInput = useRef<HTMLInputElement>(null);
const mantletContainer = useRef<Group>(null);
useEffect(() => {
if (!turret.guns.some(({ id }) => gun.id === id)) {
@@ -203,9 +204,8 @@ export default function Page({ params }: { params: { id: string } }) {
const rotationSpeed =
(2 * Math.PI) / canvas.current!.width;
const deltaTurretRotation =
event.movementX * rotationSpeed;
draftTurretRotation += deltaTurretRotation;
const delta = event.movementX * rotationSpeed;
draftTurretRotation += delta;
if (hullContainer.current) {
hullContainer.current.rotation.z =
@@ -259,20 +259,7 @@ export default function Page({ params }: { params: { id: string } }) {
`turret_${turret.model
.toString()
.padStart(2, '0')}`;
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 =
isCurrentTurret || isCurrentGun || isCurrentMantlet;
const isVisible = isCurrentTurret;
let draftTurretRotation = 0;
if (!isVisible) return null;
@@ -302,17 +289,13 @@ export default function Page({ params }: { params: { id: string } }) {
const rotationSpeed =
(2 * Math.PI) / canvas.current!.width;
const deltaTurretRotation =
event.movementX * rotationSpeed;
draftTurretRotation += deltaTurretRotation;
const delta = event.movementX * rotationSpeed;
draftTurretRotation += delta;
if (turretContainer.current) {
turretContainer.current.position
.sub(turretOrigin)
.applyAxisAngle(
new Vector3(0, 0, 1),
deltaTurretRotation,
)
.applyAxisAngle(new Vector3(0, 0, 1), delta)
.add(turretOrigin);
turretContainer.current.rotation.z =
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>
</Canvas>