您的位置:首页 > Web前端 > JavaScript

three.js学习笔记 为模型增添物理效果

2016-06-29 12:53 726 查看
前一篇介绍了物理引擎Physijs,场景中的对象只需要用特定的Physijs对象封装一下便可以在场景中展现物理效果(重力、碰撞检测等)。但Physijs并没有为模型的加载提供一种特定的方法。所以由3Dmax或是Blender等建模软件创建的模型通过传统方式加载到场景中并没有物理效果。

为了使模型具有物理效果这里我使用了一种方法(才疏学浅,仅供参考)。

这里使用的是r71的加载方式,最新的有所不同。

正常加载:

var loader = new THREE.OBJMTLLoader();
loader.load('obj/three.obj', 'obj/three.mtl', function(object) {
model =object;
scene.add(model);
}, onProgress, onError);
物理场景加载:

var loader = new THREE.OBJMTLLoader();
loader.load('obj/three.obj', 'obj/three.mtl', function(object) {
model = object;

for (var i = 0; i < model.children.length; i++) {
model.children[i].castShadow = true;
var ground_material = Physijs.createMaterial(
model.children[i].material,
1,
0
);
var mesh = new Physijs.ConcaveMesh(
model.children[i].geometry,
ground_material,
0
);
scene.add(mesh);
}

scene.add(model);

}, onProgress, onError);
在加载的过程中使用模型的几何形状和材质创建一个Physijs对象。将新建的Physijs对象和模型重叠的放置。便可产生阴影、碰撞及重力等多种效果。这里使用的是Physijs.ConcaveMesh,可以对比较复杂的图形进行比较细致的表现。

以3Dmax导出的字体模型为例。

源代码:

<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8">
<title>three.js</title>
</head>

<body>
<script type="text/javascript" src="js/three.js"></script>
<script type="text/javascript" src="js/Physijs/physi.js"></script>
<script src="js/Detector.js"></script>
<script type="text/javascript" src="js/dat.gui.min.js"></script>
<script type="text/javascript" src="js/stats.min.js"></script>
<script type="text/javascript" src="js/OBJLoader.js"></script>
<script type="text/javascript" src="js/MTLLoader.js"></script>
<script type="text/javascript" src="js/OBJMTLLoader.js"></script>

<script>
'use strict';
Physijs.scripts.worker = 'js/Physijs/physijs_worker.js';
Physijs.scripts.ammo = 'ammo.js';

if (!Detector.webgl) Detector.addGetWebGLMessage();
var renderer, scene, camera, light;
var geometry, material, mesh, model;
var stats = initStats();

function init() {
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0x000000);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.lookAt(new THREE.Vector3(-10, 0, -10));
camera.position.set(150, 30, 150);

light = new THREE.SpotLight(0xffffff);
light.castShadow = true;
light.position.set(-100, 100, 100);

scene.add(light);

var onProgress = function(xhr) {
if (xhr.lengthComputable) {
var percentComplete = xhr.loaded / xhr.total * 100;
console.log(Math.round(percentComplete, 2) + '% downloaded');
}
};
var onError = function(xhr) {};
var loader = new THREE.OBJMTLLoader();
loader.load('obj/three.obj', 'obj/three.mtl', function(object) {
model = object;
model.rotation.x = Math.PI / 180 * 90;

for (var i = 0; i < model.children.length; i++) {
model.children[i].castShadow = true;
var ground_material = Physijs.createMaterial(
model.children[i].material,
1,
0
);
var mesh = new Physijs.ConcaveMesh(
model.children[i].geometry,
ground_material,
0
);
mesh.rotation.x = Math.PI / 180 * 90;
scene.add(mesh);
}

scene.add(model);

}, onProgress, onError);

creatGround();
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
render();
}

function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}

function creatGround() {
geometry = new THREE.CubeGeometry(1000, 1, 1000);
material = new THREE.MeshBasicMaterial({
color: 0xffffff
});
mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0, -10, 0);
mesh.receiveShadow = true;
scene.add(mesh);
}

function initStats() {

var stats = new Stats();

stats.setMode(0); // 0: fps, 1: ms

stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);
return stats;
}

var control = new function() {
this.cx = 150;
this.cy = 30;
this.cz = 150;
this.redraw = function() {
camera.position.set(control.cx, control.cy, control.cz);
}
}

var gui = new dat.GUI();
gui.add(control, 'cx', -300, 300).onChange(control.redraw);
gui.add(control, 'cy', -300, 300).onChange(control.redraw);
gui.add(control, 'cz', -300, 300).onChange(control.redraw);

var clock = new THREE.Clock();

function render() {
var delta = clock.getDelta();
stats.update();
requestAnimationFrame(render);
renderer.render(scene, camera);
}
init();
</script>
<style>
body {
padding: 0;
margin: 0;
overflow: hidden;
}
</style>
</body>

</html>
效果图:


fork me on github blog: https://chenjy1225.github.io/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JavaScript three.js webgl