From 7235291e69c77b4923d8934d90dbfce65b33c0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:34:04 -0600 Subject: [PATCH] feat: started work on armor extraction --- public/test/13569.glb | Bin 16678756 -> 16751416 bytes public/test/6225.glb | Bin 2852868 -> 2902788 bytes scripts/buildAssets/circleFlags.ts | 2 +- scripts/buildAssets/constants.ts | 14 ++ scripts/buildAssets/definitions.ts | 2 +- scripts/buildAssets/index.ts | 15 -- scripts/buildAssets/moduleIcons.ts | 2 +- scripts/buildAssets/scratchedFlags.ts | 2 +- scripts/buildAssets/shellIcons.ts | 2 +- scripts/buildAssets/tankArmors.ts | 30 ++-- scripts/buildAssets/tankIcons.ts | 2 +- scripts/buildAssets/tankModels.ts | 13 +- src/core/blitz/extractArmor.ts | 226 ++++++++++++++++++++++++++ src/core/blitz/extractModel.ts | 6 +- src/core/streams/sc2.ts | 1 + src/core/streams/scg.ts | 3 + 16 files changed, 277 insertions(+), 43 deletions(-) create mode 100644 scripts/buildAssets/constants.ts create mode 100644 src/core/blitz/extractArmor.ts diff --git a/public/test/13569.glb b/public/test/13569.glb index d506846b4ccd491af025f5caad87d086eaf664dc..493f092f3494d2772d4f12ed4a9a812717613ca9 100644 GIT binary patch delta 69686 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 F{{=|M9M=E< diff --git a/public/test/6225.glb b/public/test/6225.glb index dd6b9917d47ba5446939223043521bfa7482c614..30e23e545bc64fd7c3e291b0921e54ca3be462ef 100644 GIT binary patch delta 44212 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 j4Ab@#;7_C4#I1UE}%j z0G($r8=&*I%{oSIT#pWC3w4-T9Q5iIgC8$oB!!|oe7-6@C@^%mwm^gb6(h7^wO=3i zS1P8;(^lade^4=v*>@!Z=s0|eDtwHNZE855#wG~p3cSJ2z{QdT;sCaOxHk}=!}qnV zyzfwBH;m~=;QZ1ATx$tn>xb^1_#D2kHP2z7j^Qa?;Jq|o<6mPeR)AKPiT zv|R8mEf+j$vpmAYyY39Y>8Qt-SBkvLrm(R0ubo`w(8O2*87#g3Iy76!r<;A1boEQh3lf0KLHgtUDyQglS5> zLBah~Fvoq^+z)Ssa$Lg1eJdompNEKB4qwKOz;JZ{_jf06i8EX+IA2x^&R4BzI9-Et z7-)i_20zF523lva;C@{rxKG;BaBgh?ni@KJn_ZrBYX$GgTH>99$#5<=!t~zBu;6?X zPL6M>fCcS?a3vCez0Na5tGdJ8n|Erg2HD6BQb+q<_1 z1m2b6Ee$LBlC#{U5dB_16kDCVzu3Y!yirsZ!c zhrxX(;PfVu3XMbf(Eb!}vtys$l!T#!g)sE`2Qcvhahss>pr7NZhB!V`puV?=`xKM& zDeeLc;Ze)>ebJthu#hJAjO70-WIDx?Zaz}NF)e8p)A#~!gUpe0aAzwWy(V}u9pIRb z-;Q(%$HWzQ8(bSu;9hzRt|qr24q!`Xt91?&cWR)7_m2+NE6lM~xHG8xEQ3W2`1hdd zV~&ZpPR-GE^Hp1S91V6IeO_@?Ea_K|h6VWSopvA7EbRLGdx#7huOLKThIdTxc*4t~ z4)h&Q_%x00o-Xk38^pqnrYKj2e#tUur z@r0tPw%{8YUBbjN3|-}X#lWe+>XCMZr`0#o?lqzssKXsz!(lLlt%=MBymcTrf<9f< zBOQvV*$%MbcAu%+c-N*z5!n`Ii}O`1ra5r){SKdnGz#ebqPdq+Ni|X2~lOOK$)arU9l;})$G`EM=>qaD$YTXg*>`cbHRP;^s zn-guVi4;0GJqW?`r((6bEyYA#F^&{NazPc`Kh+X8ST4rU@?#9lVeUN!^j)rouG1KT zug|7tSgsIEK??cZPpaVS)3LCDZ_kF9YJP}`8O(*4@CXxo=S-~Dlmswc0+_M@_>YPN zC?3NYNdVI&fGG=LkpLmMIu;9Ck^q)V0819YLIJ9v{w#(_0$45qELi{xNPyo`h$MjR z62O)Pu(<$<@mQ@b31GVfuw?;ggQI9)P>dvi?GnJ21)vj#F^3@*j!FVVT>?a90q}1m z3gA5#4@V^dqAmfVvH(#ozyyUz0yr)K99aMd1*nGl^RZe-62Nf@;K%~tQK!lL{(LOr zNCG%60UTKXMkN4)c3g^J*GF8@q;lEWB;qismI#m(@iX|f!eTMjKx4*bT!s_-|8lI76ca%g#SXk3ohCtK?^Sq|MThn^<~-W-_X_~m$= zTpXFZI^s8$R8W}CyX#a=m2kg30nKCYvpp$F5?S zyhq$MljRjnHd{59Otsd@RTD2_*Vf9bn|NR2k)cn|s$ZP)?1A>_GH9AE^r(o|aBmDf z4L+K#!LLnv`Urgk9#7Z6AAeZ{+owxF%@lepXvoxfY|a=$KMFrW-@)H9c#tV9z(e*h zQ&WKZpL&8b*rP#YrUw3Uy%eT03*j(z8SplCg{D`*Z)O(5=IL^Z+mEmE-&h2b argument.startsWith('--target')) diff --git a/scripts/buildAssets/moduleIcons.ts b/scripts/buildAssets/moduleIcons.ts index 8900f8a0f..533e9269b 100644 --- a/scripts/buildAssets/moduleIcons.ts +++ b/scripts/buildAssets/moduleIcons.ts @@ -1,9 +1,9 @@ import { readdir } from 'fs/promises'; -import { DATA, DOI } from '.'; import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL'; import commitMultipleFiles, { FileChange, } from '../../src/core/blitzkrieg/commitMultipleFiles'; +import { DATA, DOI } from './constants'; export async function buildModuleIcons() { console.log('Building module icons...'); diff --git a/scripts/buildAssets/scratchedFlags.ts b/scripts/buildAssets/scratchedFlags.ts index 1df8d2671..c6f056933 100644 --- a/scripts/buildAssets/scratchedFlags.ts +++ b/scripts/buildAssets/scratchedFlags.ts @@ -1,9 +1,9 @@ import { readdir } from 'fs/promises'; -import { DATA, DOI } from '.'; import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL'; import commitMultipleFiles, { FileChange, } from '../../src/core/blitzkrieg/commitMultipleFiles'; +import { DATA, DOI } from './constants'; export async function buildScratchedFlags() { console.log('Building scratched flags...'); diff --git a/scripts/buildAssets/shellIcons.ts b/scripts/buildAssets/shellIcons.ts index 3ff88207e..849a99c19 100644 --- a/scripts/buildAssets/shellIcons.ts +++ b/scripts/buildAssets/shellIcons.ts @@ -1,11 +1,11 @@ import { readdir } from 'fs/promises'; import sharp from 'sharp'; -import { DATA, DOI } from '.'; import { readDVPLFile } from '../../src/core/blitz/readDVPLFile'; import { readStringDVPL } from '../../src/core/blitz/readStringDVPL'; import commitMultipleFiles, { FileChange, } from '../../src/core/blitzkrieg/commitMultipleFiles'; +import { DATA, DOI } from './constants'; export async function buildShellIcons() { console.log('Building shell icons...'); diff --git a/scripts/buildAssets/tankArmors.ts b/scripts/buildAssets/tankArmors.ts index f60d1ae9a..d8a1ab748 100644 --- a/scripts/buildAssets/tankArmors.ts +++ b/scripts/buildAssets/tankArmors.ts @@ -1,13 +1,19 @@ +import { NodeIO } from '@gltf-transform/core'; import { readdir } from 'fs/promises'; -import { DATA, DOI } from '.'; -import { NATION_IDS } from '../../src/constants/nations'; -import { extractModel } from '../../src/core/blitz/extractModel'; +import { extractArmor } from '../../src/core/blitz/extractArmor'; import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL'; +import { toUniqueId } from '../../src/core/blitz/toUniqueId'; +import { DATA, DOI } from './constants'; import { VehicleDefinitionList } from './definitions'; +BigInt.prototype.toJSON = function () { + return this.toString(); +}; + export async function buildTankArmors() { console.log('Building tank armors...'); + const nodeIO = new NodeIO(); const nations = await readdir(`${DATA}/${DOI.vehicleDefinitions}`).then( (nations) => nations.filter((nation) => nation !== 'common'), ); @@ -20,17 +26,19 @@ export async function buildTankArmors() { for (const tankKey in tanks.root) { const tank = tanks.root[tankKey]; - const nationVehicleId = tank.id; - const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; + const id = toUniqueId(nation, tank.id); - if (id !== 24609) continue; // concept 1b - - const model = extractModel( - DATA, - `${DOI.collisionMeshes}/${nation}-${tankKey}`, - ); + // if (id !== 7297) continue; // 60tp + if (id !== 5137) continue; // tiger ii + // if (id !== 24609) continue; // concept 1b console.log(`Building armor ${id} @ ${nation}/${tankKey}`); + + const armor = await extractArmor(DATA, `${nation}-${tankKey}`); + + // await nodeIO.write('temp/armor/index.gltf', armor); + + // writeFile('test.sc2.json', JSON.stringify(sc2, null, 2)); } }), ); diff --git a/scripts/buildAssets/tankIcons.ts b/scripts/buildAssets/tankIcons.ts index a8ef3847e..a6ea24d95 100644 --- a/scripts/buildAssets/tankIcons.ts +++ b/scripts/buildAssets/tankIcons.ts @@ -1,5 +1,4 @@ import { readdir } from 'fs/promises'; -import { DATA, DOI } from '.'; import { NATION_IDS } from '../../src/constants/nations'; import { readBase64DVPL } from '../../src/core/blitz/readBase64DVPL'; import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL'; @@ -7,6 +6,7 @@ import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL'; import commitMultipleFiles, { FileChange, } from '../../src/core/blitzkrieg/commitMultipleFiles'; +import { DATA, DOI } from './constants'; import { VehicleDefinitionList } from './definitions'; export interface TankParameters { diff --git a/scripts/buildAssets/tankModels.ts b/scripts/buildAssets/tankModels.ts index 9cb4b3fa5..3a3a0a6f2 100644 --- a/scripts/buildAssets/tankModels.ts +++ b/scripts/buildAssets/tankModels.ts @@ -1,11 +1,11 @@ import { NodeIO } from '@gltf-transform/core'; import { readdir, writeFile } from 'fs/promises'; import { Vector3Tuple } from 'three'; -import { DATA, DOI } from '.'; -import { NATION_IDS } from '../../src/constants/nations'; import { extractModel } from '../../src/core/blitz/extractModel'; import { readXMLDVPL } from '../../src/core/blitz/readXMLDVPL'; import { readYAMLDVPL } from '../../src/core/blitz/readYAMLDVPL'; +import { toUniqueId } from '../../src/core/blitz/toUniqueId'; +import { DATA, DOI } from './constants'; import { VehicleDefinitionList } from './definitions'; import { TankParameters } from './tankIcons'; @@ -37,8 +37,7 @@ export async function buildTankModels() { for (const tankKey in tanks.root) { const tank = tanks.root[tankKey]; - const nationVehicleId = tank.id; - const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; + const id = toUniqueId(nation, tank.id); // if (id !== 15697) continue; // chieftain // if (id !== 24609) continue; // concept 1b @@ -49,13 +48,13 @@ export async function buildTankModels() { // if (id !== 7297) continue; // 60tp // if (id !== 1) continue; // t-34 // if (id !== 6753) continue; // type 71 - // if (id !== 5137) continue; // tiger ii + if (id !== 5137) continue; // tiger ii // if (id !== 11633) continue; // forest witch // if (id !== 6225) continue; // fv215b // if (id !== 4481) continue; // kran // if (id !== 9489) continue; // e100 // if (id !== 12049) continue; // jg e100 - if (id !== 13569) continue; // jg e100 + // if (id !== 13569) continue; // obj 268 console.log(`Building model ${id} @ ${nation}/${tankKey}`); @@ -69,8 +68,6 @@ export async function buildTankModels() { ); writeFile(`public/test/${id}.glb`, await nodeIO.writeBinary(model)); - // await mkdir(`dist/assets/models/${id}`, { recursive: true }); - // nodeIO.write(`dist/assets/models/${id}/index.gltf`, model); } }), ); diff --git a/src/core/blitz/extractArmor.ts b/src/core/blitz/extractArmor.ts new file mode 100644 index 000000000..785701ae6 --- /dev/null +++ b/src/core/blitz/extractArmor.ts @@ -0,0 +1,226 @@ +import { Document, Node, Scene } from '@gltf-transform/core'; +import { writeFile } from 'fs/promises'; +import { range, times } from 'lodash'; +import { + Matrix4, + Quaternion, + Vector3, + Vector3Tuple, + Vector4Tuple, +} from 'three'; +import { Hierarchy, Sc2Stream } from '../streams/sc2'; +import { ScgStream, vertexAttributeVectorSizes } from '../streams/scg'; +import { VertexAttribute } from '../streams/scpg'; +import { readDVPLFile } from './readDVPLFile'; + +Buffer.prototype.toJSON = function () { + return [...(this as Buffer)].map((int) => int.toString(16)).join(''); +}; + +const MAX_FLOAT32 = 2 ** 127 * (2 - 2 ** -23); + +const vertexAttributeGLTFName: Partial> = { + [VertexAttribute.VERTEX]: 'POSITION', + [VertexAttribute.NORMAL]: 'NORMAL', + [VertexAttribute.COLOR]: 'COLOR_0', + [VertexAttribute.TEXCOORD0]: 'TEXCOORD_0', + [VertexAttribute.TEXCOORD1]: 'TEXCOORD_0', + [VertexAttribute.TEXCOORD2]: 'TEXCOORD_0', + [VertexAttribute.TEXCOORD3]: 'TEXCOORD_0', + [VertexAttribute.TANGENT]: 'TANGENT', + [VertexAttribute.JOINTINDEX]: 'JOINT_0', + [VertexAttribute.JOINTWEIGHT]: 'WEIGHT_0', +}; + +const vertexAttributeGltfVectorSizes = { + ...vertexAttributeVectorSizes, + + [VertexAttribute.TANGENT]: 4, +} as const; + +export async function extractArmor( + data: string, + fileName: string, + baseColor?: Vector3Tuple, +) { + const sc2Path = `${data}/3d/Tanks/CollisionMeshes/${fileName}.sc2.dvpl`; + const scgPath = `${data}/3d/Tanks/CollisionMeshes/${fileName}.scg.dvpl`; + const sc2 = new Sc2Stream(await readDVPLFile(sc2Path)).sc2(); + const scg = new ScgStream(await readDVPLFile(scgPath)).scg(); + const document = new Document(); + const scene = document.createScene(); + const buffer = document.createBuffer(); + + writeFile('test.sc2.json', JSON.stringify(sc2, null, 2)); + + function parseHierarchies(hierarchies: Hierarchy[], parent: Scene | Node) { + hierarchies.forEach((hierarchy) => { + console.log(`hierarchy: ${hierarchy.name}`); + + const node = document.createNode(hierarchy.name); + const components = times( + hierarchy.components.count, + (index) => hierarchy.components[index.toString().padStart(4, '0')], + ); + + components.forEach((component) => { + switch (component['comp.typename']) { + case 'TransformComponent': { + const translation = new Vector3(); + const rotation = new Quaternion(); + const scale = new Vector3(); + + new Matrix4() + .multiplyMatrices( + new Matrix4().compose( + new Vector3().fromArray(component['tc.worldTranslation']), + new Quaternion().fromArray(component['tc.worldRotation']), + new Vector3().fromArray(component['tc.worldScale']), + ), + new Matrix4().compose( + new Vector3().fromArray(component['tc.localTranslation']), + new Quaternion().fromArray(component['tc.localRotation']), + new Vector3().fromArray(component['tc.localScale']), + ), + ) + .decompose(translation, rotation, scale); + + node.setTranslation(translation.toArray()); + node.setRotation(rotation.toArray() as Vector4Tuple); + node.setScale(scale.toArray()); + + break; + } + + case 'RenderComponent': { + let minLODDistanceBatchId: undefined | number; + + if (component['rc.renderObj']['rb0.lodIndex'] === -1) { + minLODDistanceBatchId = 0; + } else { + const lodList = components.find( + (component) => component['comp.typename'] === 'LodComponent', + ); + + if ( + lodList === undefined || + lodList['comp.typename'] !== 'LodComponent' // type annotation hack + ) { + throw new SyntaxError('Missing LodComponent'); + } + + let minLODDistance = Infinity; + let isFirstMaxFloat = true; + let lodIndexStreak = 0; + let lodIndexStreakIndex: undefined | number = undefined; + + range(component['rc.renderObj']['ro.batchCount']).forEach( + (id) => { + const lodIndex = + component['rc.renderObj'][`rb${id}.lodIndex`]; + const lodDistance = + lodList['lc.loddist'][`distance${lodIndex}`]; + + if (lodIndexStreakIndex === lodIndex) { + lodIndexStreak++; + } else { + lodIndexStreak = 0; + lodIndexStreakIndex = lodIndex; + } + + if ( + lodDistance < minLODDistance || + (lodDistance === minLODDistance && lodIndexStreak > 0) || + (lodDistance === MAX_FLOAT32 && isFirstMaxFloat) + ) { + if (lodDistance === MAX_FLOAT32) isFirstMaxFloat = false; + minLODDistance = lodDistance; + minLODDistanceBatchId = id; + } + }, + ); + } + + const batch = + component['rc.renderObj']['ro.batches'][ + minLODDistanceBatchId!.toString().padStart(4, '0') + ]; + const polygonGroup = scg.get(batch['rb.datasource']); + + if (!polygonGroup) { + console.warn( + `Missing polygon group ${batch['rb.datasource']} (${hierarchy.name}); skipping...`, + ); + + break; + } + + const indicesAccessor = document + .createAccessor() + .setType('SCALAR') + .setArray(new Uint16Array(polygonGroup.indices)) + .setBuffer(buffer); + const primitive = document + .createPrimitive() + .setIndices(indicesAccessor); + const attributes: Partial> = {}; + const indexedAttributes: VertexAttribute[] = []; + + polygonGroup.vertices.forEach((vertex) => { + vertex.forEach(({ attribute, value }) => { + if (attributes[attribute] === undefined) { + attributes[attribute] = []; + indexedAttributes.push(attribute); + } + + attributes[attribute]!.push(value); + }); + }); + + if (indexedAttributes.includes(VertexAttribute.TANGENT)) { + attributes[VertexAttribute.TANGENT] = attributes[ + VertexAttribute.TANGENT + ]!.map((tangent) => [...tangent, 1]); + } + + indexedAttributes.forEach((attribute) => { + const name = vertexAttributeGLTFName[attribute]; + if (!name || primitive.getAttribute(name)) return; + const vertexSize = vertexAttributeGltfVectorSizes[attribute]; + + const attributeAccessor = document + .createAccessor(name) + .setType(vertexSize === 1 ? 'SCALAR' : `VEC${vertexSize}`) + .setArray(new Float32Array(attributes[attribute]!.flat())) + .setBuffer(buffer); + primitive.setAttribute(name, attributeAccessor); + }); + + const mesh = document + .createMesh(batch['##name']) + .addPrimitive(primitive); + + node.setMesh(mesh); + + break; + } + + default: + throw new TypeError( + `Unhandled component type: ${component['comp.typename']}`, + ); + } + }); + + if (hierarchy['#hierarchy']) { + parseHierarchies(hierarchy['#hierarchy'], node); + } + + parent.addChild(node); + }); + } + + parseHierarchies(sc2['#hierarchy'], scene); + + return document; +} diff --git a/src/core/blitz/extractModel.ts b/src/core/blitz/extractModel.ts index 991260554..403af4d92 100644 --- a/src/core/blitz/extractModel.ts +++ b/src/core/blitz/extractModel.ts @@ -36,8 +36,8 @@ const vertexAttributeGltfVectorSizes = { } as const; const omitMeshNames = { - start: ['chassis_chassis_', 'chassis_track_crash_', 'HP_'], - end: ['_POINT'], + start: [], //['chassis_chassis_', 'chassis_track_crash_', 'HP_'], + end: [], //['_POINT'], }; export async function extractModel( @@ -262,7 +262,7 @@ export async function extractModel( if (!polygonGroup) { console.warn( - `Missing polygon group ${batch['rb.datasource']}; skipping...`, + `Missing polygon group ${batch['rb.datasource']} (${hierarchy.name}); skipping...`, ); break; diff --git a/src/core/streams/sc2.ts b/src/core/streams/sc2.ts index 8567f6f21..46c2fa585 100644 --- a/src/core/streams/sc2.ts +++ b/src/core/streams/sc2.ts @@ -42,6 +42,7 @@ interface EnabledPresets { interface Flags { AMBIENT_ATTENUATION_BOX: number; + BLENDING: number; } interface Properties { diff --git a/src/core/streams/scg.ts b/src/core/streams/scg.ts index 5dade80cd..5162a1570 100644 --- a/src/core/streams/scg.ts +++ b/src/core/streams/scg.ts @@ -1,3 +1,4 @@ +import { writeFile } from 'fs/promises'; import { ScpgStream, VertexAttribute } from './scpg'; interface PolygonGroupRaw { @@ -66,6 +67,8 @@ export class ScgStream extends ScpgStream { polygonGroupsRaw.push(polygonGroupRaw); } + writeFile('test.scg.json', JSON.stringify({ polygonGroupsRaw }, null, 2)); + polygonGroupsRaw.forEach((polygonGroupRaw) => { const indicesStream = new ScpgStream(polygonGroupRaw.indices); const indices: number[] = [];