mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 19:49:50 +02:00
feat: core armor
This commit is contained in:
1 parent
fabf649608
commit
2689568650
14 files changed
+430
-24
No files matched your search
@@ -4,6 +4,7 @@ import { PerspectiveCamera } from '@react-three/drei';
|
|||||||
import { Canvas } from '@react-three/fiber';
|
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 { 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';
|
||||||
@@ -18,10 +19,12 @@ import mutateTankopediaPersistent, {
|
|||||||
} from '../../../../../../stores/tankopedia';
|
} from '../../../../../../stores/tankopedia';
|
||||||
import { AntagonistBar } from '../AntagonistBar';
|
import { AntagonistBar } from '../AntagonistBar';
|
||||||
import { Controls } from '../Control';
|
import { Controls } from '../Control';
|
||||||
|
import { Lighting } from '../Lighting';
|
||||||
import { RotationInputs } from '../QuickInputs';
|
import { RotationInputs } from '../QuickInputs';
|
||||||
|
import { SceneProps } from '../SceneProps';
|
||||||
import { ModelLoader } from './components/ModelLoader';
|
import { ModelLoader } from './components/ModelLoader';
|
||||||
import { Options } from './components/Options';
|
import { Options } from './components/Options';
|
||||||
import { SpacedArmorScene } from './components/TankArmor/components/Spaced';
|
import { TankModel } from './components/TankModel';
|
||||||
|
|
||||||
export function TankSandbox() {
|
export function TankSandbox() {
|
||||||
const canvas = useRef<HTMLCanvasElement>(null);
|
const canvas = useRef<HTMLCanvasElement>(null);
|
||||||
@@ -189,13 +192,16 @@ export function TankSandbox() {
|
|||||||
>
|
>
|
||||||
<PerspectiveCamera makeDefault fov={25} far={32} />
|
<PerspectiveCamera makeDefault fov={25} far={32} />
|
||||||
<Controls />
|
<Controls />
|
||||||
{/* <SceneProps /> */}
|
<SceneProps />
|
||||||
|
|
||||||
<Suspense fallback={<ModelLoader />}>
|
<Suspense fallback={<ModelLoader />}>
|
||||||
{/* <ShotDisplay />
|
{/* <ShotDisplay />
|
||||||
|
|
||||||
|
*/}
|
||||||
|
{/* <SpacedArmorScene /> */}
|
||||||
<Lighting />
|
<Lighting />
|
||||||
<TankModel /> */}
|
<TankModel />
|
||||||
<SpacedArmorScene />
|
<Armor />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
import { useFrame } from '@react-three/fiber';
|
||||||
|
import {
|
||||||
|
MeshBasicMaterial,
|
||||||
|
Object3D,
|
||||||
|
ShaderMaterial,
|
||||||
|
Vector2,
|
||||||
|
WebGLRenderTarget,
|
||||||
|
} from 'three';
|
||||||
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
|
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
||||||
|
import { jsxTree } from '../../../../core/blitzkrieg/jsxTree';
|
||||||
|
import { useDuel } from '../../../../stores/duel';
|
||||||
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
|
|
||||||
|
export const spacedArmorRenderTarget = new WebGLRenderTarget();
|
||||||
|
|
||||||
|
interface CoreArmorProps {
|
||||||
|
thickness: number;
|
||||||
|
node: Object3D;
|
||||||
|
}
|
||||||
|
|
||||||
|
const excludeMaterial = new MeshBasicMaterial({
|
||||||
|
colorWrite: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function CoreArmor({ node, thickness }: CoreArmorProps) {
|
||||||
|
const { shell } = useDuel.getState().antagonist!;
|
||||||
|
const penetration = resolveNearPenetration(shell.penetration);
|
||||||
|
const material = new ShaderMaterial({
|
||||||
|
fragmentShader,
|
||||||
|
vertexShader,
|
||||||
|
|
||||||
|
transparent: true,
|
||||||
|
|
||||||
|
uniforms: {
|
||||||
|
thickness: { value: thickness },
|
||||||
|
penetration: { value: penetration },
|
||||||
|
caliber: { value: shell.caliber },
|
||||||
|
ricochet: { value: degToRad(shell.ricochet ?? 90) },
|
||||||
|
normalization: { value: degToRad(shell.normalization ?? 0) },
|
||||||
|
|
||||||
|
resolution: { value: new Vector2() },
|
||||||
|
spacedArmorBuffer: { value: null },
|
||||||
|
spacedArmorDepth: { value: null },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useFrame(({ gl }) => {
|
||||||
|
gl.getSize(material.uniforms.resolution.value).multiplyScalar(
|
||||||
|
gl.getPixelRatio(),
|
||||||
|
);
|
||||||
|
material.uniforms.spacedArmorBuffer.value = spacedArmorRenderTarget.texture;
|
||||||
|
material.uniforms.spacedArmorDepth.value =
|
||||||
|
spacedArmorRenderTarget.depthTexture;
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{jsxTree(node, {
|
||||||
|
renderOrder: 0,
|
||||||
|
material: excludeMaterial,
|
||||||
|
})}
|
||||||
|
|
||||||
|
{jsxTree(node, {
|
||||||
|
renderOrder: 1,
|
||||||
|
material,
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 vViewPosition;
|
||||||
|
|
||||||
|
uniform float thickness;
|
||||||
|
uniform float penetration;
|
||||||
|
uniform float caliber;
|
||||||
|
uniform float ricochet;
|
||||||
|
uniform float normalization;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
|
||||||
|
uniform sampler2D spacedArmorBuffer;
|
||||||
|
uniform highp sampler2D spacedArmorDepth;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
float penetrationChance = -1.0;
|
||||||
|
float splashChance = -1.0;
|
||||||
|
|
||||||
|
vec2 screenCoordinates = gl_FragCoord.xy / resolution;
|
||||||
|
float angle = acos(dot(vNormal, -vViewPosition) / length(vViewPosition));
|
||||||
|
|
||||||
|
vec4 spacedArmorBufferFragment = texture2D(spacedArmorBuffer, screenCoordinates);
|
||||||
|
bool isUnderSpacedArmor = spacedArmorBufferFragment.a != 0.0;
|
||||||
|
|
||||||
|
bool threeCalibersRule = caliber > thickness * 3.0;
|
||||||
|
if (!threeCalibersRule && !isUnderSpacedArmor && angle >= ricochet) {
|
||||||
|
penetrationChance = 0.0;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
bool twoCalibersRule = caliber > thickness * 2.0 && thickness > 0.0;
|
||||||
|
float finalNormalization = twoCalibersRule ? ((1.4 * normalization * caliber) / (2.0 * thickness)) : normalization;
|
||||||
|
float finalThickness = thickness / cos(angle - finalNormalization);
|
||||||
|
|
||||||
|
float remainingPenetration = penetration;
|
||||||
|
if (isUnderSpacedArmor) {
|
||||||
|
float spacedArmorThickness = spacedArmorBufferFragment.r * penetration;
|
||||||
|
remainingPenetration -= spacedArmorThickness + finalThickness;
|
||||||
|
} else {
|
||||||
|
remainingPenetration -= finalThickness;
|
||||||
|
}
|
||||||
|
|
||||||
|
penetrationChance = remainingPenetration < 0.0 ? 0.0 : 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 color = vec3(1.0, splashChance * 0.392, 0.0);
|
||||||
|
gl_FragColor = vec4(color, (1.0 - penetrationChance) * 0.5);
|
||||||
|
}
|
||||||
File renamed without changes.
@@ -0,0 +1,226 @@
|
|||||||
|
import { memo, useEffect, useRef } from 'react';
|
||||||
|
import { Euler, Group, Vector3 } from 'three';
|
||||||
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
|
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';
|
||||||
|
import { CoreArmor } from './CoreArmor';
|
||||||
|
|
||||||
|
interface CoreArmorSceneProps {
|
||||||
|
ornamental?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CoreArmorScene = memo<CoreArmorSceneProps>(
|
||||||
|
({ ornamental = false }) => {
|
||||||
|
const protagonist = useDuel((state) => state.protagonist!);
|
||||||
|
const wrapper = useRef<Group>(null);
|
||||||
|
const modelDefinitions = useModelDefinitions();
|
||||||
|
const turretContainer = useRef<Group>(null);
|
||||||
|
const gunContainer = useRef<Group>(null);
|
||||||
|
const initialTankopediaState = useTankopediaPersistent.getState();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!modelDefinitions) return;
|
||||||
|
|
||||||
|
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(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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],
|
||||||
|
).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 (
|
||||||
|
<group
|
||||||
|
ref={wrapper}
|
||||||
|
rotation={[-Math.PI / 2, 0, 0]}
|
||||||
|
visible={initialTankopediaState.mode === 'armor'}
|
||||||
|
>
|
||||||
|
<group position={hullOrigin}>
|
||||||
|
{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 || spaced || thickness === undefined) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CoreArmor key={node.uuid} thickness={thickness} node={node} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group ref={turretContainer}>
|
||||||
|
<group position={hullOrigin}>
|
||||||
|
{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 || spaced || thickness === undefined) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group key={node.uuid} position={turretOrigin}>
|
||||||
|
<CoreArmor
|
||||||
|
key={node.uuid}
|
||||||
|
thickness={thickness}
|
||||||
|
node={node}
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</group>
|
||||||
|
<group ref={gunContainer}>
|
||||||
|
<group position={hullOrigin}>
|
||||||
|
{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 || spaced || thickness === undefined)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<group
|
||||||
|
key={node.uuid}
|
||||||
|
position={turretOrigin.clone().add(gunOrigin)}
|
||||||
|
>
|
||||||
|
<CoreArmor thickness={thickness} node={node} />
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
+2
-2
@@ -7,8 +7,8 @@ import {
|
|||||||
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
||||||
import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree';
|
import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree';
|
||||||
import { useDuel } from '../../../../../../stores/duel';
|
import { useDuel } from '../../../../../../stores/duel';
|
||||||
import fragmentShader from './fragment.glsl';
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
import vertexShader from './vertex.glsl';
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
|
|
||||||
interface SpacedArmorSubExternalProps {
|
interface SpacedArmorSubExternalProps {
|
||||||
node: Object3D;
|
node: Object3D;
|
||||||
|
|||||||
File renamed without changes.
File renamed without changes.
+2
-4
@@ -3,8 +3,8 @@ import { degToRad } from 'three/src/math/MathUtils';
|
|||||||
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../../../core/blitz/resolveNearPenetration';
|
||||||
import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree';
|
import { jsxTree } from '../../../../../../core/blitzkrieg/jsxTree';
|
||||||
import { useDuel } from '../../../../../../stores/duel';
|
import { useDuel } from '../../../../../../stores/duel';
|
||||||
import fragmentShader from './fragment.glsl';
|
import fragmentShader from './shaders/fragment.glsl';
|
||||||
import vertexShader from './vertex.glsl';
|
import vertexShader from './shaders/vertex.glsl';
|
||||||
|
|
||||||
interface SpacedArmorSubSpacedProps {
|
interface SpacedArmorSubSpacedProps {
|
||||||
node: Object3D;
|
node: Object3D;
|
||||||
@@ -18,8 +18,6 @@ export function SpacedArmorSubSpaced({
|
|||||||
const { shell } = useDuel.getState().antagonist!;
|
const { shell } = useDuel.getState().antagonist!;
|
||||||
const penetration = resolveNearPenetration(shell.penetration);
|
const penetration = resolveNearPenetration(shell.penetration);
|
||||||
|
|
||||||
console.log(shell.ricochet);
|
|
||||||
|
|
||||||
return jsxTree(node, {
|
return jsxTree(node, {
|
||||||
renderOrder: 2,
|
renderOrder: 2,
|
||||||
material: new ShaderMaterial({
|
material: new ShaderMaterial({
|
||||||
|
|||||||
File renamed without changes.
+11
@@ -0,0 +1,11 @@
|
|||||||
|
varying vec3 vNormal;
|
||||||
|
varying vec3 vViewPosition;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 vViewPosition4 = modelViewMatrix * vec4(position, 1.0);
|
||||||
|
|
||||||
|
vViewPosition = vViewPosition4.xyz;
|
||||||
|
vNormal = normalMatrix * normal;
|
||||||
|
|
||||||
|
gl_Position = projectionMatrix * vViewPosition4;
|
||||||
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
import { MeshBasicMaterial, Object3D } from 'three';
|
import { MeshBasicMaterial, Object3D } from 'three';
|
||||||
import { ArmorType } from '../../../../app/tools/tankopedia/[id]/components/Model/components/TankArmor/components/Spaced';
|
|
||||||
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
import { resolveNearPenetration } from '../../../../core/blitz/resolveNearPenetration';
|
||||||
import { jsxTree } from '../../../../core/blitzkrieg/jsxTree';
|
import { jsxTree } from '../../../../core/blitzkrieg/jsxTree';
|
||||||
import { useDuel } from '../../../../stores/duel';
|
import { useDuel } from '../../../../stores/duel';
|
||||||
|
import { ArmorType } from '../SpacedArmorScene';
|
||||||
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
|
import { SpacedArmorSubExternal } from './components/SpacedArmorSubExternal';
|
||||||
import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced';
|
import { SpacedArmorSubSpaced } from './components/SpacedArmorSubSpaced';
|
||||||
// import fragmentShader from './shaders/fragment.glsl';
|
|
||||||
// import vertexShader from './shaders/vertex.glsl';
|
|
||||||
|
|
||||||
interface SpacedArmorProps {
|
interface SpacedArmorProps {
|
||||||
node: Object3D;
|
node: Object3D;
|
||||||
ornamental?: boolean;
|
ornamental?: boolean;
|
||||||
|
|||||||
+10
-10
@@ -1,19 +1,19 @@
|
|||||||
import { memo, useEffect, useRef } from 'react';
|
import { memo, useEffect, useRef } from 'react';
|
||||||
import { Euler, Group, Vector3 } from 'three';
|
import { Euler, Group, Vector3 } from 'three';
|
||||||
import { degToRad } from 'three/src/math/MathUtils';
|
import { degToRad } from 'three/src/math/MathUtils';
|
||||||
import { SpacedArmor } from '../../../../../../../../../components/Armor/components/SpacedArmor';
|
import { I_HAT, J_HAT, K_HAT } from '../../../constants/axis';
|
||||||
import { I_HAT, J_HAT, K_HAT } from '../../../../../../../../../constants/axis';
|
|
||||||
import {
|
import {
|
||||||
ModelTransformEventData,
|
ModelTransformEventData,
|
||||||
modelTransformEvent,
|
modelTransformEvent,
|
||||||
} from '../../../../../../../../../core/blitzkrieg/modelTransform';
|
} from '../../../core/blitzkrieg/modelTransform';
|
||||||
import { nameToArmorId } from '../../../../../../../../../core/blitzkrieg/nameToArmorId';
|
import { nameToArmorId } from '../../../core/blitzkrieg/nameToArmorId';
|
||||||
import { resolveArmor } from '../../../../../../../../../core/blitzkrieg/resolveThickness';
|
import { resolveArmor } from '../../../core/blitzkrieg/resolveThickness';
|
||||||
import { useArmor } from '../../../../../../../../../hooks/useArmor';
|
import { useArmor } from '../../../hooks/useArmor';
|
||||||
import { useModel } from '../../../../../../../../../hooks/useModel';
|
import { useModel } from '../../../hooks/useModel';
|
||||||
import { useModelDefinitions } from '../../../../../../../../../hooks/useModelDefinitions';
|
import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||||
import { useDuel } from '../../../../../../../../../stores/duel';
|
import { useDuel } from '../../../stores/duel';
|
||||||
import { useTankopediaPersistent } from '../../../../../../../../../stores/tankopedia';
|
import { useTankopediaPersistent } from '../../../stores/tankopedia';
|
||||||
|
import { SpacedArmor } from './SpacedArmor';
|
||||||
|
|
||||||
export enum ArmorType {
|
export enum ArmorType {
|
||||||
Core,
|
Core,
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import { createPortal, useFrame } from '@react-three/fiber';
|
||||||
|
import { DepthTexture, Scene, Vector2 } from 'three';
|
||||||
|
import { spacedArmorRenderTarget } from './components/CoreArmor';
|
||||||
|
import { CoreArmorScene } from './components/CoreArmorScene';
|
||||||
|
import { SpacedArmorScene } from './components/SpacedArmorScene';
|
||||||
|
|
||||||
|
export function Armor() {
|
||||||
|
const spacedArmorScene = new Scene();
|
||||||
|
const coreArmorScene = new Scene();
|
||||||
|
const spacedArmorPortal = createPortal(
|
||||||
|
<SpacedArmorScene />,
|
||||||
|
spacedArmorScene,
|
||||||
|
);
|
||||||
|
const coreArmorPortal = createPortal(<CoreArmorScene />, coreArmorScene);
|
||||||
|
|
||||||
|
const renderSize = new Vector2();
|
||||||
|
const newRenderSize = new Vector2();
|
||||||
|
|
||||||
|
useFrame(({ gl, camera, scene }) => {
|
||||||
|
gl.autoClear = true;
|
||||||
|
|
||||||
|
gl.getSize(newRenderSize).multiplyScalar(gl.getPixelRatio());
|
||||||
|
|
||||||
|
if (!newRenderSize.equals(renderSize)) {
|
||||||
|
renderSize.copy(newRenderSize);
|
||||||
|
spacedArmorRenderTarget.depthTexture = new DepthTexture(
|
||||||
|
renderSize.x,
|
||||||
|
renderSize.y,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
spacedArmorRenderTarget.setSize(renderSize.x, renderSize.y);
|
||||||
|
gl.setRenderTarget(spacedArmorRenderTarget);
|
||||||
|
gl.render(spacedArmorScene, camera);
|
||||||
|
|
||||||
|
gl.autoClear = false;
|
||||||
|
|
||||||
|
gl.setRenderTarget(null);
|
||||||
|
gl.render(scene, camera);
|
||||||
|
|
||||||
|
gl.clearDepth();
|
||||||
|
gl.render(coreArmorScene, camera);
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{spacedArmorPortal}
|
||||||
|
{coreArmorPortal}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user