You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

寻求Web端MeshLab纹理保留Quadric Edge Collapse Decimation算法实现方案

Great question! Since you're already using MeshLab's Quadric Edge Collapse Decimation with texture preservation, sticking to tools that use the same underlying logic will give you the most consistent results for batch processing. Here's how to implement this in Python, Node.js, and PHP, plus tips for integrating with Omeka and optimizing for WebGL display:


Python: Pymeshlab (MeshLab's Python Binding)

This is your best bet for consistency with your existing workflow—it uses MeshLab's core algorithms directly, so you can replicate the exact filter settings you use manually.

Installation

pip install pymeshlab

Single Model Simplification Script

import pymeshlab as ml

def simplify_textured_mesh(input_path, output_path, target_faces):
    # Initialize MeshSet (MeshLab's core data structure)
    ms = ml.MeshSet()
    
    # Load your textured OBJ (automatically reads associated MTL and textures)
    ms.load_new_mesh(input_path)
    
    # Apply Quadric Edge Collapse Decimation with texture preservation
    # Parameters match MeshLab's UI options—tweak these to match your manual workflow
    ms.apply_filter(
        'quadric_edge_collapse_decimation',
        targetfacenum=target_faces,
        preservenormal=True,
        preservetexture=True,
        preservecolor=True,
        qualitythr=0.3  # Adjust based on your quality tolerance
    )
    
    # Save the simplified mesh (exports OBJ, MTL, and copies textures to output dir)
    ms.save_current_mesh(output_path)

# Example usage
simplify_textured_mesh("input/photogrammetry_model.obj", "output/simplified_model.obj", 10000)

Batch Processing

Wrap the function in a directory loop to process all models at once:

import os

input_dir = "/path/to/your/input/models"
output_dir = "/path/to/simplified/output"
target_faces = 10000

os.makedirs(output_dir, exist_ok=True)

for filename in os.listdir(input_dir):
    if filename.lower().endswith(".obj"):
        input_path = os.path.join(input_dir, filename)
        output_path = os.path.join(output_dir, filename)
        try:
            simplify_textured_mesh(input_path, output_path, target_faces)
            print(f"Successfully simplified: {filename}")
        except Exception as e:
            print(f"Failed to process {filename}: {str(e)}")

Node.js: Three-Mesh-Simplifier + Three.js

For a native Node.js solution, three-mesh-simplifier implements the quadric edge collapse algorithm and integrates seamlessly with Three.js—ideal if you're already using Three.js for WebGL display.

Installation

npm install three three-mesh-simplifier fs-extra three/examples/jsm/loaders/OBJLoader three/examples/jsm/loaders/MTLLoader

Simplification Script

const THREE = require('three');
const { SimplifyModifier } = require('three-mesh-simplifier');
const fs = require('fs-extra');
const { OBJLoader, MTLLoader } = require('three/examples/jsm/loaders/index.js');

async function simplifyTexturedMesh(inputObjPath, outputObjPath, targetFaces) {
    // Load MTL materials first
    const mtlLoader = new MTLLoader();
    const materials = await mtlLoader.loadAsync(inputObjPath.replace('.obj', '.mtl'));
    materials.preload();

    // Load OBJ with materials attached
    const objLoader = new OBJLoader();
    objLoader.setMaterials(materials);
    const scene = await objLoader.loadAsync(inputObjPath);

    // Simplify each mesh in the scene
    const simplifyModifier = new SimplifyModifier();
    scene.traverse((child) => {
        if (child.isMesh) {
            // Calculate simplification ratio to hit target face count
            const faceCount = child.geometry.attributes.position.count / 3;
            const ratio = targetFaces / faceCount;
            const simplifiedGeometry = simplifyModifier.modify(child.geometry, ratio);
            child.geometry = simplifiedGeometry;
        }
    });

    // Export simplified OBJ
    const exporter = new THREE.OBJExporter();
    const objContent = exporter.parse(scene);
    await fs.writeFile(outputObjPath, objContent);

    // Copy MTL and texture files to output directory
    const mtlPath = inputObjPath.replace('.obj', '.mtl');
    await fs.copy(mtlPath, outputObjPath.replace('.obj', '.mtl'));
    // Add logic here to copy texture files referenced in the MTL
}

// Example usage
simplifyTexturedMesh('./input/model.obj', './output/simplified.obj', 10000)
    .then(() => console.log('Simplification complete!'))
    .catch(err => console.error('Error:', err));

For batch processing, use fs.readdir to loop through your input directory, similar to the Python example.


PHP: MeshLab CLI via Exec

PHP lacks native libraries for quadric edge collapse, but you can use MeshLab's command-line tool (meshlabserver) to run the exact filter you use manually. This is reliable and matches your existing workflow.

Prerequisites

  1. Install MeshLab on your server (ensure meshlabserver is in your system PATH)
  2. Export a MeshLab filter script (.mlx) from the MeshLab UI: Filter > Show Current Filter Script > Save (configure the Quadric Edge Collapse Decimation settings first)

PHP Script

<?php
function simplifyTexturedMesh($inputObj, $outputObj, $mlxScript) {
    // Build meshlabserver command
    $command = sprintf(
        'meshlabserver -i "%s" -o "%s" -s "%s" -om vn vt fc',
        escapeshellarg($inputObj),
        escapeshellarg($outputObj),
        escapeshellarg($mlxScript)
    );

    // Execute command and capture output
    $output = [];
    $returnVar = 0;
    exec($command, $output, $returnVar);

    if ($returnVar !== 0) {
        throw new Exception("MeshLab failed: " . implode("\n", $output));
    }

    // Copy associated MTL and texture files
    $inputMtl = str_replace('.obj', '.mtl', $inputObj);
    $outputMtl = str_replace('.obj', '.mtl', $outputObj);
    copy($inputMtl, $outputMtl);
    // Add logic to copy texture files referenced in the MTL
}

// Batch processing example
$inputDir = '/path/to/input/models';
$outputDir = '/path/to/simplified/models';
$mlxScript = '/path/to/decimation_settings.mlx';

mkdir($outputDir, 0755, true);

$files = scandir($inputDir);
foreach ($files as $file) {
    if (pathinfo($file, PATHINFO_EXTENSION) === 'obj') {
        $inputObj = $inputDir . '/' . $file;
        $outputObj = $outputDir . '/' . $file;
        try {
            simplifyTexturedMesh($inputObj, $outputObj, $mlxScript);
            echo "Simplified: $file\n";
        } catch (Exception $e) {
            echo "Failed to process $file: " . $e->getMessage() . "\n";
        }
    }
}
?>

Integrating with Omeka

Omeka's REST API lets you programmatically upload simplified models and their assets. Here's a quick Python example using requests:

import requests
import os

def upload_to_omeka(item_title, file_paths, omeka_url, api_key):
    # Create a new Omeka item
    item_data = {
        'o:title': item_title,
        'o:resource_class': {'o:id': 123}  # Replace with your resource class ID
    }
    headers = {'X-Omeka-Api-Key': api_key}
    item_response = requests.post(
        f"{omeka_url}/api/items",
        json=item_data,
        headers=headers
    )
    item_id = item_response.json()['o:id']

    # Upload each file (OBJ, MTL, textures)
    for file_path in file_paths:
        with open(file_path, 'rb') as f:
            files = {'file': (os.path.basename(file_path), f)}
            requests.post(
                f"{omeka_url}/api/items/{item_id}/files",
                files=files,
                headers=headers
            )

# Example usage
upload_to_omeka(
    "Simplified Photogrammetry Model",
    ["output/simplified_model.obj", "output/simplified_model.mtl", "output/texture.jpg"],
    "https://your-omeka-instance.com",
    "your-omeka-api-key"
)

Similar logic works for Node.js (using axios) and PHP (using cURL).


WebGL Display Tips

  • Sketchfab: Use Sketchfab's API to upload simplified models directly from your server, or manually upload them via the web interface.
  • Three.js/Babylon.js: For better web performance, convert simplified OBJ/MTL models to glTF (using tools like obj2gltf in Node.js). glTF is optimized for web loading and supported natively by both libraries.

内容的提问来源于stack exchange,提问作者HB87

火山引擎 最新活动