diff --git a/docs/changelogs/1.29.15.md b/docs/changelogs/1.29.15.md new file mode 100644 index 000000000..1daf674ea --- /dev/null +++ b/docs/changelogs/1.29.15.md @@ -0,0 +1,5 @@ +# BlitzKit 1.29.15 + +## Fixes + +- Tanks now use alpha clipping to render translucency, fixing a lot of "ghostly" looking tanks diff --git a/packages/core/src/streams/bufferToBigInt.ts b/packages/core/src/streams/bufferToBigInt.ts new file mode 100644 index 000000000..564401728 --- /dev/null +++ b/packages/core/src/streams/bufferToBigInt.ts @@ -0,0 +1,3 @@ +export function bufferToBigInt(buffer: ArrayBuffer) { + return new DataView(buffer).getBigUint64(0, true); +} \ No newline at end of file diff --git a/packages/core/src/streams/index.ts b/packages/core/src/streams/index.ts index 2cf686118..bd8949a2d 100644 --- a/packages/core/src/streams/index.ts +++ b/packages/core/src/streams/index.ts @@ -1,4 +1,5 @@ export * from './buffer'; +export * from './bufferToBigInt'; export * from './dds'; export * from './dids'; export * from './pvr'; @@ -7,3 +8,4 @@ export * from './sc2'; export * from './scg'; export * from './scpg'; export * from './windows'; + diff --git a/packages/scripts/src/buildAssets/tankModels.ts b/packages/scripts/src/buildAssets/tankModels.ts index ca206dad4..1d2ee278b 100644 --- a/packages/scripts/src/buildAssets/tankModels.ts +++ b/packages/scripts/src/buildAssets/tankModels.ts @@ -12,12 +12,14 @@ export async function tankModels() { using uploader = new AssetUploader("tank models"); const nodeIO = new NodeIO().registerExtensions(ALL_EXTENSIONS); - const nations = vfs.dir(`Data/XML/item_defs/vehicles`).filter((nation) => nation !== "common") + const nations = vfs + .dir(`Data/XML/item_defs/vehicles`) + .filter((nation) => nation !== "common"); for (const nationIndex in nations) { const nation = nations[nationIndex]; const tanks = await vfs.xml<{ root: VehicleDefinitionList }>( - `Data/XML/item_defs/vehicles/${nation}/list.xml` + `Data/XML/item_defs/vehicles/${nation}/list.xml`, ); const entries = Object.entries(tanks.root); @@ -26,11 +28,11 @@ export async function tankModels() { const id = toUniqueId(nation, tank.id); const parameters = await vfs.yaml( - `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml` + `Data/3d/Tanks/Parameters/${nation}/${tankKey}.yaml`, ); const model = await extractModel( vfs, - parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, "") + parameters.resourcesPath.blitzModelPath.replace(/\.sc2$/, ""), ); const content = Buffer.from(await nodeIO.writeBinary(model)); @@ -39,4 +41,4 @@ export async function tankModels() { } await uploader.flush(); -} +} \ No newline at end of file diff --git a/packages/scripts/src/core/blitz/extractArmor.ts b/packages/scripts/src/core/blitz/extractArmor.ts index d30b38433..bf504d53a 100644 --- a/packages/scripts/src/core/blitz/extractArmor.ts +++ b/packages/scripts/src/core/blitz/extractArmor.ts @@ -6,13 +6,13 @@ import { } from "@blitzkit/core"; import { Accessor, Document, Node, Scene } from "@gltf-transform/core"; import { times } from "lodash-es"; -import { SteamVFS } from "../vfs/steam"; +import { AbstractVFS } from "../vfs/abstract"; import { vertexAttributeGLTFName, vertexAttributeGltfVectorSizes, } from "./extractModel/constants"; -export async function extractArmor(vfs: SteamVFS, fileName: string) { +export async function extractArmor(vfs: AbstractVFS, fileName: string) { const sc2Path = `Data/3d/Tanks/CollisionMeshes/${fileName}.sc2`; const scgPath = `Data/3d/Tanks/CollisionMeshes/${fileName}.scg`; const sc2 = new Sc2ReadStream( @@ -141,4 +141,4 @@ export async function extractArmor(vfs: SteamVFS, fileName: string) { parseHierarchies(sc2["#hierarchy"], scene); return document; -} +} \ No newline at end of file diff --git a/packages/scripts/src/core/blitz/extractModel/index.ts b/packages/scripts/src/core/blitz/extractModel/index.ts index f42a018bf..c535c86c6 100644 --- a/packages/scripts/src/core/blitz/extractModel/index.ts +++ b/packages/scripts/src/core/blitz/extractModel/index.ts @@ -1,4 +1,5 @@ import { + bufferToBigInt, Hierarchy, Sc2ReadStream, ScgReadStream, @@ -9,7 +10,7 @@ import { Document, Material, Node, Scene } from "@gltf-transform/core"; import { dedup, prune } from "@gltf-transform/functions"; import { times } from "lodash-es"; import { dirname } from "path"; -import { SteamVFS } from "../../vfs/steam"; +import { AbstractVFS } from "../../vfs/abstract"; import { readBaseColor } from "../readBaseColor"; import { readNormal } from "../readNormal"; import { readRoughnessMetallic } from "../readRoughnessMetallic"; @@ -25,7 +26,7 @@ const omitMeshNames = { end: ["_POINT"], }; -export async function extractModel(vfs: SteamVFS, path: string) { +export async function extractModel(vfs: AbstractVFS, path: string) { const sc2Path = `Data/3d/${path}.sc2`; const scgPath = `Data/3d/${path}.scg`; const sc2 = new Sc2ReadStream( @@ -40,7 +41,7 @@ export async function extractModel(vfs: SteamVFS, path: string) { const materials = new Map(); for (const node of sc2["#dataNodes"]) { - const id = new DataView(node["#id"]).getBigUint64(0, true); + const id = bufferToBigInt(node["#id"]); if (node.parentMaterialKey !== undefined) { /** @@ -80,8 +81,20 @@ export async function extractModel(vfs: SteamVFS, path: string) { configIndex < node.configCount; configIndex++ ) { - if (!hasAlpha) continue; - material.setAlphaMode("BLEND").setDoubleSided(true); + const archive = node[`configArchive_${configIndex}`]; + + if ( + archive.configName !== "Default" || + !archive.enabledPresets?.AlphaTest + ) { + continue; + } + + const view = new DataView(archive.properties.alphatestThreshold); + const _ = view.getUint8(0); // only god knows what these flags are + const alphaCutoff = view.getFloat32(1, true); + + material.setAlphaMode("MASK").setAlphaCutoff(alphaCutoff); } } @@ -116,7 +129,7 @@ export async function extractModel(vfs: SteamVFS, path: string) { ); } - materials.set(new DataView(node["#id"]).getBigUint64(0, true), material); + materials.set(id, material); } } @@ -266,4 +279,4 @@ export async function extractModel(vfs: SteamVFS, path: string) { await document.transform(prune({ keepAttributes: true }), dedup()); return document; -} +} \ No newline at end of file