mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-21 10:47:04 +02:00
fix: render tracer over armor
This commit is contained in:
1 parent
2b34863b53
commit
00cee28e08
3 files changed
+100
-63
No files matched your search
@@ -2,7 +2,6 @@ import { PerspectiveCamera } from '@react-three/drei';
|
||||
import { Canvas } from '@react-three/fiber';
|
||||
import { Suspense, use, useEffect, useRef } from 'react';
|
||||
import { Armor } from '../../../../../../components/Armor';
|
||||
import { ShotDisplay } from '../../../../../../components/Armor/components/ShotDisplay';
|
||||
import { applyPitchYawLimits } from '../../../../../../core/blitz/applyPitchYawLimits';
|
||||
import { modelDefinitions } from '../../../../../../core/blitzkit/modelDefinitions';
|
||||
import { modelTransformEvent } from '../../../../../../core/blitzkit/modelTransform';
|
||||
@@ -143,7 +142,6 @@ export function TankSandbox() {
|
||||
<Lighting />
|
||||
<TankModel />
|
||||
<Armor />
|
||||
<ShotDisplay />
|
||||
</Suspense>
|
||||
</Canvas>
|
||||
);
|
||||
|
||||
@@ -13,6 +13,7 @@ import { useModelDefinitions } from '../../../hooks/useModelDefinitions';
|
||||
import { useDuel } from '../../../stores/duel';
|
||||
import { useTankopediaPersistent } from '../../../stores/tankopedia';
|
||||
import { CoreArmorSceneComponent } from './CoreArmorSceneComponent';
|
||||
import { ShotDisplay } from './ShotDisplay';
|
||||
|
||||
export const CoreArmorScene = memo(() => {
|
||||
const wrapper = useRef<Group>(null);
|
||||
@@ -135,86 +136,94 @@ export const CoreArmorScene = memo(() => {
|
||||
).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,
|
||||
);
|
||||
<>
|
||||
<ShotDisplay />
|
||||
|
||||
if (!isVisible || spaced || thickness === undefined) return null;
|
||||
|
||||
return (
|
||||
<CoreArmorSceneComponent
|
||||
key={node.uuid}
|
||||
thickness={thickness}
|
||||
node={node}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
|
||||
<group ref={turretContainer}>
|
||||
<group
|
||||
ref={wrapper}
|
||||
rotation={[-Math.PI / 2, 0, 0]}
|
||||
visible={initialTankopediaState.mode === 'armor'}
|
||||
>
|
||||
<group position={hullOrigin}>
|
||||
{armorNodes.map((node) => {
|
||||
const isCurrentTurret = node.name.startsWith(
|
||||
`turret_${turretModelDefinition.model.toString().padStart(2, '0')}`,
|
||||
);
|
||||
const isVisible = isCurrentTurret;
|
||||
const isHull = node.name.startsWith('hull_');
|
||||
const isVisible = isHull;
|
||||
const armorId = nameToArmorId(node.name);
|
||||
const { spaced, thickness } = resolveArmor(
|
||||
turretModelDefinition.armor,
|
||||
tankModelDefinition.armor,
|
||||
armorId,
|
||||
);
|
||||
|
||||
if (!isVisible || spaced || thickness === undefined) return null;
|
||||
|
||||
return (
|
||||
<group key={node.uuid} position={turretOrigin}>
|
||||
<CoreArmorSceneComponent
|
||||
key={node.uuid}
|
||||
thickness={thickness}
|
||||
node={node}
|
||||
/>
|
||||
</group>
|
||||
<CoreArmorSceneComponent
|
||||
key={node.uuid}
|
||||
thickness={thickness}
|
||||
node={node}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
<group ref={gunContainer}>
|
||||
|
||||
<group ref={turretContainer}>
|
||||
<group position={hullOrigin}>
|
||||
{armorNodes.map((node) => {
|
||||
const isCurrentGun = node.name.startsWith(
|
||||
`gun_${gunModelDefinition.model.toString().padStart(2, '0')}`,
|
||||
const isCurrentTurret = node.name.startsWith(
|
||||
`turret_${turretModelDefinition.model.toString().padStart(2, '0')}`,
|
||||
);
|
||||
const isVisible = isCurrentGun;
|
||||
const isVisible = isCurrentTurret;
|
||||
const armorId = nameToArmorId(node.name);
|
||||
const { spaced, thickness } = resolveArmor(
|
||||
gunModelDefinition.armor,
|
||||
turretModelDefinition.armor,
|
||||
armorId,
|
||||
);
|
||||
|
||||
if (!isVisible || spaced || thickness === undefined) return null;
|
||||
|
||||
return (
|
||||
<group
|
||||
key={node.uuid}
|
||||
position={turretOrigin.clone().add(gunOrigin)}
|
||||
>
|
||||
<CoreArmorSceneComponent thickness={thickness} node={node} />
|
||||
<group key={node.uuid} position={turretOrigin}>
|
||||
<CoreArmorSceneComponent
|
||||
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)}
|
||||
>
|
||||
<CoreArmorSceneComponent
|
||||
thickness={thickness}
|
||||
node={node}
|
||||
/>
|
||||
</group>
|
||||
);
|
||||
})}
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
});
|
||||
@@ -164,6 +164,10 @@ export function ShotDisplay() {
|
||||
)
|
||||
: LENGTH_INFINITY;
|
||||
const inLast = shot.in.layers.findLast((layer) => layer.type !== null)!;
|
||||
const outTitleColor = shot.out
|
||||
? shotStatusColors[shot.out.status]
|
||||
: undefined;
|
||||
const inTitleColor = shotStatusColors[shot.in.status];
|
||||
|
||||
return (
|
||||
<group>
|
||||
@@ -177,7 +181,7 @@ export function ShotDisplay() {
|
||||
<Card ml="9" style={{ width: 300 }}>
|
||||
<Flex direction="column" gap="2">
|
||||
<Flex direction="column" gap="1">
|
||||
<Text color={shotStatusColors[shot.in.status]} weight="bold">
|
||||
<Text color={inTitleColor} weight="bold">
|
||||
{shot.in.status !== 'blocked' &&
|
||||
shot.in.status !== 'ricochet' && (
|
||||
<>
|
||||
@@ -224,10 +228,24 @@ export function ShotDisplay() {
|
||||
{shot.out && shot.out.layers.length > 0 && (
|
||||
<>
|
||||
<Inset side="x">
|
||||
<Separator size="4" />
|
||||
<Flex align="center" gap="2">
|
||||
<Separator
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
/>
|
||||
<Text size="1" color="gray">
|
||||
ricochet (-25% penetration)
|
||||
</Text>
|
||||
<Separator
|
||||
style={{
|
||||
flex: 1,
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Inset>
|
||||
|
||||
<Text color={shotStatusColors[shot.out.status]} weight="bold">
|
||||
<Text color={outTitleColor} weight="bold">
|
||||
{shot.out.status !== 'blocked' &&
|
||||
shot.out.status !== 'ricochet' && (
|
||||
<>
|
||||
@@ -309,18 +327,22 @@ export function ShotDisplay() {
|
||||
new Quaternion().setFromUnitVectors(J_HAT, shot.in.surfaceNormal),
|
||||
)}
|
||||
>
|
||||
<mesh position={[0, inLength / 2, 0]}>
|
||||
<mesh position={[0, inLength / 2, 0]} renderOrder={2}>
|
||||
<cylinderGeometry
|
||||
args={[TRACER_THIN / 2, TRACER_THIN / 2, inLength]}
|
||||
/>
|
||||
<meshBasicMaterial depthTest={false} />
|
||||
<meshBasicMaterial depthTest={false} transparent />
|
||||
</mesh>
|
||||
|
||||
<mesh ref={inTracer} position={[0, inLength / 2, 0]}>
|
||||
<mesh ref={inTracer} position={[0, inLength / 2, 0]} renderOrder={3}>
|
||||
<cylinderGeometry
|
||||
args={[TRACER_THICK / 2, TRACER_THICK / 2, inLength]}
|
||||
/>
|
||||
<meshBasicMaterial color="red" />
|
||||
<meshBasicMaterial
|
||||
color={inTitleColor}
|
||||
depthTest={false}
|
||||
transparent
|
||||
/>
|
||||
</mesh>
|
||||
</group>
|
||||
|
||||
@@ -334,18 +356,26 @@ export function ShotDisplay() {
|
||||
),
|
||||
)}
|
||||
>
|
||||
<mesh position={[0, outLength / 2, 0]}>
|
||||
<mesh position={[0, outLength / 2, 0]} renderOrder={2}>
|
||||
<cylinderGeometry
|
||||
args={[TRACER_THIN / 2, TRACER_THIN / 2, outLength]}
|
||||
/>
|
||||
<meshBasicMaterial depthTest={false} />
|
||||
<meshBasicMaterial depthTest={false} transparent />
|
||||
</mesh>
|
||||
|
||||
<mesh ref={outTracer} position={[0, outLength / 2, 0]}>
|
||||
<mesh
|
||||
ref={outTracer}
|
||||
position={[0, outLength / 2, 0]}
|
||||
renderOrder={3}
|
||||
>
|
||||
<cylinderGeometry
|
||||
args={[TRACER_THICK / 2, TRACER_THICK / 2, outLength]}
|
||||
/>
|
||||
<meshBasicMaterial color="yellow" />
|
||||
<meshBasicMaterial
|
||||
color={outTitleColor}
|
||||
depthTest={false}
|
||||
transparent
|
||||
/>
|
||||
</mesh>
|
||||
</group>
|
||||
)}
|
||||
|
||||
Reference in new issue
Block a user