我是Three.js的新手。我试图使用示例中的STLLoader
加载STL模型。我要加载的model是艾菲尔铁塔模型。我下载了STL文件,该文件为ASCII格式,大小约为33 MB。我有以下设置来显示模型:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 5% auto; }
canvas { width: 80%; height: 80% }
#progress {
margin-bottom: 2%;
min-width: 50%;
}
</style>
<script src="js/three.js"></script>
<script src="js/STLLoader.js"></script>
</head>
<body>
<div id="progress"></div>
<script>
// window properties
const windowWidth = window.innerWidth;
const windowHeight = window.innerHeight;
// camera properties
const FOV = 35;
const ASPECT_RATIO = windowWidth / windowHeight;
const NEAR = 0.1;
const FAR = 1000;
// scene settings
const SCENE_BKG = new THREE.Color("rgb(220,220,220)");
const scene = new THREE.Scene();
scene.background = SCENE_BKG;
const camera = new THREE.PerspectiveCamera( FOV, ASPECT_RATIO, NEAR, FAR );
const STLLoader = new THREE.STLLoader();
STLLoader.load('./sample_stl/Eiffel_tower_sample.STL', function(geometry) {
console.dir(geometry);
const materials = [];
const nGeometryGroups = geometry.groups.length;
let colorMap = []; // Some logic to index colors.
let material;
// create a random colorMap
let startColor = 0x010101;
let clr = startColor;
let count = 0;
while (count++ < nGeometryGroups) {
colorMap.push(clr);
clr = ( parseInt(clr, 16) + startColor ).toString();
}
console.log(colorMap);
for (let i = 0; i < nGeometryGroups; i++) {
material = new THREE.MeshPhongMaterial({
color: colorMap[i],
wireframe: false
});
}
materials.push(material);
const mesh = new THREE.Mesh(geometry, materials);
console.dir(mesh);
scene.add(mesh);
// should i call animate here?
}, function (xhr) {
// show progress here
progressBar.innerHTML = `<span style="color: green;">${(xhr.loaded/xhr.total) * 100}%</span> have been loaded`;
}, function(err) {
console.error('[!] Fatal Error: Could not load model');
console.error(err);
});
const renderer = new THREE.WebGLRenderer();
renderer.setSize( windowWidth, windowHeight );
const progressBar = document.querySelector('#progress');
document.body.appendChild( renderer.domElement );
const animate = () => {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
camera.position.set(0, 0, 10);
animate();
</script>
</body>
</html>
我不确定两件事。首先,colorMap
数组是什么?我查看了MeshPhongMaterial
类文档,发现它是十六进制颜色值。我直接从STLLoader示例文件夹here复制了此代码。我发现了一种快速的技巧,可以生成一些十六进制的颜色并填充colorMap数组(一个空数组会引发错误)。其次,我应该在哪里调用animate()
函数?我尝试在modelLoaded
处理程序内部以及外部调用它,唯一的区别是在处理程序内部调用了Violation: handler took 500ms
。我检查了Firefox和Chromium上的“网络”选项卡,以查看STL文件是否已正确加载。我还在控制台中打印了Mesh
对象,如下所示:
Mesh
castShadow: false
children: []
drawMode: 0
frustumCulled: true
geometry: BufferGeometry
attributes: {position: Float32BufferAttribute, normal: Float32BufferAttribute}
boundingBox: null
boundingSphere: Sphere {center: Vector3, radius: 71.76963889659893}
drawRange: {start: 0, count: Infinity}
groups: [{…}]
index: null
morphAttributes: {}
morphTargetsRelative: false
name: ""
type: "BufferGeometry"
userData: {}
uuid: "28A4B269-2828-477D-9C6D-5C9A30E95A7F"
_listeners: {dispose: Array(1)}
drawcalls: (...)
id: 7
offsets: (...)
__proto__: EventDispatcher
layers: Layers
mask: 1
__proto__: Object
material: Array(1)
0: MeshPhongMaterial {uuid: "1E33986A-A979-49C0-ADF5-823CACC6F3AA", name: "", type: "MeshPhongMaterial", fog: true, blending: 1, …}
length: 1
__proto__: Array(0)
matrix: Matrix4
elements: Array(16)
0: 1
1: 0
2: 0
3: 0
4: 0
5: 1
6: 0
7: 0
8: 0
9: 0
10: 1
11: 0
12: 0
13: 0
14: 0
15: 1
length: 16
__proto__: Array(0)
__proto__: Object
matrixAutoUpdate: true
matrixWorld: Matrix4
elements: Array(16)
0: 1
1: 0
2: 0
3: 0
4: 0
5: 1
6: 0
7: 0
8: 0
9: 0
10: 1
11: 0
12: 0
13: 0
14: 0
15: 1
length: 16
__proto__: Array(0)
__proto__: Object
matrixWorldNeedsUpdate: false
name: ""
parent: Scene
autoUpdate: true
background: Color {r: 0.8627450980392157, g: 0.8627450980392157, b: 0.8627450980392157}
castShadow: false
children: [Mesh]
fog: null
frustumCulled: true
layers: Layers {mask: 1}
matrix: Matrix4 {elements: Array(16)}
matrixAutoUpdate: true
matrixWorld: Matrix4 {elements: Array(16)}
matrixWorldNeedsUpdate: false
name: ""
overrideMaterial: null
parent: null
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, _onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", _onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "Scene"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {}
uuid: "3F9C4993-4CB4-4541-9C64-34FCBB12B1E3"
visible: true
_listeners: {dispose: Array(2)}
eulerOrder: (...)
id: 4
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: Object3D
position: Vector3 {x: 0, y: 0, z: 0}
quaternion: Quaternion {_x: 0, _y: 0, _z: 0, _w: 1, _onChangeCallback: ƒ}
receiveShadow: false
renderOrder: 0
rotation: Euler {_x: 0, _y: 0, _z: 0, _order: "XYZ", _onChangeCallback: ƒ}
scale: Vector3 {x: 1, y: 1, z: 1}
type: "Mesh"
up: Vector3 {x: 0, y: 1, z: 0}
userData: {}
uuid: "72BA29AF-F939-45F8-869A-D074E6696D7F"
visible: true
eulerOrder: (...)
id: 10
modelViewMatrix: Matrix4 {elements: Array(16)}
normalMatrix: Matrix3 {elements: Array(9)}
useQuaternion: (...)
__proto__: Object3D
这是打印的网格对象。我不确定有什么问题,如果有人可以向我解释如何使用colorMap
属性,并在animate
函数调用范围内给我一个明确的答案,我将很高兴。
编辑 添加了小提琴here。
答案 0 :(得分:1)
首先,什么是colorMap数组?
示例中的代码假定模型的几何图形具有多个groups。如果是这样,则可以将多个材质分配给单个3D对象。但是,这不是强制性的。如果您只想使用一种颜色,请执行以下操作:
const material = new THREE.MeshPhongMaterial( { color: 0x0000ff } );
const mesh = new THREE.Mesh( geometry, material );
第二,我应该在哪里调用animate()函数?
three.js
示例通常具有一个init()
和一个animate()
函数。这意味着您要在初始化场景(创建相机,渲染器,灯光等)之后立即开始动画制作。您也可以在应用程序中执行此操作,但是STL文件将在其加载和解析进度完成后立即弹出。另外,您也可以在onLoad()
回调中开始动画制作。这实际上取决于您的用例(因此没有对与错)。
three.js R111