From b3a6a47a6a76a7e0b8ec69868177153cecd6b96f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:29:05 -0600 Subject: [PATCH] feat: start of new engine --- .../[id]/components/Model/TankSandbox.tsx | 18 +- .../components/ArmorHighlighting.tsx | 213 ------------- .../components/ExternalModuleMask.tsx | 286 ------------------ .../{SpacedArmorDepth.tsx => Spaced.tsx} | 88 +++--- .../Model/components/TankArmor/index.tsx | 67 ---- .../Armor/components/SpacedArmor.tsx | 34 +++ src/stores/tankopedia.ts | 3 +- 7 files changed, 82 insertions(+), 627 deletions(-) delete mode 100644 src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ArmorHighlighting.tsx delete mode 100644 src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ExternalModuleMask.tsx rename src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/{SpacedArmorDepth.tsx => Spaced.tsx} (83%) create mode 100644 src/components/Armor/components/SpacedArmor.tsx diff --git a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx index a8a087792..b73d552fd 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx @@ -4,7 +4,6 @@ import { PerspectiveCamera } from '@react-three/drei'; import { Canvas } from '@react-three/fiber'; import { Suspense, use, useEffect, useRef, useState } from 'react'; import { isMobile } from 'react-device-detect'; -import { ShotDisplay } from '../../../../../../components/ShotDisplay'; import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits'; import { modelDefinitions } from '../../../../../../core/blitzkrieg/modelDefinitions'; import { modelTransformEvent } from '../../../../../../core/blitzkrieg/modelTransform'; @@ -19,15 +18,10 @@ import mutateTankopediaPersistent, { } from '../../../../../../stores/tankopedia'; import { AntagonistBar } from '../AntagonistBar'; import { Controls } from '../Control'; -import { Lighting } from '../Lighting'; import { RotationInputs } from '../QuickInputs'; -import { SceneProps } from '../SceneProps'; import { ModelLoader } from './components/ModelLoader'; import { Options } from './components/Options'; -import { TankArmor } from './components/TankArmor'; -import { ExternalModuleMask } from './components/TankArmor/components/ExternalModuleMask'; -import { SpacedArmorDepth } from './components/TankArmor/components/SpacedArmorDepth'; -import { TankModel } from './components/TankModel'; +import { SpacedArmorScene } from './components/TankArmor/components/Spaced'; export function TankSandbox() { const canvas = useRef(null); @@ -195,15 +189,13 @@ export function TankSandbox() { > - + {/* */} }> - + {/* - - - - + */} + diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ArmorHighlighting.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ArmorHighlighting.tsx deleted file mode 100644 index e547a01fe..000000000 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ArmorHighlighting.tsx +++ /dev/null @@ -1,213 +0,0 @@ -import { useEffect, useRef } from 'react'; -import { Euler, Group, Mesh, Vector3 } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; -import { ArmorMesh } from '../../../../../../../../../components/ArmorMesh'; -import { I_HAT, J_HAT, K_HAT } from '../../../../../../../../../constants/axis'; -import { - ModelTransformEventData, - modelTransformEvent, -} from '../../../../../../../../../core/blitzkrieg/modelTransform'; -import { nameToArmorId } from '../../../../../../../../../core/blitzkrieg/nameToArmorId'; -import { resolveArmor } from '../../../../../../../../../core/blitzkrieg/resolveThickness'; -import { useArmor } from '../../../../../../../../../hooks/useArmor'; -import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions'; -import { useDuel } from '../../../../../../../../../stores/duel'; -import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia'; - -export function ArmorHighlighting() { - const protagonist = useDuel((state) => state.protagonist!); - const wrapper = useRef(null); - const modelDefinitions = useModelDefinitions(); - const gunContainer = useRef(null); - const turretContainer = useRef(null); - const initialTankopediaState = useTankopediaPersistent.getState(); - - useEffect(() => { - const hullOrigin = new Vector3( - trackModelDefinition.origin[0], - trackModelDefinition.origin[1], - -trackModelDefinition.origin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const turretOrigin = new Vector3( - tankModelDefinition.turretOrigin[0], - tankModelDefinition.turretOrigin[1], - -tankModelDefinition.turretOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const turretPosition = new Vector3(); - const turretRotation = new Euler(); - const gunPosition = new Vector3(); - const gunRotation = new Euler(); - - function handleModelTransform({ pitch, yaw }: ModelTransformEventData) { - if (yaw === undefined) return; - - gunPosition - .set(0, 0, 0) - .sub(hullOrigin) - .sub(turretOrigin) - .sub(gunOrigin) - .applyAxisAngle(I_HAT, pitch) - .add(gunOrigin) - .add(turretOrigin) - .add(hullOrigin); - gunRotation.set(pitch, 0, 0); - gunContainer.current?.position.copy(gunPosition); - gunContainer.current?.rotation.copy(gunRotation); - turretPosition - .set(0, 0, 0) - .sub(hullOrigin) - .sub(turretOrigin) - .applyAxisAngle(new Vector3(0, 0, 1), yaw); - turretRotation.set(0, 0, yaw); - - if (tankModelDefinition.turretRotation) { - const initialPitch = -degToRad( - tankModelDefinition.turretRotation.pitch, - ); - const initialYaw = -degToRad(tankModelDefinition.turretRotation.yaw); - const initialRoll = -degToRad(tankModelDefinition.turretRotation.roll); - - turretPosition - .applyAxisAngle(I_HAT, initialPitch) - .applyAxisAngle(J_HAT, initialRoll) - .applyAxisAngle(K_HAT, initialYaw); - turretRotation.x += initialPitch; - turretRotation.y += initialRoll; - turretRotation.z += initialYaw; - } - - turretPosition.add(turretOrigin).add(hullOrigin); - turretContainer.current?.position.copy(turretPosition); - turretContainer.current?.rotation.copy(turretRotation); - } - const unsubscribe = useTankopediaPersistent.subscribe( - (state) => state.mode, - (mode) => { - if (wrapper.current) wrapper.current.visible = mode === 'armor'; - }, - ); - - handleModelTransform(protagonist); - modelTransformEvent.on(handleModelTransform); - - return () => { - modelTransformEvent.off(handleModelTransform); - unsubscribe(); - }; - }); - - const armorGltf = useArmor(protagonist.tank.id); - const armorNodes = Object.values(armorGltf.nodes); - const tankModelDefinition = modelDefinitions[protagonist.tank.id]; - const trackModelDefinition = tankModelDefinition.tracks[protagonist.track.id]; - const turretModelDefinition = - tankModelDefinition.turrets[protagonist.turret.id]; - const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; - const hullOrigin = new Vector3( - trackModelDefinition.origin[0], - trackModelDefinition.origin[1], - -trackModelDefinition.origin[2], - ); - const turretOrigin = new Vector3( - tankModelDefinition.turretOrigin[0], - tankModelDefinition.turretOrigin[1], - -tankModelDefinition.turretOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const gunOrigin = new Vector3( - turretModelDefinition.gunOrigin[0], - turretModelDefinition.gunOrigin[1], - -turretModelDefinition.gunOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const maxThickness = Math.max( - trackModelDefinition.thickness, - gunModelDefinition.thickness, - ...armorNodes - .map((node) => { - const armorId = nameToArmorId(node.name); - return resolveArmor(tankModelDefinition.armor, armorId).thickness; - }) - .filter(Boolean), - ); - - return ( - - {armorNodes.map((node) => { - const isHull = node.name.startsWith('hull_'); - const isVisible = isHull; - const armorId = nameToArmorId(node.name); - const { spaced, thickness } = resolveArmor( - tankModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - ); - })} - - - {armorNodes.map((node) => { - const isCurrentTurret = node.name.startsWith( - `turret_${turretModelDefinition.model.toString().padStart(2, '0')}`, - ); - const isVisible = isCurrentTurret; - const armorId = nameToArmorId(node.name); - const { spaced, thickness } = resolveArmor( - turretModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - ); - })} - - - {armorNodes.map((node) => { - const isCurrentGun = node.name.startsWith( - `gun_${gunModelDefinition.model.toString().padStart(2, '0')}`, - ); - const isVisible = isCurrentGun; - const armorId = nameToArmorId(node.name); - const { spaced, thickness } = resolveArmor( - gunModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - ); - })} - - - - ); -} diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ExternalModuleMask.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ExternalModuleMask.tsx deleted file mode 100644 index 66858e5bd..000000000 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/ExternalModuleMask.tsx +++ /dev/null @@ -1,286 +0,0 @@ -import { memo, useEffect, useRef } from 'react'; -import { Euler, Group, Vector3 } from 'three'; -import { degToRad } from 'three/src/math/MathUtils'; -import { ArmorMeshExternalModuleMask } from '../../../../../../../../../components/ArmorMesh'; -import { I_HAT, J_HAT, K_HAT } from '../../../../../../../../../constants/axis'; -import { - ModelTransformEventData, - modelTransformEvent, -} from '../../../../../../../../../core/blitzkrieg/modelTransform'; -import { nameToArmorId } from '../../../../../../../../../core/blitzkrieg/nameToArmorId'; -import { resolveArmor } from '../../../../../../../../../core/blitzkrieg/resolveThickness'; -import { useArmor } from '../../../../../../../../../hooks/useArmor'; -import { useModel } from '../../../../../../../../../hooks/useModel'; -import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions'; -import { useDuel } from '../../../../../../../../../stores/duel'; -import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia'; - -interface ExternalModuleMaskProps { - ornamental?: boolean; -} - -/** - * When rendered, generates a mask and thickness buffer for external modules. - * - R: 1 means external module - * - G: normalized thickness; multiply with max thickness to get nominal thickness - * - B: no data - * - A: 1 means is armor; 0 is background - */ -export const ExternalModuleMask = memo( - ({ ornamental = false }) => { - const protagonist = useDuel((state) => state.protagonist!); - const wrapper = useRef(null); - const modelDefinitions = useModelDefinitions(); - const turretContainer = useRef(null); - const gunContainer = useRef(null); - const initialTankopediaState = useTankopediaPersistent.getState(); - - useEffect(() => { - const hullOrigin = new Vector3( - trackModelDefinition.origin[0], - trackModelDefinition.origin[1], - -trackModelDefinition.origin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const turretOrigin = new Vector3( - tankModelDefinition.turretOrigin[0], - tankModelDefinition.turretOrigin[1], - -tankModelDefinition.turretOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const gunOrigin = new Vector3( - turretModelDefinition.gunOrigin[0], - turretModelDefinition.gunOrigin[1], - -turretModelDefinition.gunOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const turretPosition = new Vector3(); - const turretRotation = new Euler(); - const gunPosition = new Vector3(); - const gunRotation = new Euler(); - - function handleModelTransform({ yaw, pitch }: ModelTransformEventData) { - gunPosition - .set(0, 0, 0) - .sub(hullOrigin) - .sub(turretOrigin) - .sub(gunOrigin) - .applyAxisAngle(I_HAT, pitch) - .add(gunOrigin) - .add(turretOrigin) - .add(hullOrigin); - gunRotation.set(pitch, 0, 0); - gunContainer.current?.position.copy(gunPosition); - gunContainer.current?.rotation.copy(gunRotation); - - if (yaw === undefined) return; - - turretPosition - .set(0, 0, 0) - .sub(turretOrigin) - .sub(hullOrigin) - .applyAxisAngle(new Vector3(0, 0, 1), yaw); - turretRotation.set(0, 0, yaw); - - if (tankModelDefinition.turretRotation) { - const initialPitch = -degToRad( - tankModelDefinition.turretRotation.pitch, - ); - const initialYaw = -degToRad(tankModelDefinition.turretRotation.yaw); - const initialRoll = -degToRad( - tankModelDefinition.turretRotation.roll, - ); - - turretPosition - .applyAxisAngle(I_HAT, initialPitch) - .applyAxisAngle(J_HAT, initialRoll) - .applyAxisAngle(K_HAT, initialYaw); - turretRotation.x += initialPitch; - turretRotation.y += initialRoll; - turretRotation.z += initialYaw; - } - - turretPosition.add(turretOrigin).add(hullOrigin); - turretContainer.current?.position.copy(turretPosition); - turretContainer.current?.rotation.copy(turretRotation); - } - - handleModelTransform(protagonist); - modelTransformEvent.on(handleModelTransform); - - return () => { - modelTransformEvent.off(handleModelTransform); - }; - }); - - useEffect(() => { - const unsubscribe = useTankopediaPersistent.subscribe( - (state) => state.mode, - (mode) => { - if (wrapper.current) wrapper.current.visible = mode === 'armor'; - }, - ); - - return unsubscribe; - }); - - const armorGltf = useArmor(protagonist.tank.id); - const { gltf: modelGltf } = useModel(protagonist.tank.id); - - const armorNodes = Object.values(armorGltf.nodes); - const modelNodes = Object.values(modelGltf.nodes); - const tankModelDefinition = modelDefinitions[protagonist.tank.id]; - const trackModelDefinition = - tankModelDefinition.tracks[protagonist.track.id]; - const turretModelDefinition = - tankModelDefinition.turrets[protagonist.turret.id]; - const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; - const maxThickness = Math.max( - trackModelDefinition.thickness, - gunModelDefinition.thickness, - ...armorNodes - .map((node) => { - const armorId = nameToArmorId(node.name); - return resolveArmor(tankModelDefinition.armor, armorId).thickness; - }) - .filter(Boolean), - ); - const hullOrigin = new Vector3( - trackModelDefinition.origin[0], - trackModelDefinition.origin[1], - -trackModelDefinition.origin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const turretOrigin = new Vector3( - tankModelDefinition.turretOrigin[0], - tankModelDefinition.turretOrigin[1], - -tankModelDefinition.turretOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - const gunOrigin = new Vector3( - turretModelDefinition.gunOrigin[0], - turretModelDefinition.gunOrigin[1], - -turretModelDefinition.gunOrigin[2], - ).applyAxisAngle(I_HAT, Math.PI / 2); - - return ( - - - {armorNodes.map((node) => { - const isHull = node.name.startsWith('hull_'); - const isVisible = isHull; - const armorId = nameToArmorId(node.name); - const { thickness, spaced } = resolveArmor( - tankModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - ); - })} - - - {modelNodes.map((node) => { - const isWheel = node.name.startsWith('chassis_wheel_'); - const isTrack = node.name.startsWith('chassis_track_'); - const isVisible = isWheel || isTrack; - - if (!isVisible) return null; - - return ( - - ); - })} - - - - {armorNodes.map((node) => { - const isCurrentTurret = node.name.startsWith( - `turret_${turretModelDefinition.model.toString().padStart(2, '0')}`, - ); - const isVisible = isCurrentTurret; - const armorId = nameToArmorId(node.name); - const { thickness, spaced } = resolveArmor( - turretModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - - - ); - })} - - - - {armorNodes.map((node) => { - const isCurrentGun = node.name.startsWith( - `gun_${gunModelDefinition.model.toString().padStart(2, '0')}`, - ); - const isVisible = isCurrentGun; - const armorId = nameToArmorId(node.name); - const { thickness, spaced } = resolveArmor( - gunModelDefinition.armor, - armorId, - ); - - if (!isVisible || thickness === undefined || spaced) return null; - - return ( - - - - ); - })} - - {modelNodes.map((node) => { - const isCurrentGun = - node.name === - `gun_${gunModelDefinition.model.toString().padStart(2, '0')}`; - const isVisible = isCurrentGun; - - if (!isVisible) return null; - - return ( - - ); - })} - - - - ); - }, -); diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/SpacedArmorDepth.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/Spaced.tsx similarity index 83% rename from src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/SpacedArmorDepth.tsx rename to src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/Spaced.tsx index a856743ae..1f768debe 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/SpacedArmorDepth.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/Spaced.tsx @@ -1,8 +1,9 @@ import { memo, useEffect, useRef } from 'react'; import { Euler, Group, Vector3 } from 'three'; import { degToRad } from 'three/src/math/MathUtils'; -import { ArmorMeshSpacedArmorDepth } from '../../../../../../../../../components/ArmorMesh/components/SpacedArmorDepth'; +import { SpacedArmor } from '../../../../../../../../../components/Armor/components/SpacedArmor'; import { I_HAT, J_HAT, K_HAT } from '../../../../../../../../../constants/axis'; +import { resolveNearPenetration } from '../../../../../../../../../core/blitz/resolveNearPenetration'; import { ModelTransformEventData, modelTransformEvent, @@ -15,22 +16,17 @@ import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDe import { useDuel } from '../../../../../../../../../stores/duel'; import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia'; -interface SpacedArmorDepthProps { +export enum ArmorType { + Core, + Spaced, + External, +} + +interface SpacedArmorSceneProps { ornamental?: boolean; } -/** - * When rendered, this component provides the depth buffer for the armor which - * when compared to the depth of the core armor will give you the distance - * between the first point of contact and the core armor. The color channels - * hold information about the thickness of the spaced armor (external modules - * not included). - * - R: angle of the armor where 0 is 0 and 1 is 90 - * - G: normalized thickness; multiply with max thickness to get nominal thickness - * - B: no data - * - A: 1 means is armor; 0 is background - */ -export const SpacedArmorDepth = memo( +export const SpacedArmorScene = memo( ({ ornamental = false }) => { const protagonist = useDuel((state) => state.protagonist!); const wrapper = useRef(null); @@ -138,16 +134,6 @@ export const SpacedArmorDepth = memo( const turretModelDefinition = tankModelDefinition.turrets[protagonist.turret.id]; const gunModelDefinition = turretModelDefinition.guns[protagonist.gun.id]; - const maxThickness = Math.max( - trackModelDefinition.thickness, - gunModelDefinition.thickness, - ...armorNodes - .map((node) => { - const armorId = nameToArmorId(node.name); - return resolveArmor(tankModelDefinition.armor, armorId).thickness; - }) - .filter(Boolean), - ); const hullOrigin = new Vector3( trackModelDefinition.origin[0], trackModelDefinition.origin[1], @@ -164,6 +150,17 @@ export const SpacedArmorDepth = memo( -turretModelDefinition.gunOrigin[2], ).applyAxisAngle(I_HAT, Math.PI / 2); + console.log( + 'test', + gunModelDefinition.thickness, + resolveNearPenetration(useDuel.getState().antagonist!.shell.penetration), + (gunModelDefinition.thickness / + resolveNearPenetration( + useDuel.getState().antagonist!.shell.penetration, + )) * + 255, + ); + return ( ( if (!isVisible || thickness === undefined) return null; return ( - ); @@ -203,10 +198,11 @@ export const SpacedArmorDepth = memo( if (!isVisible) return null; return ( - ); @@ -229,12 +225,11 @@ export const SpacedArmorDepth = memo( return ( - @@ -261,12 +256,10 @@ export const SpacedArmorDepth = memo( key={node.uuid} position={turretOrigin.clone().add(gunOrigin)} > - @@ -275,18 +268,19 @@ export const SpacedArmorDepth = memo( {modelNodes.map((node) => { - const isCurrentGun = - node.name === - `gun_${gunModelDefinition.model.toString().padStart(2, '0')}`; + const isCurrentGun = node.name.startsWith( + `gun_${gunModelDefinition.model.toString().padStart(2, '0')}`, + ); const isVisible = isCurrentGun; if (!isVisible) return null; return ( - ); diff --git a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/index.tsx b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/index.tsx index df4cc78d5..e69de29bb 100644 --- a/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/index.tsx +++ b/src/app/tools/tankopedia/[id]/components/Model/components/TankArmor/index.tsx @@ -1,67 +0,0 @@ -import { createPortal, useFrame } from '@react-three/fiber'; -import { memo } from 'react'; -import { DepthTexture, Scene, Vector2 } from 'three'; -import { externalModuleMaskRenderTarget } from '../../../../../../../../components/ArmorMesh'; -import { spacedArmorDepthRenderTarget } from '../../../../../../../../components/ArmorMesh/components/SpacedArmorDepth'; -import { ArmorHighlighting } from './components/ArmorHighlighting'; -import { ExternalModuleMask } from './components/ExternalModuleMask'; -import { SpacedArmorDepth } from './components/SpacedArmorDepth'; - -export const TankArmor = memo(() => { - const externalModuleMaskScene = new Scene(); - const spacedArmorDepthScene = new Scene(); - const armorHighlightingScene = new Scene(); - const externalModuleMaskPortal = createPortal( - , - externalModuleMaskScene, - ); - const spacedArmorDepthPortal = createPortal( - , - spacedArmorDepthScene, - ); - const armorHighlightingPortal = createPortal( - , - armorHighlightingScene, - ); - const renderSize = new Vector2(); - const newRenderSize = new Vector2(); - - useFrame(({ gl, scene, camera }) => { - const pixelRatio = gl.getPixelRatio(); - gl.autoClear = true; - - gl.getSize(newRenderSize).multiplyScalar(pixelRatio); - if (!newRenderSize.equals(renderSize)) { - renderSize.copy(newRenderSize); - spacedArmorDepthRenderTarget.depthTexture = new DepthTexture( - renderSize.x, - renderSize.y, - ); - } - - externalModuleMaskRenderTarget.setSize(renderSize.x, renderSize.y); - gl.setRenderTarget(externalModuleMaskRenderTarget); - gl.render(externalModuleMaskScene, camera); - - gl.clearDepth(); - spacedArmorDepthRenderTarget.setSize(renderSize.x, renderSize.y * 0.5); - gl.setRenderTarget(spacedArmorDepthRenderTarget); - gl.render(spacedArmorDepthScene, camera); - - gl.autoClear = false; - - gl.setRenderTarget(null); - gl.render(scene, camera); - - gl.clearDepth(); - gl.render(armorHighlightingScene, camera); - }, 1); - - return ( - <> - {externalModuleMaskPortal} - {spacedArmorDepthPortal} - {armorHighlightingPortal} - - ); -}); diff --git a/src/components/Armor/components/SpacedArmor.tsx b/src/components/Armor/components/SpacedArmor.tsx new file mode 100644 index 000000000..a4706ccf5 --- /dev/null +++ b/src/components/Armor/components/SpacedArmor.tsx @@ -0,0 +1,34 @@ +import { AdditiveBlending, Color, MeshBasicMaterial, Object3D } from 'three'; +import { ArmorType } from '../../../app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/Spaced'; +import { resolveNearPenetration } from '../../../core/blitz/resolveNearPenetration'; +import { jsxTree } from '../../../core/blitzkrieg/jsxTree'; +import { useDuel } from '../../../stores/duel'; + +interface SpacedArmorProps { + node: Object3D; + ornamental?: boolean; + type: ArmorType; + thickness: number; +} + +const omitColor = new Color(0, 0, 0); + +export function SpacedArmor({ node, type, thickness }: SpacedArmorProps) { + const penetrationRaw = useDuel( + (state) => state.antagonist!.shell.penetration, + ); + const penetration = resolveNearPenetration(penetrationRaw); + + return jsxTree(node, { + material: new MeshBasicMaterial({ + color: + type === ArmorType.Core + ? omitColor + : type === ArmorType.Spaced + ? new Color(0, 0, 0) + : new Color(thickness / penetration, 0, 0), + depthWrite: type === ArmorType.Core, + blending: type === ArmorType.Core ? undefined : AdditiveBlending, + }), + }); +} diff --git a/src/stores/tankopedia.ts b/src/stores/tankopedia.ts index f2f8b5d26..773014f21 100644 --- a/src/stores/tankopedia.ts +++ b/src/stores/tankopedia.ts @@ -5,6 +5,7 @@ import { create } from 'zustand'; import { persist, subscribeWithSelector } from 'zustand/middleware'; import { ENVIRONMENTS } from '../app/tools/tankopedia/[id]/components/Lighting'; import { TankType, TreeType } from '../components/Tanks'; +import isDev from '../core/blitzkrieg/isDev'; import { Tier } from '../core/blitzkrieg/tankDefinitions'; export type TankopediaSortBy = keyof typeof SORT_NAMES; @@ -123,7 +124,7 @@ export const useTankopediaPersistent = create()( test: 'include', page: 0, }, - mode: 'model', + mode: isDev() ? 'armor' : 'model', })), { name: 'tankopedia', merge }, ),