ioname  

在引入obj文件前确保自己已经完成three.js的初始化(初始化scene,camera,renderer)

接着将所需要展示的obj文件放在项目中

根据官方文档中的描述

const loader = new OBJLoader();
loader.load(
     './obj/file.obj',
     function(object){
         scene.add(object);
     },
    //显示模型加载进度
     function(xhr){
         console.log((xhr.loaded / xhr.total*100)+'%loaded');
     },
     function(error){
         console.log('happend');
     }
 )

官方文档的前提是他已经正确引入了所有依赖,因此我们这里引入依赖

<script src="./node_modules/three/build/three.js"></script>
<script type="module">
    import {OBJLoader}  from "./node_modules/three/examples/jsm/loaders/OBJLoader.js"
    ....
</script>

引入依赖后运行可能会有报错,以下是我遇到的报错问题:

1、

Uncaught SyntaxError: ambiguous indirect export: default

//语法问题,es6的import导出要使用 {}进行包含
import {OBJLoader}  from "./node_modules/three/examples/jsm/loaders/OBJLoader.js"

2、

Uncaught SyntaxError: import declarations may only appear at top level of a module

静态的 import 语句用于导入由另一个模块导出的绑定。导入的模块时刻执行在严格模式下。在浏览器中/html文件中,import语句 只能在type=“module”的script标签中使用,因此要在script标签中添加type

<script type="module">
	....
</script>

动态import不依赖type=“module” 的script标签

3、

Uncaught TypeError: 解析模块说明符“three”时出错。相对模块说明符必须以“./”、 “../”或 “/”开头

正常引入时出现错误,发现是three.js用到的OBJLoader.js文件中的import问题,如下,我这里直接修改了官方的源码引用部分

import {
	EventDispatcher,
	MOUSE,
	Quaternion,
	Spherical,
	TOUCH,
	Vector2,
	Vector3
} from 'three';
//这里three有问题,更改成three.module.js的路径
from '/node_modules/three/build/three.module.js'

4、

已拦截跨源请求:同源策略禁止读取位于 file:///D:/%E9%A1%B9%E7%9B%AE/three/node_modules/three/examples/jsm/loaders/OBJLoader.js 的远程资源。

当在vscode中不经意右键使用 open in default brower 时,vscode将在浏览器中使用文件协议直接打开我们的html文件,可是cors不支持此协议,因此报错。

跨源请求只支持: http, data, chrome, chrome-extension, https.

在vscode中安装插件后使用右键 open with live server即可

5、

THREE.OrbitControls is not a constructor

three.js更新飞快,官方文档中的代码有时候跟不上,这里错误使用了THREE.OrbitControls,应该改为OrbitControls

const controls = new THREE.OrbitControls(camera,renderer.domElement);
//同理还有
const loader = new THREE.OBJLoader();

--去除THREE即可
 const controls = new OrbitControls(camera,renderer.domElement);
const loader = new OBJLoader();

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            margin: 0;
        }
    </style>
</head>
<body>
    <script src="./node_modules/three/build/three.js"></script>
   <script type="module">
import {OBJLoader}  from "./node_modules/three/examples/jsm/loaders/OBJLoader.js"
import  {OrbitControls}  from "./node_modules/three/examples/jsm/controls/OrbitControls.js";
import {MTLLoader} from "./node_modules/three/examples/jsm/loaders/MTLLoader.js"
 const scene = new THREE.Scene();
 const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

 const renderer = new THREE.WebGLRenderer();
 renderer.setSize( window.innerWidth, window.innerHeight );
 //domElement canvas对象
 document.body.appendChild( renderer.domElement );
 const loader = new OBJLoader();
 const mtlLoader = new MTLLoader();
  mtlLoader.load('./obj/test1.mtl',(mtl)=>{
    mtl.preload();
 loader.setMaterials(mtl);
   loader.load('./obj/textured_output.obj', (root) => {
      scene.add(root);
  });
 })
 camera.position.z = 5;//因此移动相机

 const point = new THREE.PointLight(0xffffff);
 point.position.set(400,400,400);
 scene.add(point)

 const ambient = new THREE.AmbientLight(0x444444);
 scene.add(ambient)
 renderer.setClearColor(0xb9d3ff,1);

 function animate(){
     requestAnimationFrame(animate);  //向浏览器发起一个执行某函数的请求, 什么时候会执行由浏览器决定,一般默认保持60FPS的频率
     renderer.render(scene,camera); //每次渲染出一幅图像
 }
 animate();

 const controls = new OrbitControls(camera,renderer.domElement);
// controls.addEventListener('change',render); //当使用requestAnimationFrame时,没必要在通过controls.addEventListener('change', render)监听鼠标事件调用渲染函数

   </script>
</body>
</html>

posted on 2022-09-01 21:29  ioname  阅读(3416)  评论(0编辑  收藏  举报