先貼上我前無古人後無來者的宇宙無敵攪拌機
我想用鍵盤控制框框中各部分分別有各自的動作,我這模型雖然是簡單幾何體堆積的,但是這是在blender裏製作了模型,導出obj格式的模型再導進頁面的,主要是測試功能,所以模型沒好好做,有點辣眼睛。在blender裏製作模型的時候我把需要單獨動作的部分不進行合併,這樣導進頁面後好控制。
我用OBJLoader和MTLLoader將模型導入頁面
<script src="build/three.js"></script>
<script src="build/OBJLoader.js"></script>
<script src="build/MTLLoader.js"></script>
用Object3D的移動旋轉方法控制局部動作。cord的位置是按照從大塊動作到小塊動作的方向找的,cord4的位置是相對於cord3位置的偏移量。加cubMesh是爲了標識coed的位置,cubeMesh位置不重新設置,只改變cord的位置,這樣將cubMesh調到旋轉中心點後(即cord的原點),無論cord中包含什麼,不管設置的是朝哪個方向轉動,轉動的中心都是此cubMesh。上圖中是調好cord位置後把cubeMesh註釋掉的結果。
var container;
var camera, scene, renderer,cord;
var robot=null,joint1=null,joint2=null;
var mouseX = 0, mouseY = 0;
var m0,m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12;
var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;
var cord0=new THREE.Object3D;
var cord1=new THREE.Object3D;
var cord2=new THREE.Object3D;
var cord3=new THREE.Object3D;
var cord4=new THREE.Object3D;
var cord5=new THREE.Object3D;
init();
function init() {
container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set(200, 100, 150);
scene = new THREE.Scene();
//輔助軸
// var axisHelper = new THREE.AxisHelper( 500);
// scene.add( axisHelper );
//輔助網格
// var size = 100;
// var step = 10;
//
// var gridHelper = new THREE.GridHelper( size, step );
// scene.add( gridHelper );
// var gridHelper1 = new THREE.GridHelper( size, step );
// gridHelper1.rotation.z=Math.PI*0.5;
// scene.add( gridHelper1 );
var ambient = new THREE.AmbientLight( 0x101030,5 );
scene.add( ambient );
var directionalLight = new THREE.DirectionalLight( 0xffeedd ,1);
directionalLight.position.set( 0, 10, 10 );
scene.add( directionalLight );
// texture
var manager = new THREE.LoadingManager();
manager.onProgress = function ( item, loaded, total ) {
};
var onProgress = function ( xhr ) {
if ( xhr.lengthComputable ) {
var percentComplete = xhr.loaded / xhr.total * 100;
}
};
var onError = function ( xhr ) {
};
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath('obj/');
mtlLoader.load('jiaobanji.mtl', function(materials) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials(materials);
objLoader.setPath('obj/');
objLoader.load('jiaobanji.obj', function(object) {
m0=object.children[5];
m1=object.children[4];
m2=object.children[3];
m3=object.children[2];
m4=object.children[1];
m5=object.children[0];
//找cord位置的輔助方塊
// var cubeMesh, cubeMesh1,cubeMesh2,cubeMesh3,cubeMesh4;
// cubeMesh = new THREE.Mesh(new THREE.BoxGeometry(5,5,5),new THREE.MeshLambertMaterial({color:0xff0000}));
// cubeMesh1 = new THREE.Mesh(new THREE.BoxGeometry(5,5,5),new THREE.MeshLambertMaterial({color:0x000000}));
// cubeMesh2 = new THREE.Mesh(new THREE.BoxGeometry(5,5,5),new THREE.MeshLambertMaterial({color:0x000080}));
// cord5.add(m5,cubeMesh);
cord5.add(m5);
cord5.position.set(0,-25,0);
m5.position.x-=(cord5.position.x);
m5.position.y-=(cord5.position.y);
m5.position.z-=(cord5.position.z);
// cord4.add(m4,cord5,cubeMesh1);
cord4.add(m4,cord5);
cord4.position.set(0,-5,0);
m5.position.x-=(cord4.position.x);
m5.position.y-=(cord4.position.y);
m5.position.z-=(cord4.position.z);
m4.position.x-=(cord4.position.x);
m4.position.y-=(cord4.position.y);
m4.position.z-=(cord4.position.z);
// cord3.add(m3,cord4,cubeMesh2);
cord3.add(m3,cord4);
cord3.position.set(0,0,-60);
m5.position.x-=(cord3.position.x);
m5.position.y-=(cord3.position.y);
m5.position.z-=(cord3.position.z);
m4.position.x-=(cord3.position.x);
m4.position.y-=(cord3.position.y);
m4.position.z-=(cord3.position.z);
m3.position.x-=(cord3.position.x);
m3.position.y-=(cord3.position.y);
m3.position.z-=(cord3.position.z);
cord2.add(m2,cord3);
cord2.position.set(0,96,0);
m5.position.x-=(cord2.position.x);
m5.position.y-=(cord2.position.y);
m5.position.z-=(cord2.position.z);
m4.position.x-=(cord2.position.x);
m4.position.y-=(cord2.position.y);
m4.position.z-=(cord2.position.z);
m3.position.x-=(cord2.position.x);
m3.position.y-=(cord2.position.y);
m3.position.z-=(cord2.position.z);
m2.position.x-=(cord2.position.x);
m2.position.y-=(cord2.position.y);
m2.position.z-=(cord2.position.z);
cord1.add(m1,cord2);
cord0.add(m0,cord1);
scene.add(cord0);
render();
return object;
}, onProgress, onError);
});
renderer = new THREE.WebGLRenderer();
renderer.setClearColor( 0xffffff );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize, false );
document.addEventListener( 'keydown', onKeyDown, false );
}
function onKeyDown(event){
if(event.keyCode==90){
cord1.rotation.y+=0.1;
}
if(event.keyCode==65){
cord1.rotation.y-=0.1;
}
if(event.keyCode==88){
if(cord2.rotation.x>3.14){}
else{
cord2.rotation.x+=0.1;
}
}
if(event.keyCode==83){
if(cord2.rotation.x<-0.4){}
else{
cord2.rotation.x-=0.1;
}
}
if(event.keyCode==67){
cord3.rotation.x+=0.1;
}
if(event.keyCode==68){
cord3.rotation.x+=0.1;
}
if(event.keyCode==86 ){
if(cord4.position.y>6){}
else{
cord4.position.y+=0.5;
}
}
if(event.keyCode==70 ){
if(cord4.position.y<-6){}
else{
cord4.position.y-=0.5;
}
}
if(event.keyCode==66){
cord5.rotation.y+=0.1;
}
if(event.keyCode==71){
cord5.rotation.y-=0.1;
}
render();
}
function onWindowResize() {
windowHalfX = window.innerWidth / 2;
windowHalfY = window.innerHeight / 2;
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function render() {
camera.lookAt(new THREE.Vector3( 0, 50, 0 ));
renderer.render( scene, camera );
}
看效果:http://ulyanov.esy.es/3D/jiaobanji.html
感謝WebGL學習交流羣(Three.js)狼行天下 的資料分享。
這個方法還是笨笨的,畢竟模型複雜沒有尺寸或者動作較多時不能挨個找軸位置啊,感覺可解燃眉之急但並不是長久之計。若有好的思路望衆大神不吝賜教~~~