[software] 添加16DOF早期训练仿真与Sim2Real闭环
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Adapted MeshLoader for sim2real web console.
|
||||
* Supports both fileMap-based loading (original robot_viewer API) and URL-based
|
||||
* fetching from the sim2real HTTP server at /meshes/<name>.STL.
|
||||
*
|
||||
* Uses importmap-resolved Three.js via CDN (no bundler).
|
||||
*/
|
||||
import * as THREE from 'three';
|
||||
import { STLLoader } from 'three/examples/jsm/loaders/STLLoader.js';
|
||||
|
||||
const _stlLoader = new STLLoader();
|
||||
|
||||
let loadersCache = null;
|
||||
async function getLoaders() {
|
||||
if (!loadersCache) {
|
||||
loadersCache = { STLLoader: _stlLoader };
|
||||
}
|
||||
return loadersCache;
|
||||
}
|
||||
|
||||
function normalizePath(path) {
|
||||
if (!path) return '';
|
||||
return path.replace(/\\/g, '/').replace(/^\/+/, '').replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load mesh from URL (sim2real server) or fileMap (robot_viewer compatibility).
|
||||
* @param {string} meshPath - e.g. "fl_hip_abduction_Link.STL"
|
||||
* @param {Map|null} fileMap - optional File map (compat with MJCFAdapter)
|
||||
* @param {string|null} meshBaseUrl - e.g. "/meshes/" for URL-based loading
|
||||
* @returns {Promise<THREE.BufferGeometry|THREE.Group|null>}
|
||||
*/
|
||||
export async function loadMeshFile(meshPath, fileMap = null, meshBaseUrl = null) {
|
||||
const fileName = normalizePath(meshPath).split('/').pop();
|
||||
|
||||
// Strategy 1: try fileMap (robot_viewer compatibility)
|
||||
if (fileMap) {
|
||||
for (const [key, file] of fileMap.entries()) {
|
||||
if (typeof key === 'string' && key.toLowerCase().endsWith(fileName.toLowerCase())) {
|
||||
try {
|
||||
const url = URL.createObjectURL(file);
|
||||
const geom = await new Promise((resolve, reject) => {
|
||||
_stlLoader.load(url, resolve, undefined, reject);
|
||||
});
|
||||
URL.revokeObjectURL(url);
|
||||
console.log('[MeshLoader] loaded from fileMap:', fileName);
|
||||
return geom;
|
||||
} catch (e) {
|
||||
URL.revokeObjectURL(url);
|
||||
console.warn('[MeshLoader] fileMap load failed:', fileName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Strategy 2: try URL-based loading from sim2real server
|
||||
const baseUrl = meshBaseUrl || '/meshes/';
|
||||
const url = baseUrl + fileName;
|
||||
try {
|
||||
console.log('[MeshLoader] fetching:', url);
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) {
|
||||
console.warn('[MeshLoader] 404:', url);
|
||||
return null;
|
||||
}
|
||||
const arrayBuf = await resp.arrayBuffer();
|
||||
const blobUrl = URL.createObjectURL(new Blob([arrayBuf]));
|
||||
const geom = await new Promise((resolve, reject) => {
|
||||
_stlLoader.load(blobUrl, resolve, undefined, reject);
|
||||
});
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
console.log('[MeshLoader] loaded from URL:', fileName);
|
||||
return geom;
|
||||
} catch (e) {
|
||||
console.warn('[MeshLoader] URL load failed:', url, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function ensureMeshHasPhongMaterial(meshObject) {
|
||||
meshObject.traverse((child) => {
|
||||
if (child.isMesh && child.material) {
|
||||
const materials = Array.isArray(child.material) ? child.material : [child.material];
|
||||
materials.forEach((mat, i) => {
|
||||
if (!mat) return;
|
||||
if (mat.type === 'MeshBasicMaterial' || mat.type === 'MeshLambertMaterial') {
|
||||
const nm = new THREE.MeshPhongMaterial({
|
||||
color: mat.color, map: mat.map,
|
||||
transparent: mat.transparent, opacity: mat.opacity, side: mat.side,
|
||||
shininess: 50, specular: new THREE.Color(0.3, 0.3, 0.3),
|
||||
});
|
||||
if (nm.map) nm.map.colorSpace = THREE.SRGBColorSpace;
|
||||
materials[i] = nm;
|
||||
} else if (mat.isMeshPhongMaterial || mat.isMeshStandardMaterial) {
|
||||
if (mat.shininess === undefined || mat.shininess < 50) mat.shininess = 50;
|
||||
if (!mat.specular) mat.specular = new THREE.Color(0.3, 0.3, 0.3);
|
||||
mat.needsUpdate = true;
|
||||
}
|
||||
});
|
||||
if (Array.isArray(child.material)) child.material = materials;
|
||||
else if (materials.length === 1) child.material = materials[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { getLoaders };
|
||||
Reference in New Issue
Block a user