63 Three.js 將多個網格合併成一個網格
阿新 • • 發佈:2019-02-07
var renderer;
function initRender() {
renderer = new THREE.WebGLRenderer({antialias:true});
renderer.setSize(window.innerWidth, window.innerHeight);
//告訴渲染器需要陰影效果
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 預設的是,沒有設定的這個清晰 THREE.PCFShadowMap
document.body.appendChild(renderer.domElement);
}
var camera;
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
camera.position.set(0, 40, 100);
camera.lookAt(new THREE.Vector3(0,0,0));
}
var scene;
function initScene() {
scene = new THREE.Scene();
}
//初始化dat.GUI簡化試驗流程
var gui;
function initGui() {
//宣告一個儲存需求修改的相關資料的物件
gui = {
numberOfObjects:500, //當前場景中模型的個數
combined:false, //是否合併模型
redraw:function () {
//刪除場景內現有的立方體
var arr = [];
scene.traverse(function (e) {
if (e instanceof THREE.Mesh) arr.push(e);
});
arr.forEach(function (value) {
scene.remove(value);
});
//重新生成立方體
if(gui.combined){
//合併模型,則使用merge方法合併
var geometry = new THREE.Geometry();
//merge方法將兩個幾何體物件或者Object3D裡面的幾何體物件合併,(使用物件的變換)將幾何體的頂點,面,UV分別合併.
//THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.
for(var i=0; i<gui.numberOfObjects; i++){
var cube = addCube();
cube.updateMatrix();
geometry.merge(cube.geometry, cube.matrix);
}
scene.add(new THREE.Mesh(geometry, cubeMaterial));
}
else{
//不合並模型,則直接將模型放入
for(var i=0; i<gui.numberOfObjects; i++){
scene.add(addCube());
}
}
}
};
var datGui = new dat.GUI();
//將設定屬性新增到gui當中,gui.add(物件,屬性,最小值,最大值)
//新增旋轉功能
datGui.add(gui, "numberOfObjects", 0, 20000);
datGui.add(gui, "combined");
datGui.add(gui, "redraw");
gui.redraw();
}
//建立立方體的方法
var cubeMaterial = new THREE.MeshLambertMaterial({color: 0x00ff00, transparent: true, opacity: 0.8});
function addCube() {
var cubeSize = 1.0;
var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.position.x = -100+Math.round(Math.random()*200);
cube.position.y = -100+Math.round(Math.random()*200);
cube.position.z = -100+Math.round(Math.random()*200);
return cube;
}
var light;
function initLight() {
scene.add(new THREE.AmbientLight(0x444444));
light = new THREE.DirectionalLight(0xffffff);
light.position.set(15,50,10);
//告訴平行光需要開啟陰影投射
light.castShadow = true;
scene.add(light);
}
var sphere,cube;
function initModel() {
//輔助工具
var helper = new THREE.AxisHelper(50);
scene.add(helper);
return;
//模型組
group = new THREE.Object3D();
scene.add(group);
//球
var sphereGeometry = new THREE.SphereGeometry(5,200,200);
var sphereMaterial = new THREE.MeshLambertMaterial({color:0xaaaaaa});
sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = -5;
sphere.position.y = 5;
//告訴球需要投射陰影
sphere.castShadow = true;
group.add(sphere);
//立方體
var cubeGeometry = new THREE.CubeGeometry(10,10,8);
var cubeMaterial = new THREE.MeshLambertMaterial({color:0x00ffff});
cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.position.x = 15;
cube.position.y = 5;
cube.position.z = -5;
//告訴立方體需要投射陰影
cube.castShadow = true;
group.add(cube);
//底部平面
var planeGeometry = new THREE.PlaneGeometry(100,100);
var planeMaterial = new THREE.MeshStandardMaterial({color:0xaaaaaa});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = - 0.5 * Math.PI;
plane.position.y = -0;
//告訴底部平面需要接收陰影
plane.receiveShadow = true;
scene.add(plane);
}
//初始化效能外掛
var stats;
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
//使用者互動外掛 滑鼠左鍵按住旋轉,右鍵按住平移,滾輪縮放
var controls;
function initControls() {
controls = new THREE.OrbitControls( camera, renderer.domElement );
// 如果使用animate方法時,將此函式刪除
//controls.addEventListener( 'change', render );
// 使動畫迴圈使用時阻尼或自轉 意思是否有慣性
controls.enableDamping = true;
//動態阻尼係數 就是滑鼠拖拽旋轉靈敏度
//controls.dampingFactor = 0.25;
//是否可以縮放
controls.enableZoom = true;
//是否自動旋轉
controls.autoRotate = true;
controls.autoRotateSpeed = 0.5;
//設定相機距離原點的最近距離
controls.minDistance = 10;
//設定相機距離原點的最遠距離
controls.maxDistance = 500;
//是否開啟右鍵拖拽
controls.enablePan = true;
}
var step = 0.02; //模型旋轉的速度
function render() {
renderer.render( scene, camera );
}
//視窗變動觸發的函式
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
render();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
//更新控制器
render();
//更新效能外掛
stats.update();
controls.update();
requestAnimationFrame(animate);
}
function draw() {
initRender();
initScene();
initCamera();
initLight();
initModel();
initGui();
initControls();
initStats();
animate();
window.onresize = onWindowResize;
}