feat: more progress

This commit is contained in:
TrèsAbhi committed 2024-02-28 23:06:37 -06:00
1 parent f55313e0cd
commit 7f49245f15
4 files changed
+95 -67

No files matched your search

@@ -5,7 +5,7 @@ import { Canvas } from '@react-three/fiber';
import { Suspense, use, useEffect, useRef, useState } from 'react'; import { Suspense, use, useEffect, useRef, useState } from 'react';
import { isMobile } from 'react-device-detect'; import { isMobile } from 'react-device-detect';
import { Armor } from '../../../../../../components/Armor'; import { Armor } from '../../../../../../components/Armor';
import { ShotScene } from '../../../../../../components/Armor/components/ShotScene'; import { ShotDisplay } from '../../../../../../components/Armor/components/ShotDisplay';
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions'; import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions';
import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform'; import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform';
@@ -201,6 +201,7 @@ export function TankSandbox() {
<Lighting /> <Lighting />
<TankModel /> <TankModel />
<Armor /> <Armor />
<ShotDisplay />
</Suspense> </Suspense>
</Canvas> </Canvas>
</div> </div>
@@ -1,6 +1,6 @@
import { Text } from '@radix-ui/themes'; import { Text } from '@radix-ui/themes';
import { Html } from '@react-three/drei'; import { Html } from '@react-three/drei';
import { DoubleSide, Euler, Quaternion, Vector3 } from 'three'; import { Euler, Quaternion, Vector3 } from 'three';
import { J_HAT } from '../../../constants/axis'; import { J_HAT } from '../../../constants/axis';
import { import {
ShotLayerGap, ShotLayerGap,
@@ -22,7 +22,7 @@ import {
// const THICKNESS = 0.05; // const THICKNESS = 0.05;
// const LENGTH = 4; // const LENGTH = 4;
export function ShotScene() { export function ShotDisplay() {
const shot = useTankopediaTemporary((state) => state.shot); const shot = useTankopediaTemporary((state) => state.shot);
return ( return (
@@ -39,28 +39,39 @@ export function ShotScene() {
return ( return (
<> <>
<mesh renderOrder={1} key={`${index}-point`} position={layer.point}>
<icosahedronGeometry args={[1 / 16, 1]} />
<meshBasicMaterial
side={DoubleSide}
color={
layer.status === 'penetration'
? 0x00ff00
: layer.status === 'blocked'
? 0xff0000
: 0xffff00
}
/>
</mesh>
<group <group
key={`${index}-line`} key={`${index}-line`}
position={layer.point} position={layer.point}
rotation={shellRotation} rotation={shellRotation}
> >
{shot.length > 1 && ( {shot.length > 1 && (
<Html> <Html center>
<Text>{layer.index + 1}</Text> <div
style={{
width: 12,
height: 12,
borderRadius: '100%',
position: 'relative',
backgroundColor:
layer.status === 'penetration'
? '#00ff00'
: layer.status === 'blocked'
? '#ff0000'
: '#ffff00',
}}
>
<Text
style={{
position: 'absolute',
left: '100%',
top: '50%',
transform: 'translateY(-50%)',
marginLeft: 8,
}}
>
{layer.index + 1}
</Text>
</div>
</Html> </Html>
)} )}
@@ -73,9 +84,9 @@ export function ShotScene() {
} }
return ( return (
<mesh position={[0, length / 2, 0]} renderOrder={0}> <mesh position={[0, length / 2, 0]}>
<cylinderGeometry args={[1 / 64, 1 / 64, length]} /> <cylinderGeometry args={[1 / 64, 1 / 64, length]} />
<meshBasicMaterial color={0xffffff} /> <meshBasicMaterial color={0xffffff} depthTest={false} />
</mesh> </mesh>
); );
})()} })()}
@@ -8,13 +8,17 @@ import {
Scene, Scene,
Vector3, Vector3,
} from 'three'; } from 'three';
import { degToRad, radToDeg } from 'three/src/math/MathUtils'; import { degToRad } from 'three/src/math/MathUtils';
import { isExplosive } from '../../../../core/blitz/isExplosive'; import { isExplosive } from '../../../../core/blitz/isExplosive';
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration'; import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
import { hasEquipment } from '../../../../core/blitzkrieg/hasEquipment'; import { hasEquipment } from '../../../../core/blitzkrieg/hasEquipment';
import { jsxTree } from '../../../../core/blitzkrieg/jsxTree'; import { jsxTree } from '../../../../core/blitzkrieg/jsxTree';
import { useDuel } from '../../../../stores/duel'; import { useDuel } from '../../../../stores/duel';
import { Shot, useTankopediaTemporary } from '../../../../stores/tankopedia'; import {
Shot,
ShotLayerBase,
useTankopediaTemporary,
} from '../../../../stores/tankopedia';
import { ArmorType } from '../SpacedArmorScene'; import { ArmorType } from '../SpacedArmorScene';
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal'; import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced'; import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced';
@@ -68,7 +72,7 @@ export function SpacedArmorSceneComponent({
...props ...props
}: SpacedArmorSceneComponentProps) { }: SpacedArmorSceneComponentProps) {
const camera = useThree((state) => state.camera); const camera = useThree((state) => state.camera);
const cameraNormal = new Vector3(); // const cameraNormal = new Vector3();
return ( return (
<> <>
@@ -104,26 +108,26 @@ export function SpacedArmorSceneComponent({
.clone() .clone()
.sub(event.point) .sub(event.point)
.normalize(); .normalize();
shellNormal const cameraNormal = shellNormal.clone().multiplyScalar(-1);
.copy(camera.getWorldDirection(cameraNormal))
.multiplyScalar(-1);
pushLogs( pushLogs(
shellNormal, shellNormal,
cameraNormal,
filterIntersections(event.intersections), filterIntersections(event.intersections),
true, 0,
); );
console.clear(); // console.clear();
console.log( // console.log(
JSON.stringify( // JSON.stringify(
shot.map((i) => ({ // shot.map((i) => ({
...i, // ...i,
...(i.angle ? { angle: radToDeg(i.angle) } : {}), // ...(i.angle ? { angle: radToDeg(i.angle) } : {}),
})), // })),
null, // null,
2, // 2,
), // ),
); // );
function filterIntersections(intersectionsRaw: Intersection[]) { function filterIntersections(intersectionsRaw: Intersection[]) {
const intersectionsAll = intersectionsRaw.filter( const intersectionsAll = intersectionsRaw.filter(
@@ -166,15 +170,35 @@ export function SpacedArmorSceneComponent({
}); });
} }
console.log(
JSON.stringify(
intersections.map((i) => i.object.userData),
null,
2,
),
);
return intersections; return intersections;
} }
function pushLogs( function pushLogs(
shellNormal: Vector3, shellNormal: Vector3,
cameraNormal: Vector3,
intersections: ArmorMeshIntersection[], intersections: ArmorMeshIntersection[],
allowRicochets: boolean, startingIndex: number,
) { ) {
let index = 0; let layerIndex = startingIndex;
let loopIndex = 0;
if (layerIndex !== 0) {
shot.push({
type: null,
distance: (shot.at(-1) as ShotLayerBase).point.distanceTo(
intersections[0].point,
),
});
}
for (const intersection of intersections) { for (const intersection of intersections) {
const surfaceNormal = intersection const surfaceNormal = intersection
.normal!.clone() .normal!.clone()
@@ -184,8 +208,8 @@ export function SpacedArmorSceneComponent({
const thickness = const thickness =
thicknessCoefficient * intersection.object.userData.thickness; thicknessCoefficient * intersection.object.userData.thickness;
if (index !== 0) { if (layerIndex !== 0 && startingIndex === 0) {
const previousIntersection = intersections[index - 1]; const previousIntersection = intersections[layerIndex - 1];
shot.push({ shot.push({
type: null, type: null,
distance: distance:
@@ -199,7 +223,7 @@ export function SpacedArmorSceneComponent({
shot.push({ shot.push({
type: ArmorType.External, type: ArmorType.External,
index, index: layerIndex,
shellNormal, shellNormal,
surfaceNormal, surfaceNormal,
point: intersection.point, point: intersection.point,
@@ -210,19 +234,11 @@ export function SpacedArmorSceneComponent({
if (blocked) break; if (blocked) break;
} else { } else {
const type = intersection.object.userData.type; const type = intersection.object.userData.type;
shellNormal.copy(
cameraNormal
.copy(camera.position)
.sub(event.point)
.normalize(),
);
const angle = surfaceNormal.angleTo(shellNormal); const angle = surfaceNormal.angleTo(shellNormal);
const ricochet = degToRad(shell.ricochet ?? 90); const ricochet = degToRad(shell.ricochet ?? 90);
const normalization = degToRad(shell.normalization ?? 0); const normalization = degToRad(shell.normalization ?? 0);
const threeCalibersRule = const threeCalibersRule =
shell.caliber > thickness * 3 || shell.caliber > thickness * 3 || layerIndex > 0;
index > 0 ||
!allowRicochets;
const twoCalibersRule = shell.caliber > thickness * 2; const twoCalibersRule = shell.caliber > thickness * 2;
const finalNormalization = twoCalibersRule const finalNormalization = twoCalibersRule
? (1.4 * normalization * shell.caliber) / (2.0 * thickness) ? (1.4 * normalization * shell.caliber) / (2.0 * thickness)
@@ -234,7 +250,7 @@ export function SpacedArmorSceneComponent({
if (!threeCalibersRule && angle >= ricochet) { if (!threeCalibersRule && angle >= ricochet) {
shot.push({ shot.push({
type, type,
index, index: layerIndex,
shellNormal, shellNormal,
surfaceNormal, surfaceNormal,
point: intersection.point, point: intersection.point,
@@ -245,15 +261,21 @@ export function SpacedArmorSceneComponent({
}); });
const raycaster = new Raycaster(); const raycaster = new Raycaster();
const newShellNormal = cameraNormal const newShellNormal = shellNormal
.clone() .clone()
.reflect(surfaceNormal); .reflect(surfaceNormal);
const newCameraNormal = newShellNormal
.clone()
.multiplyScalar(-1);
raycaster.set(intersection.point, newShellNormal); raycaster.set(intersection.point, newCameraNormal);
pushLogs( pushLogs(
newShellNormal, newShellNormal,
raycaster.intersectObjects(scene.children, true), newCameraNormal,
false, filterIntersections(
raycaster.intersectObjects(scene.children, true),
),
layerIndex + 1,
); );
break; break;
@@ -261,7 +283,7 @@ export function SpacedArmorSceneComponent({
const blocked = remainingPenetration < 0; const blocked = remainingPenetration < 0;
shot.push({ shot.push({
type, type,
index, index: layerIndex,
shellNormal, shellNormal,
surfaceNormal, surfaceNormal,
point: intersection.point, point: intersection.point,
@@ -273,7 +295,8 @@ export function SpacedArmorSceneComponent({
} }
} }
index++; layerIndex++;
loopIndex++;
} }
} }
-7
View File
@@ -3,19 +3,16 @@ import { memo, useState } from 'react';
import { DepthTexture, Scene, Vector2 } from 'three'; import { DepthTexture, Scene, Vector2 } from 'three';
import { CoreArmorScene } from './components/CoreArmorScene'; import { CoreArmorScene } from './components/CoreArmorScene';
import { spacedArmorRenderTarget } from './components/CoreArmorSceneComponent'; import { spacedArmorRenderTarget } from './components/CoreArmorSceneComponent';
import { ShotScene } from './components/ShotScene';
import { SpacedArmorScene } from './components/SpacedArmorScene'; import { SpacedArmorScene } from './components/SpacedArmorScene';
export const Armor = memo(() => { export const Armor = memo(() => {
const [spacedArmorScene] = useState(() => new Scene()); const [spacedArmorScene] = useState(() => new Scene());
const [coreArmorScene] = useState(() => new Scene()); const [coreArmorScene] = useState(() => new Scene());
const [shotScene] = useState(() => new Scene());
const spacedArmorPortal = createPortal( const spacedArmorPortal = createPortal(
<SpacedArmorScene scene={spacedArmorScene} />, <SpacedArmorScene scene={spacedArmorScene} />,
spacedArmorScene, spacedArmorScene,
); );
const coreArmorPortal = createPortal(<CoreArmorScene />, coreArmorScene); const coreArmorPortal = createPortal(<CoreArmorScene />, coreArmorScene);
const shotPortal = createPortal(<ShotScene />, shotScene);
const renderSize = new Vector2(); const renderSize = new Vector2();
const newRenderSize = new Vector2(); const newRenderSize = new Vector2();
@@ -44,16 +41,12 @@ export const Armor = memo(() => {
gl.clearDepth(); gl.clearDepth();
gl.render(coreArmorScene, camera); gl.render(coreArmorScene, camera);
gl.clearDepth();
gl.render(shotScene, camera);
}, 1); }, 1);
return ( return (
<> <>
{spacedArmorPortal} {spacedArmorPortal}
{coreArmorPortal} {coreArmorPortal}
{shotPortal}
</> </>
); );
}); });