zoukankan      html  css  js  c++  java
  • 【three.js练习程序】创建简单物理场景

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>ceshi</title>
        <style>
            body {
                margin: 0;
                overflow: hidden;
            }
        </style>
        <script src="./build/three.js"></script>
        <script src="./examples/js/libs/ammo.js"></script>
        <script src="./examples/js/controls/OrbitControls.js"></script>
    </head>
    <body>
        <div id="ThreeJs">
        </div>
        <script>
            var camera, controls, scene, renderer;
            var clock = new THREE.Clock();
    
            // 物理引擎相关变量
            var gravityConstant = -9.8;
            var collisionConfiguration;
            var dispatcher;
            var broadphase;
            var solver;
            var physicsWorld;
            var rigidBodies = [];
            var margin = 0.05;
            var transformAux1 = new Ammo.btTransform();
            var time = 0;
    
            init();
            animate();
    
            function init() {
                initGraphics();
                initPhysics();
                createObjects();
            }
    
            function initGraphics() {
                // three.js基本场景配置
                camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 2000);
                camera.position.x = 30;
                camera.position.y = 30;
                camera.position.z = 30;
    
                controls = new THREE.OrbitControls(camera);
                controls.target.y = 2;
    
                renderer = new THREE.WebGLRenderer();
                renderer.setClearColor(new THREE.Color("#bfd1e5"));
                renderer.shadowMapEnabled = true;
                renderer.setSize(window.innerWidth, window.innerHeight);
                // 场景
                scene = new THREE.Scene();
                // 环境光
                var ambientLight = new THREE.AmbientLight(0x404040);
                scene.add(ambientLight);
                // 线性光
                var light = new THREE.DirectionalLight(0xffffff, 1);
                light.position.set(-20, 20, 10);
                light.castShadow = true;
                var d = 50;
                light.shadow.camera.left = -d;
                light.shadow.camera.right = d;
                light.shadow.camera.top = d;
                light.shadow.camera.bottom = -d;
    
                light.shadow.camera.near = 2;
                light.shadow.camera.far = 50;
    
                light.shadow.mapSize.x = 1024;
                light.shadow.mapSize.y = 1024;
                scene.add(light);
    
                var axes = new THREE.AxisHelper(50);               //创建三轴表示
                scene.add(axes);
                // 添加窗口大小变化监听
                window.addEventListener('resize', onWindowResize, false);
            }
    
            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            }
    
            function initPhysics() {
                // bullet基本场景配置
                collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
                dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
                broadphase = new Ammo.btDbvtBroadphase();
                solver = new Ammo.btSequentialImpulseConstraintSolver();
                physicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
                physicsWorld.setGravity(new Ammo.btVector3(0, gravityConstant, 0));
            }
    
            function createObjects() {
                var pos = new THREE.Vector3();
                var quat = new THREE.Quaternion();
                //创建地面
                pos.set(0, 0, 0);
                quat.set(0, 0, 0, 1);
                var ground = createParallellepiped(40, 1, 40, 0, pos, quat, new THREE.MeshPhongMaterial({ color: 0xffffff }));
                ground.castShadow = true;       // 开启投影
                ground.receiveShadow = true;    // 接受阴影(可以在表面上显示阴影)
    
                //创建50个小球
                for (var i = 0; i < 50; i++) {
                    var ballMass = 1.2;
                    var ballRadius = 0.5;
    
                    var ball = new THREE.Mesh(new THREE.SphereGeometry(ballRadius, 20, 20), createRendomColorObjectMeatrial());
                    ball.castShadow = true;
                    ball.receiveShadow = true;
                    var ballShape = new Ammo.btSphereShape(ballRadius);
                    ballShape.setMargin(margin);
                    pos.set(Math.random() + 10, 2 * (i + 1), Math.random() - 10);
                    quat.set(0, 0, 0, 1);
                    createRigidBody(ball, ballShape, ballMass, pos, quat);
                    ball.userData.physicsBody.setFriction(1.5);
                }
    
                //创建50个方块
                for (var i = 0; i < 50; i++) {
                    pos.set(Math.random() - 10, 2 * (i + 1), Math.random() + 10);
                    quat.set(0, 0, 0, 1);
                    createParallellepiped(1, 1, 1, 1, pos, quat, createRendomColorObjectMeatrial());
                }
            }
            
            function createRendomColorObjectMeatrial() {
                var color = Math.floor(Math.random() * (1 << 24));
                return new THREE.MeshPhongMaterial({ color: color });
            }
    
            function createParallellepiped(sx, sy, sz, mass, pos, quat, material) {
                var threeObject = new THREE.Mesh(new THREE.BoxGeometry(sx, sy, sz, 1, 1, 1), material);
                threeObject.castShadow = true;
                threeObject.receiveShadow = true;
                var shape = new Ammo.btBoxShape(new Ammo.btVector3(sx * 0.5, sy * 0.5, sz * 0.5));
                shape.setMargin(margin);
                createRigidBody(threeObject, shape, mass, pos, quat);
                return threeObject;
            }
    
            function createRigidBody(threeObject, physicsShape, mass, pos, quat) {
                threeObject.position.copy(pos);
                threeObject.quaternion.copy(quat);
                var transform = new Ammo.btTransform();
                transform.setIdentity();
                transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
                transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
                var motionState = new Ammo.btDefaultMotionState(transform);
                var localInertia = new Ammo.btVector3(0, 0, 0);
                physicsShape.calculateLocalInertia(mass, localInertia);
                var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, physicsShape, localInertia);
                var body = new Ammo.btRigidBody(rbInfo);
                threeObject.userData.physicsBody = body;
                scene.add(threeObject);
                if (mass > 0) {
                    rigidBodies.push(threeObject);
                    body.setActivationState(4);
                }
                physicsWorld.addRigidBody(body);
                return body;
            }
    
            function animate() {
                requestAnimationFrame(animate);
                var deltaTime = clock.getDelta();
                updatePhysics(deltaTime);
                controls.update(deltaTime);
                renderer.render(scene, camera);
                time += deltaTime;
            }
    
            function updatePhysics(deltaTime) {
                physicsWorld.stepSimulation(deltaTime);
                // 更新物体位置
                for (var i = 0, iL = rigidBodies.length; i < iL; i++) {
                    var objThree = rigidBodies[i];
                    var objPhys = objThree.userData.physicsBody;
                    var ms = objPhys.getMotionState();
                    if (ms) {
                        ms.getWorldTransform(transformAux1);
                        var p = transformAux1.getOrigin();
                        var q = transformAux1.getRotation();
                        objThree.position.set(p.x(), p.y(), p.z());
                        objThree.quaternion.set(q.x(), q.y(), q.z(), q.w());
                    }
                }
            }
    
            document.getElementById("ThreeJs").appendChild(renderer.domElement);
        </script>
    </html>

  • 相关阅读:
    对象形式传递
    解决DLNA方案的技术框架
    关于DLNA
    MAC配置Xcode的Cocos2d-x环境
    什么叫做双缓冲?
    Window7 Cocos2d-x配置开发环境
    Windows 8.1 Update 2更新了什么?
    微软发布Windows Phone 8.1 Update 和中文版Cortana“小娜”
    大开眼界 游览Facebook香港办公室
    小米的“假照片”危机
  • 原文地址:https://www.cnblogs.com/tiandsp/p/8453969.html
Copyright © 2011-2022 走看看