You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Autodesk Forge Reality Capture生成OBJ接入网页3D查看器的简易示例

极简OBJ 3D查看器实现方案

核心特性

  • 单HTML文件,纯前端实现,无需后端服务、无需Node.js环境
  • 自动读取URL参数中的模型地址,支持直接加载公网OBJ模型
  • 支持鼠标/触摸交互:旋转、缩放、平移查看
  • 全屏自适应,支持iframe嵌入

完整实现代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D模型查看器</title>
    <style>
        * { margin: 0; padding: 0; }
        html, body { width: 100%; height: 100%; overflow: hidden; }
        canvas { display: block; width: 100%; height: 100%; }
    </style>
    <!-- 引入Three.js相关依赖 -->
    <script src="https://cdn.jsdelivr.net/npm/three@0.158.0/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.158.0/examples/js/loaders/OBJLoader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.158.0/examples/js/loaders/MTLLoader.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.158.0/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
    <script>
        // 读取URL参数
        const params = new URLSearchParams(window.location.search);
        const modelUrl = params.get('url');
        if (!modelUrl) {
            document.body.innerHTML = '<p style="padding: 20px; font-size: 16px;">请指定模型URL参数,格式:?url=你的OBJ模型公网地址</p>';
        }

        // 初始化3D场景
        const scene = new THREE.Scene();
        scene.background = new THREE.Color(0xf0f0f0);

        // 初始化相机
        const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.position.set(0, 0, 10);

        // 初始化渲染器
        const renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setPixelRatio(window.devicePixelRatio);
        document.body.appendChild(renderer.domElement);

        // 添加光照
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
        scene.add(ambientLight);
        const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
        directionalLight.position.set(10, 10, 10);
        scene.add(directionalLight);

        // 初始化交互控制器
        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        controls.enableDamping = true;
        controls.dampingFactor = 0.05;

        // 加载模型
        const mtlLoader = new THREE.MTLLoader();
        const objLoader = new THREE.OBJLoader();
        // 尝试先加载同路径MTL材质
        const mtlUrl = modelUrl.replace(/\.obj$/i, '.mtl');
        mtlLoader.load(mtlUrl, (materials) => {
            materials.preload();
            objLoader.setMaterials(materials);
            loadObj();
        }, undefined, () => {
            // 没有MTL文件直接加载OBJ
            loadObj();
        });

        function loadObj() {
            objLoader.load(modelUrl, (obj) => {
                // 模型居中适配
                const box = new THREE.Box3().setFromObject(obj);
                const center = box.getCenter(new THREE.Vector3());
                const size = box.getSize(new THREE.Vector3());
                const maxDim = Math.max(size.x, size.y, size.z);
                const scale = 5 / maxDim;
                obj.scale.multiplyScalar(scale);
                obj.position.sub(center.multiplyScalar(scale));
                scene.add(obj);
                // 调整相机位置适配模型大小
                camera.position.z = maxDim * scale * 2;
                controls.target.copy(obj.position);
                controls.update();
            }, undefined, (err) => {
                document.body.innerHTML = '<p style="padding: 20px; font-size: 16px; color: red;">模型加载失败,请检查URL是否有效、是否配置跨域规则</p>';
                console.error(err);
            });
        }

        // 窗口自适应
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });

        // 渲染循环
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>
</html>

使用说明

  1. 部署:将上述代码保存为viewer.html,上传到任意静态服务器(可直接托管在OSS、Nginx静态目录等,无需后端接口支持)
  2. 直接访问:访问地址拼接参数即可,示例:
    https://你的域名/viewer.html?url=http://cloud1.tri-di.com/data/uploaded/xxx/result.obj
  3. iframe嵌入:直接用一行代码嵌入到任意页面中,示例:
<iframe src="https://你的域名/viewer.html?url=http://cloud1.tri-di.com/data/uploaded/xxx/result.obj" width="100%" height="900" frameborder="0" allowfullscreen></iframe>

常见问题解决

  • 加载失败提示跨域:在你存储模型文件的服务器配置CORS规则,允许查看器所在域名的GET请求即可,OSS类存储服务可直接在后台配置跨域规则。
  • 材质/纹理不显示:确保OBJ配套的MTL文件、纹理图片和OBJ在同一公网路径下,文件名和OBJ内引用的路径一致。
  • 需要加载ZIP压缩包:可引入JSZip库,前端直接读取GET参数传入的ZIP包地址,自动解压后读取内部的OBJ、MTL及纹理文件即可,无需修改现有模型导出流程。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 19:42:00