feat: stride mis-match management

This commit is contained in:
TrèsAbhi committed 2023-12-25 11:21:39 -06:00
1 parent 15a8e53e22
commit 510eebd2f4
4 files changed
+79 -44

No files matched your search

+1
View File
@@ -10,6 +10,7 @@
"BINORMAL", "BINORMAL",
"Binormals", "Binormals",
"blitzstars", "blitzstars",
"Camo",
"classname", "classname",
"cleandist", "cleandist",
"cockroackdb", "cockroackdb",
+3 -1
View File
@@ -518,7 +518,9 @@ if (allTargets || targets?.includes('tankModels')) {
const nationVehicleId = tank.id; const nationVehicleId = tank.id;
const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1; const id = (nationVehicleId << 8) + (NATION_IDS[nation] << 4) + 1;
if (id !== 15697) continue; // if (id !== 15697) continue; // chieftain TODO: investigate vertices stream over read
// if (id !== 4417) continue; // amx m4 mle
if (id !== 7297) continue; // 60tp
console.log(`Building model ${id} @ ${nation}/${tankIndex}`); console.log(`Building model ${id} @ ${nation}/${tankIndex}`);
const parameters = await readYAMLDVPL<TankParameters>( const parameters = await readYAMLDVPL<TankParameters>(
+52 -40
View File
@@ -43,26 +43,26 @@ enum KAType {
} }
export enum VertexAttribute { export enum VertexAttribute {
VERTEX, VERTEX = 0,
NORMAL, NORMAL = 1,
COLOR, COLOR = 2,
TEXCOORD0, TEXCOORD0 = 3,
TEXCOORD1, TEXCOORD1 = 4,
TEXCOORD2, TEXCOORD2 = 5,
TEXCOORD3, TEXCOORD3 = 6,
TANGENT, TANGENT = 7,
BINORMAL, BINORMAL = 8,
HARD_JOINTINDEX, HARD_JOINTINDEX = 9,
PIVOT4, PIVOT4 = 10,
PIVOT_DEPRECATED, PIVOT_DEPRECATED = 11,
FLEXIBILITY, FLEXIBILITY = 12,
ANGLE_SIN_COS, ANGLE_SIN_COS = 13,
JOINTINDEX, JOINTINDEX = 14,
JOINTWEIGHT, JOINTWEIGHT = 15,
CUBETEXCOORD0, CUBETEXCOORD0 = 16,
CUBETEXCOORD1, CUBETEXCOORD1 = 17,
CUBETEXCOORD2, CUBETEXCOORD2 = 18,
CUBETEXCOORD3, CUBETEXCOORD3 = 19,
} }
export const vertexAttributeVectorSizes = { export const vertexAttributeVectorSizes = {
@@ -118,7 +118,6 @@ interface PolygonGroupRaw {
} }
type BlitzkriegVertex = { attribute: VertexAttribute; value: number[] }[]; type BlitzkriegVertex = { attribute: VertexAttribute; value: number[] }[];
interface BlitzkriegPolygonGroup { interface BlitzkriegPolygonGroup {
id: bigint;
vertices: BlitzkriegVertex[]; vertices: BlitzkriegVertex[];
indices: number[]; indices: number[];
} }
@@ -146,6 +145,9 @@ export class SCPGStream {
readRemaining() { readRemaining() {
return this.read(Number.POSITIVE_INFINITY); return this.read(Number.POSITIVE_INFINITY);
} }
readRemainingLength() {
return this.buffer.length - this.index;
}
consumeRemaining() { consumeRemaining() {
return this.consume(Number.POSITIVE_INFINITY); return this.consume(Number.POSITIVE_INFINITY);
} }
@@ -216,7 +218,7 @@ export class SCPGStream {
return this.consumeMatrixN(4); return this.consumeMatrixN(4);
} }
getVertexStride(vertexFormat: number) { static getVertexStride(vertexFormat: number) {
const flags = vertexFormat.toString(2); const flags = vertexFormat.toString(2);
return Object.values(VertexAttribute) return Object.values(VertexAttribute)
@@ -242,13 +244,14 @@ export class SCPGStream {
consumeSCG() { consumeSCG() {
const header = this.consumeSCGHeader(); const header = this.consumeSCGHeader();
const polygonGroupsRaw: PolygonGroupRaw[] = []; const polygonGroupsRaw: PolygonGroupRaw[] = [];
const polygonGroups = new Map<bigint, BlitzkriegPolygonGroup>();
for (let index = 0; index < header.nodeCount; index++) { for (let index = 0; index < header.nodeCount; index++) {
const polygonGroupRaw = this.consumeKA() as PolygonGroupRaw; const polygonGroupRaw = this.consumeKA() as PolygonGroupRaw;
polygonGroupsRaw.push(polygonGroupRaw); polygonGroupsRaw.push(polygonGroupRaw);
} }
const polygonGroups = polygonGroupsRaw.map((polygonGroupRaw) => { polygonGroupsRaw.forEach((polygonGroupRaw) => {
const indicesStream = new SCPGStream(polygonGroupRaw.indices); const indicesStream = new SCPGStream(polygonGroupRaw.indices);
const indices: number[] = []; const indices: number[] = [];
@@ -262,6 +265,17 @@ export class SCPGStream {
const verticesStream = new SCPGStream(polygonGroupRaw.vertices); const verticesStream = new SCPGStream(polygonGroupRaw.vertices);
const vertices: BlitzkriegVertex[] = []; const vertices: BlitzkriegVertex[] = [];
const stride =
SCPGStream.getVertexStride(polygonGroupRaw.vertexFormat) *
polygonGroupRaw.vertexCount;
if (verticesStream.buffer.length !== stride) {
console.warn(
`Vertex stride mismatch; expected ${stride}, got ${verticesStream.buffer.length}`,
);
return;
}
const vertexFormat = ( const vertexFormat = (
polygonGroupRaw.vertexFormat polygonGroupRaw.vertexFormat
@@ -273,13 +287,7 @@ export class SCPGStream {
).filter((type) => type !== null); ).filter((type) => type !== null);
for (let index = 0; index < polygonGroupRaw.vertexCount; index++) { for (let index = 0; index < polygonGroupRaw.vertexCount; index++) {
// TODO: ISSUE
vertices[index] = vertexFormat.map((attribute) => { vertices[index] = vertexFormat.map((attribute) => {
console.log(
VertexAttribute[attribute],
vertexAttributeVectorSizes[attribute],
);
return { return {
attribute, attribute,
value: verticesStream.consumeVectorN( value: verticesStream.consumeVectorN(
@@ -289,11 +297,14 @@ export class SCPGStream {
}); });
} }
return { if (verticesStream.readRemainingLength() !== 0) {
id: polygonGroupRaw['#id'].readBigUInt64LE(), throw new RangeError('Vertices stream was not fully consumed');
}
polygonGroups.set(polygonGroupRaw['#id'].readBigUInt64LE(), {
vertices, vertices,
indices, indices,
} satisfies BlitzkriegPolygonGroup; });
}); });
return polygonGroups; return polygonGroups;
@@ -573,7 +584,7 @@ export class SCPGStream {
.then(({ data, info }) => { .then(({ data, info }) => {
// fake it till you make it // fake it till you make it
for (let index = 0; index < data.length; index++) { for (let index = 0; index < data.length; index++) {
data[index] = -data[index] + 255; data[index] = 255 - data[index];
} }
return sharp(data, { raw: info }).jpeg().toBuffer(); return sharp(data, { raw: info }).jpeg().toBuffer();
@@ -598,7 +609,7 @@ export class SCPGStream {
.then(({ data, info }) => { .then(({ data, info }) => {
// https://www.youtube.com/watch?v=CGys6CnnYSg // https://www.youtube.com/watch?v=CGys6CnnYSg
for (let index = 0; index < data.length; index += 3) { for (let index = 0; index < data.length; index += 3) {
data[index + 2] = -data[index + 2] + 255; data[index + 2] = 255 - data[index + 2];
} }
return sharp(data, { raw: info }).jpeg().toBuffer(); return sharp(data, { raw: info }).jpeg().toBuffer();
@@ -644,7 +655,8 @@ export class SCPGStream {
components.forEach((component) => { components.forEach((component) => {
switch (component['comp.typename']) { switch (component['comp.typename']) {
case 'LodComponent': case 'LodComponent':
break; case 'DecorItemComponent':
case 'NewSlotComponent':
case 'SlotComponent': case 'SlotComponent':
break; break;
@@ -716,14 +728,14 @@ export class SCPGStream {
component['rc.renderObj']['ro.batches'][ component['rc.renderObj']['ro.batches'][
minLODDistanceBatchId!.toString().padStart(4, '0') minLODDistanceBatchId!.toString().padStart(4, '0')
]; ];
const polygonGroup = scg.find( const polygonGroup = scg.get(batch['rb.datasource']);
(group) => group.id === batch['rb.datasource'],
);
if (!polygonGroup) { if (!polygonGroup) {
throw new Error( console.warn(
`Missing polygon group ${batch['rb.datasource']}`, `Missing polygon group ${batch['rb.datasource']}; skipping...`,
); );
break;
} }
const indexedVertexAttributes: VertexAttribute[] = []; const indexedVertexAttributes: VertexAttribute[] = [];
+23 -3
View File
@@ -91,8 +91,6 @@ type Components = {
count: number; count: number;
} & Record<string, Component>; } & Record<string, Component>;
type LODDistance = Record<`distance${number}`, number>;
// 0001, 0002, 0003... // 0001, 0002, 0003...
type RoBatches = Record< type RoBatches = Record<
string, string,
@@ -146,7 +144,29 @@ export type Component =
} }
| { | {
'comp.typename': 'LodComponent'; 'comp.typename': 'LodComponent';
'lc.loddist': LODDistance; 'lc.loddist': Record<`distance${number}`, number>;
}
| {
'comp.typename': 'DecorItemComponent';
drawOrder: number;
shouldApplyCamo: boolean;
vanishTargetAlpha: number;
vanishWhenArmorShown: boolean;
}
| {
'comp.typename': 'NewSlotComponent';
slotItemsCount: number;
slots: {
[key: string]: {
configFilePath: string;
name: string;
transform: {
position: Vector3Tuple;
scale: Vector3Tuple;
rotation: Vector4Tuple;
};
};
};
}; };
interface SceneComponents { interface SceneComponents {