feat: spaced armor

This commit is contained in:
TrèsAbhi committed 2024-01-10 19:04:04 -06:00
1 parent cae4836e17
commit 9218eb09d6
4 files changed
+34 -9

No files matched your search

@@ -142,7 +142,11 @@ export function TankDisplay() {
} }
> >
<TankModel /> <TankModel />
{mode === 'armor' && <TankArmor visible={controlsEnabled} />} {mode === 'armor' && (
<group visible={controlsEnabled}>
<TankArmor />
</group>
)}
</Suspense> </Suspense>
</Canvas> </Canvas>
</div> </div>
@@ -16,7 +16,7 @@ import { Lighting } from '../../Lighting';
interface TankArmorProps extends GroupProps {} interface TankArmorProps extends GroupProps {}
export function TankArmor(props: TankArmorProps) { export function TankArmor({ ...props }: TankArmorProps) {
const [awaitedModelDefinitions, setAwaitedModelDefinitions] = useState< const [awaitedModelDefinitions, setAwaitedModelDefinitions] = useState<
ModelDefinitions | undefined ModelDefinitions | undefined
>(undefined); >(undefined);
@@ -91,10 +91,12 @@ export function TankArmor(props: TankArmorProps) {
const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]); const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]);
const isVisible = isHull; const isVisible = isHull;
const thickness = tankModelDefinition.armor.thickness[armorId]; const thickness = tankModelDefinition.armor.thickness[armorId];
const isSpaced = tankModelDefinition.armor.spaced?.includes(armorId);
if (!isVisible || thickness === undefined) return null; if (!isVisible || thickness === undefined) return null;
return ( return (
<ArmorMesh <ArmorMesh
spaced={isSpaced}
key={node.uuid} key={node.uuid}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
thickness={thickness} thickness={thickness}
@@ -116,10 +118,13 @@ export function TankArmor(props: TankArmorProps) {
const isVisible = isCurrentTurret; const isVisible = isCurrentTurret;
const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]); const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]);
const thickness = turretModelDefinition.armor.thickness[armorId]; const thickness = turretModelDefinition.armor.thickness[armorId];
const isSpaced =
turretModelDefinition.armor.spaced?.includes(armorId);
if (!isVisible || thickness === undefined) return null; if (!isVisible || thickness === undefined) return null;
return ( return (
<ArmorMesh <ArmorMesh
spaced={isSpaced}
key={node.uuid} key={node.uuid}
position={turretOrigin} position={turretOrigin}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
@@ -148,10 +153,13 @@ export function TankArmor(props: TankArmorProps) {
const isVisible = isCurrentGun; const isVisible = isCurrentGun;
const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]); const armorId = parseInt(node.name.match(/.+_armor_(\d+)/)![1]);
const thickness = gunModelDefinition.armor.thickness[armorId]; const thickness = gunModelDefinition.armor.thickness[armorId];
const isSpaced =
gunModelDefinition.armor.spaced?.includes(armorId);
if (!isVisible || thickness === undefined) return null; if (!isVisible || thickness === undefined) return null;
return ( return (
<ArmorMesh <ArmorMesh
spaced={isSpaced}
key={node.uuid} key={node.uuid}
position={turretOrigin.clone().add(gunOrigin)} position={turretOrigin.clone().add(gunOrigin)}
geometry={(node as Mesh).geometry} geometry={(node as Mesh).geometry}
+12 -6
View File
@@ -12,25 +12,31 @@ interface ArmorMeshProps extends MeshProps {
ricochet: number; ricochet: number;
caliber: number; caliber: number;
normalization: number; normalization: number;
spaced?: boolean;
} }
// shader split: https://github.com/FarazzShaikh/THREE-CustomShaderMaterial/issues/48
export function ArmorMesh({ export function ArmorMesh({
thickness, thickness,
penetration, penetration,
caliber, caliber,
ricochet, ricochet,
normalization, normalization,
spaced = false,
...props ...props
}: ArmorMeshProps) { }: ArmorMeshProps) {
const opaqueArmor = useTankopedia((state) => state.model.opaqueArmor); const opaqueArmor = useTankopedia((state) => state.model.opaqueArmor);
return ( return (
<> <>
<mesh {...props}> {!spaced && (
<meshBasicMaterial colorWrite={false} /> <mesh {...props}>
</mesh> <meshBasicMaterial colorWrite={false} />
</mesh>
)}
<mesh {...props} renderOrder={1}> <mesh {...props} renderOrder={spaced ? 3 : 1}>
<CustomShaderMaterial <CustomShaderMaterial
baseMaterial={MeshStandardMaterial} baseMaterial={MeshStandardMaterial}
transparent transparent
@@ -42,10 +48,10 @@ export function ArmorMesh({
ricochet: { value: ricochet * (Math.PI / 180) }, ricochet: { value: ricochet * (Math.PI / 180) },
caliber: { value: caliber }, caliber: { value: caliber },
normalization: { value: normalization * (Math.PI / 180) }, normalization: { value: normalization * (Math.PI / 180) },
spaced: { value: spaced },
}} }}
vertexShader={vertex} vertexShader={vertex}
// split shaders due to https://github.com/FarazzShaikh/THREE-CustomShaderMaterial/issues/48 fragmentShader={opaqueArmor && !spaced ? fragmentOpaque : fragment}
fragmentShader={opaqueArmor ? fragmentOpaque : fragment}
/> />
</mesh> </mesh>
</> </>
@@ -6,6 +6,7 @@ uniform float penetration;
uniform float ricochet; uniform float ricochet;
uniform float caliber; uniform float caliber;
uniform float normalization; uniform float normalization;
uniform bool spaced;
void main() { void main() {
vec3 normalizedNormal = normalize(vNormal); vec3 normalizedNormal = normalize(vNormal);
@@ -41,5 +42,11 @@ void main() {
} }
} }
csm_FragColor = vec4(1.0, 0.0, 0.0, (1.0 - penetrationChance) * 0.5); float alpha = (1.0 - penetrationChance) * 0.5;
if (spaced) {
csm_FragColor = vec4(0.0, 0.0, 1.0, alpha);
} else {
csm_FragColor = vec4(1.0, 0.0, 0.0, alpha);
}
} }