fixed slider texture viewer

This commit is contained in:
Andrea Pozzetti
2026-02-12 21:43:40 +01:00
parent c3a9844089
commit 339afca01b
5 changed files with 166 additions and 21 deletions
+15
View File
@@ -384,6 +384,7 @@ export class BaseViewer {
format: result.format,
actors: result.actors.length,
hasTexture: result.hasTexture || false,
hasVertexColors: result.hasVertexColors || false,
fields: result.fields || []
});
@@ -408,6 +409,20 @@ export class BaseViewer {
if (this.config.enableTextures && this.textureManager && result.hasTexture) {
this.textureManager.applyTextureFixesMultiple(this.actors);
this.textureManager.configureRenderer(this.renderer);
} else if (result.hasVertexColors) {
// Mesh has vertex colors - don't override with default color
// Just configure edges if needed, colors are already set up by loader
this.actors.forEach(actor => {
const property = actor.getProperty();
if (property) {
if (this.config.showEdges) {
property.setEdgeVisibility(true);
if (this.config.edgeColor) {
property.setEdgeColor(...this.config.edgeColor);
}
}
}
});
} else {
// Apply standard actor configuration
this.actorManager.configureActors(this.actors, {
+21 -3
View File
@@ -75,9 +75,10 @@ export async function loadGLTF(filepath, vtk, renderer, options = {}) {
const actorsMap = importer.getActors();
const actors = Array.from(actorsMap.values());
// Track texture information
// Track texture and vertex color information
let hasTexture = false;
let hasMaterial = false;
let hasVertexColors = false;
// Process actors and apply texture fixes
if (applyTextureFixes) {
@@ -87,6 +88,12 @@ export async function loadGLTF(filepath, vtk, renderer, options = {}) {
const input = mapper?.getInputData();
if (input && input.getNumberOfPoints() > 0) {
// Check for vertex colors (stored as scalars in VTK)
const scalars = input.getPointData()?.getScalars();
if (scalars && scalars.getNumberOfComponents() >= 3) {
hasVertexColors = true;
}
if (property) {
// CRITICAL FIX: Remove metallicRoughnessTexture if present
// VTK.js GLTFImporter may use this instead of baseColorTexture
@@ -131,9 +138,17 @@ export async function loadGLTF(filepath, vtk, renderer, options = {}) {
}
}
// Configure mapper for texture rendering
// Configure mapper for rendering
if (mapper) {
mapper.setScalarVisibility(false);
if (hasVertexColors && !hasTexture) {
// Enable scalar visibility to show vertex colors
mapper.setScalarVisibility(true);
mapper.setScalarModeToUsePointData();
mapper.setColorModeToDirectScalars();
} else {
// Disable scalars for texture rendering
mapper.setScalarVisibility(false);
}
mapper.modified();
}
}
@@ -171,6 +186,8 @@ export async function loadGLTF(filepath, vtk, renderer, options = {}) {
actors,
importer,
bounds,
hasTexture,
hasVertexColors,
metadata: {
format: 'GLTF',
numActors: actors.length,
@@ -178,6 +195,7 @@ export async function loadGLTF(filepath, vtk, renderer, options = {}) {
numPolys: totalPolys,
bounds,
hasTexture,
hasVertexColors,
hasMaterial
}
};
+12 -2
View File
@@ -306,8 +306,17 @@ export class DualViewer {
// Apply texture fixes for GLTF/GLB
vp.textureManager.applyTextureFixesMultiple(result.actors);
vp.textureManager.configureRenderer(vp.renderer);
} else if (result.hasVertexColors) {
// Mesh has vertex colors - don't override with default color
// Just configure edges if needed, colors are already set up by loader
result.actors.forEach(actor => {
const property = actor.getProperty();
if (property && this.config.showEdges) {
property.setEdgeVisibility(true);
}
});
} else {
// Standard actor configuration
// Standard actor configuration - apply default color
this.actorManager.configureActors(result.actors, {
color: defaultColor,
showEdges: this.config.showEdges
@@ -325,7 +334,8 @@ export class DualViewer {
viewport,
filename: vp.filename,
format: result.format,
hasTexture: result.hasTexture || false
hasTexture: result.hasTexture || false,
hasVertexColors: result.hasVertexColors || false
});
return result;
+102 -14
View File
@@ -238,6 +238,10 @@
let mesh1Polydata = null;
let mesh2Polydata = null;
// GLTF actors (stored separately since they replace the pre-made actors)
let mesh1GltfActors = null;
let mesh2GltfActors = null;
// Camera sync state
let isSyncing = false;
let isAnimating1 = false;
@@ -429,21 +433,88 @@
const arrayBuffer = await response.arrayBuffer();
if (isGLB) {
reader.parseAsArrayBuffer(arrayBuffer);
await reader.update();
const source = reader.getOutputData();
targetMapper.setInputData(source);
targetMapper.update();
// GLTFImporter requires using its own actors - we can't extract polydata
// So we need to replace the pre-made actors with the GLTF actors
const targetRenderer = isMesh1 ? renderer1 : renderer2;
const targetActor = isMesh1 ? mesh1Actor : mesh2Actor;
const polydata = targetMapper.getInputData();
const bounds = polydata.getBounds();
// Clean up any previous GLTF actors
const prevGltfActors = isMesh1 ? mesh1GltfActors : mesh2GltfActors;
if (prevGltfActors) {
prevGltfActors.forEach(actor => targetRenderer.removeActor(actor));
}
const importer = vtkGLTFImporter.newInstance();
importer.setRenderer(targetRenderer);
importer.setUrl(filepath);
// Wait for GLTF parsing using onReady callback
await new Promise((resolve, reject) => {
importer.onReady(() => resolve());
importer.loadData().catch(reject);
});
// Import actors - this adds them to the renderer
importer.importActors();
const actorsMap = importer.getActors();
const actors = Array.from(actorsMap.values());
console.log(`[GeomPack VTK Slider Viewer] GLTF actors found: ${actors.length}`);
if (actors.length === 0) {
throw new Error('No actors found in GLTF');
}
// Remove the pre-made actor (it has no data)
targetRenderer.removeActor(targetActor);
// Calculate bounds from all GLTF actors and apply vertex color settings
let bounds = null;
actors.forEach((actor, idx) => {
const mapper = actor.getMapper();
const property = actor.getProperty();
const input = mapper?.getInputData();
if (input) {
const actorBounds = actor.getBounds();
if (!bounds) {
bounds = [...actorBounds];
} else {
bounds[0] = Math.min(bounds[0], actorBounds[0]);
bounds[1] = Math.max(bounds[1], actorBounds[1]);
bounds[2] = Math.min(bounds[2], actorBounds[2]);
bounds[3] = Math.max(bounds[3], actorBounds[3]);
bounds[4] = Math.min(bounds[4], actorBounds[4]);
bounds[5] = Math.max(bounds[5], actorBounds[5]);
}
// Check for vertex colors
const scalars = input.getPointData()?.getScalars();
if (scalars && scalars.getNumberOfComponents() >= 3) {
mapper.setScalarVisibility(true);
mapper.setScalarModeToUsePointData();
mapper.setColorModeToDirectScalars();
console.log(`[GeomPack VTK Slider Viewer] Mesh ${isMesh1 ? '1' : '2'} actor ${idx} has vertex colors`);
}
// Apply material fixes for better rendering
if (property) {
if (typeof property.setMetallic === 'function') property.setMetallic(0.0);
if (typeof property.setRoughness === 'function') property.setRoughness(1.0);
}
}
});
console.log(`[GeomPack VTK Slider Viewer] Mesh ${isMesh1 ? '1' : '2'} bounds:`, bounds);
if (isMesh1) {
mesh1Bounds = bounds;
mesh1Polydata = polydata;
mesh1Polydata = null; // GLTF doesn't provide simple polydata access
mesh1GltfActors = actors; // Store for later reference
} else {
mesh2Bounds = bounds;
mesh2Polydata = polydata;
mesh2Polydata = null;
mesh2GltfActors = actors;
}
} else {
if (isSTL) {
@@ -712,12 +783,20 @@
positionCamera(combinedBounds);
// Apply opacity values
// Apply opacity values (handle both regular actors and GLTF actors)
if (data.opacity1 !== undefined) {
mesh1Actor.getProperty().setOpacity(data.opacity1);
if (mesh1GltfActors) {
mesh1GltfActors.forEach(actor => actor.getProperty().setOpacity(data.opacity1));
} else {
mesh1Actor.getProperty().setOpacity(data.opacity1);
}
}
if (data.opacity2 !== undefined) {
mesh2Actor.getProperty().setOpacity(data.opacity2);
if (mesh2GltfActors) {
mesh2GltfActors.forEach(actor => actor.getProperty().setOpacity(data.opacity2));
} else {
mesh2Actor.getProperty().setOpacity(data.opacity2);
}
}
renderWindow1.render();
@@ -737,8 +816,17 @@
// Control event handlers
document.getElementById('showEdges').addEventListener('change', (e) => {
const edgeViz = e.target.checked;
mesh1Actor.getProperty().setEdgeVisibility(edgeViz);
mesh2Actor.getProperty().setEdgeVisibility(edgeViz);
// Handle both regular actors and GLTF actors
if (mesh1GltfActors) {
mesh1GltfActors.forEach(actor => actor.getProperty().setEdgeVisibility(edgeViz));
} else {
mesh1Actor.getProperty().setEdgeVisibility(edgeViz);
}
if (mesh2GltfActors) {
mesh2GltfActors.forEach(actor => actor.getProperty().setEdgeVisibility(edgeViz));
} else {
mesh2Actor.getProperty().setEdgeVisibility(edgeViz);
}
renderWindow1.render();
renderWindow2.render();
});
+16 -2
View File
@@ -606,6 +606,11 @@
];
}
// Check for vertex colors early
const scalars = input.getPointData()?.getScalars();
const hasVertexColors = scalars && scalars.getNumberOfComponents() >= 3;
let hasTexture = false;
// Apply texture fixes
if (property) {
// CRITICAL FIX: Remove metallicRoughnessTexture if present
@@ -630,6 +635,7 @@
if (texture) {
actor.addTexture(texture);
hasTexture = true;
}
// Set material to non-metallic for proper texture display
@@ -638,9 +644,17 @@
property.setInterpolation(2);
}
// Configure mapper for texture rendering
// Configure mapper for rendering
if (mapper) {
mapper.setScalarVisibility(false);
if (hasVertexColors && !hasTexture) {
// Enable vertex colors
mapper.setScalarVisibility(true);
mapper.setScalarModeToUsePointData();
mapper.setColorModeToDirectScalars();
} else {
// Disable scalars for texture rendering
mapper.setScalarVisibility(false);
}
mapper.modified();
}
}