fixes texturing
This commit is contained in:
+54
-2
@@ -158,8 +158,8 @@ function parseGeometry(chunk) {
|
|||||||
|
|
||||||
// One draw group per material, so each group can get its own texture.
|
// One draw group per material, so each group can get its own texture.
|
||||||
const order = [...Array(numTriangles).keys()].sort((x, y) => triMaterial[x] - triMaterial[y]);
|
const order = [...Array(numTriangles).keys()].sort((x, y) => triMaterial[x] - triMaterial[y]);
|
||||||
const indices = new Uint32Array(numTriangles * 3);
|
let indices = new Uint32Array(numTriangles * 3);
|
||||||
const groups = [];
|
let groups = [];
|
||||||
let current = null;
|
let current = null;
|
||||||
order.forEach((tri, slot) => {
|
order.forEach((tri, slot) => {
|
||||||
indices[slot * 3] = tris[tri * 3];
|
indices[slot * 3] = tris[tri * 3];
|
||||||
@@ -173,6 +173,19 @@ function parseGeometry(chunk) {
|
|||||||
current.count += 3;
|
current.count += 3;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Many GTA:SA exporters leave the per-triangle material index at zero and put
|
||||||
|
// the real split in the BINMESH extension instead. The struct then yields a
|
||||||
|
// single group and the whole model renders with material 0's texture, so
|
||||||
|
// prefer BINMESH whenever it describes more submeshes than the struct did.
|
||||||
|
const binMesh = extension && extension.find(RW.BINMESH);
|
||||||
|
if (binMesh) {
|
||||||
|
const split = parseBinMesh(binMesh, numVertices);
|
||||||
|
if (split && split.groups.length > groups.length) {
|
||||||
|
indices = split.indices;
|
||||||
|
groups = split.groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
numVertices,
|
numVertices,
|
||||||
positions,
|
positions,
|
||||||
@@ -187,6 +200,45 @@ function parseGeometry(chunk) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The BINMESH extension holds the render-ready index lists, one submesh per
|
||||||
|
// material. flags bit 0 means the indices are tristrips rather than triangle
|
||||||
|
// lists; degenerate triangles are the standard way strips stitch together, so
|
||||||
|
// they are dropped rather than emitted as zero area faces.
|
||||||
|
function parseBinMesh(chunk, numVertices) {
|
||||||
|
const r = chunk.reader();
|
||||||
|
if (r.remaining < 12) return null;
|
||||||
|
const strip = r.u32() & 1;
|
||||||
|
const numMeshes = r.u32();
|
||||||
|
r.u32(); // total index count, recomputed below
|
||||||
|
const out = [];
|
||||||
|
const groups = [];
|
||||||
|
for (let i = 0; i < numMeshes; i++) {
|
||||||
|
if (r.remaining < 8) return null;
|
||||||
|
const count = r.u32();
|
||||||
|
const material = r.u32();
|
||||||
|
if (r.remaining < count * 4) return null;
|
||||||
|
const list = new Uint32Array(count);
|
||||||
|
for (let k = 0; k < count; k++) list[k] = r.u32();
|
||||||
|
|
||||||
|
const start = out.length;
|
||||||
|
if (strip) {
|
||||||
|
for (let k = 0; k + 2 < count; k++) {
|
||||||
|
const a = list[k], b = list[k + (k & 1 ? 2 : 1)], c = list[k + (k & 1 ? 1 : 2)];
|
||||||
|
if (a === b || b === c || a === c) continue; // strip stitch
|
||||||
|
out.push(a, b, c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let k = 0; k + 2 < count; k += 3) out.push(list[k], list[k + 1], list[k + 2]);
|
||||||
|
}
|
||||||
|
if (out.length > start) groups.push({ start, count: out.length - start, material });
|
||||||
|
}
|
||||||
|
if (!groups.length) return null;
|
||||||
|
for (const index of out) {
|
||||||
|
if (index >= numVertices) return null; // not indices we can trust
|
||||||
|
}
|
||||||
|
return { indices: Uint32Array.from(out), groups };
|
||||||
|
}
|
||||||
|
|
||||||
export function parseDFF(buffer) {
|
export function parseDFF(buffer) {
|
||||||
const view = new DataView(buffer);
|
const view = new DataView(buffer);
|
||||||
let clump = new Chunk(view, 0);
|
let clump = new Chunk(view, 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user