mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-24 20:19:49 +02:00
feat: stride mis-match management
This commit is contained in:
1 parent
15a8e53e22
commit
510eebd2f4
4 files changed
+79
-44
No files matched your search
Vendored
+1
@@ -10,6 +10,7 @@
|
|||||||
"BINORMAL",
|
"BINORMAL",
|
||||||
"Binormals",
|
"Binormals",
|
||||||
"blitzstars",
|
"blitzstars",
|
||||||
|
"Camo",
|
||||||
"classname",
|
"classname",
|
||||||
"cleandist",
|
"cleandist",
|
||||||
"cockroackdb",
|
"cockroackdb",
|
||||||
|
|||||||
@@ -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>(
|
||||||
|
|||||||
@@ -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
@@ -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 {
|
||||||
|
|||||||
Reference in new issue
Block a user