fix(3d): rewrite wrl fallback parser to maintain hierarchy and fix phase extraction
This commit is contained in:
@@ -191,71 +191,103 @@ function parseVrmlDirectFallback(
|
|||||||
const group = new THREE.Group();
|
const group = new THREE.Group();
|
||||||
group.name = 'WRL_Direct_Fallback_Root';
|
group.name = 'WRL_Direct_Fallback_Root';
|
||||||
|
|
||||||
const defRegex = /DEF\s+([^\s\{\[\(\)]+)[\s\S]*?(?:point\s*\[([\s\S]*?)\])[\s\S]*?(?:coordIndex\s*\[([\s\S]*?)\])/gi;
|
const tokenRegex = /(DEF\s+([^\s\{\[\(\)]+))|(\{)|(\})|(point\s*\[([\s\S]*?)\])|(coordIndex\s*\[([\s\S]*?)\])/gi;
|
||||||
let match: RegExpExecArray | null;
|
let match: RegExpExecArray | null;
|
||||||
|
|
||||||
|
const stack: { name: string; group: THREE.Group }[] = [{ name: 'ROOT', group }];
|
||||||
|
let currentGroup = group;
|
||||||
|
let lastDef: string | null = null;
|
||||||
|
let currentPoints: number[] | null = null;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
while ((match = defRegex.exec(vrmlText)) !== null) {
|
while ((match = tokenRegex.exec(vrmlText)) !== null) {
|
||||||
count++;
|
if (match[1]) {
|
||||||
const rawDefName = match[1].trim();
|
lastDef = match[2];
|
||||||
const originalName = nameMap.get(rawDefName) || rawDefName;
|
} else if (match[3]) {
|
||||||
const pointStr = match[2];
|
const newGroup = new THREE.Group();
|
||||||
const indexStr = match[3];
|
if (lastDef) {
|
||||||
|
newGroup.name = nameMap.get(lastDef) || lastDef;
|
||||||
const rawCoords = pointStr.trim().split(/[\s,]+/).filter(Boolean).map(Number);
|
lastDef = null;
|
||||||
if (rawCoords.length < 9) continue;
|
} else {
|
||||||
|
newGroup.name = 'Unnamed_Group';
|
||||||
const vertices: [number, number, number][] = [];
|
|
||||||
for (let i = 0; i < rawCoords.length; i += 3) {
|
|
||||||
if (!isNaN(rawCoords[i]) && !isNaN(rawCoords[i + 1]) && !isNaN(rawCoords[i + 2])) {
|
|
||||||
vertices.push([rawCoords[i], rawCoords[i + 1], rawCoords[i + 2]]);
|
|
||||||
}
|
}
|
||||||
}
|
currentGroup.add(newGroup);
|
||||||
|
stack.push({ name: newGroup.name, group: newGroup });
|
||||||
|
currentGroup = newGroup;
|
||||||
|
} else if (match[4]) {
|
||||||
|
if (stack.length > 1) {
|
||||||
|
stack.pop();
|
||||||
|
currentGroup = stack[stack.length - 1].group;
|
||||||
|
}
|
||||||
|
} else if (match[5]) {
|
||||||
|
const rawCoords = match[6].trim().split(/[\s,]+/).filter(Boolean).map(Number);
|
||||||
|
if (rawCoords.length >= 9) {
|
||||||
|
currentPoints = rawCoords;
|
||||||
|
}
|
||||||
|
} else if (match[7]) {
|
||||||
|
if (!currentPoints) continue;
|
||||||
|
|
||||||
if (vertices.length === 0) continue;
|
const indexStr = match[8];
|
||||||
|
const rawIndices = indexStr.trim().split(/[\s,]+/).filter(Boolean).map(Number);
|
||||||
|
|
||||||
const rawIndices = indexStr.trim().split(/[\s,]+/).filter(Boolean).map(Number);
|
const vertices: [number, number, number][] = [];
|
||||||
const triangleIndices: number[] = [];
|
for (let i = 0; i < currentPoints.length; i += 3) {
|
||||||
let currentPoly: number[] = [];
|
if (!isNaN(currentPoints[i]) && !isNaN(currentPoints[i + 1]) && !isNaN(currentPoints[i + 2])) {
|
||||||
|
vertices.push([currentPoints[i], currentPoints[i + 1], currentPoints[i + 2]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (const idx of rawIndices) {
|
const triangleIndices: number[] = [];
|
||||||
if (idx === -1) {
|
let currentPoly: number[] = [];
|
||||||
if (currentPoly.length >= 3) {
|
|
||||||
for (let p = 1; p < currentPoly.length - 1; p++) {
|
for (const idx of rawIndices) {
|
||||||
triangleIndices.push(currentPoly[0], currentPoly[p], currentPoly[p + 1]);
|
if (idx === -1) {
|
||||||
|
if (currentPoly.length >= 3) {
|
||||||
|
for (let p = 1; p < currentPoly.length - 1; p++) {
|
||||||
|
triangleIndices.push(currentPoly[0], currentPoly[p], currentPoly[p + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentPoly = [];
|
||||||
|
} else {
|
||||||
|
currentPoly.push(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentPoly.length >= 3) {
|
||||||
|
for (let p = 1; p < currentPoly.length - 1; p++) {
|
||||||
|
triangleIndices.push(currentPoly[0], currentPoly[p], currentPoly[p + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (triangleIndices.length === 0) continue;
|
||||||
|
|
||||||
|
const positions: number[] = [];
|
||||||
|
for (const tIdx of triangleIndices) {
|
||||||
|
const v = vertices[tIdx];
|
||||||
|
if (v) positions.push(v[0], v[1], v[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (positions.length > 0) {
|
||||||
|
const geometry = new THREE.BufferGeometry();
|
||||||
|
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
||||||
|
geometry.computeVertexNormals();
|
||||||
|
|
||||||
|
const mesh = new THREE.Mesh(geometry);
|
||||||
|
|
||||||
|
let meshName = `PECA-${++count}`;
|
||||||
|
for (let i = stack.length - 1; i >= 0; i--) {
|
||||||
|
if (stack[i].name && stack[i].name !== 'Unnamed_Group' && stack[i].name !== 'ROOT') {
|
||||||
|
meshName = stack[i].name;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentPoly = [];
|
mesh.name = meshName;
|
||||||
} else {
|
mesh.castShadow = true;
|
||||||
currentPoly.push(idx);
|
mesh.receiveShadow = true;
|
||||||
|
|
||||||
|
currentGroup.add(mesh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentPoly.length >= 3) {
|
|
||||||
for (let p = 1; p < currentPoly.length - 1; p++) {
|
|
||||||
triangleIndices.push(currentPoly[0], currentPoly[p], currentPoly[p + 1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (triangleIndices.length === 0) continue;
|
|
||||||
|
|
||||||
const positions: number[] = [];
|
|
||||||
for (const tIdx of triangleIndices) {
|
|
||||||
const v = vertices[tIdx];
|
|
||||||
if (v) positions.push(v[0], v[1], v[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (positions.length === 0) continue;
|
|
||||||
|
|
||||||
const geometry = new THREE.BufferGeometry();
|
|
||||||
geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
|
|
||||||
geometry.computeVertexNormals();
|
|
||||||
|
|
||||||
const mesh = new THREE.Mesh(geometry);
|
|
||||||
mesh.name = originalName;
|
|
||||||
mesh.castShadow = true;
|
|
||||||
mesh.receiveShadow = true;
|
|
||||||
group.add(mesh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count === 0) {
|
if (count === 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user