html 场景创建,【three.js练习程序】创建简单物理场景

该博客介绍了如何使用Three.js库与Bullet物理引擎进行集成,以创建一个3D模拟环境。作者详细阐述了初始化场景、设置光照、创建地面和多个小球与方块的过程,并通过物理引擎实现它们之间的交互。文章还展示了如何更新物体的位置以反映物理模拟的结果,为读者提供了一个完整的3D物理模拟的示例。
摘要由CSDN通过智能技术生成
ceshi

body {

margin: 0;

overflow: hidden;

}

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);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来回答您的问题。为了创建一个带有贴图的地球,您可以使用 three.js 库中的 SphereGeometry 和 MeshBasicMaterial 类。以下是创建地球的代码示例: ```javascript // 创建场景 var scene = new THREE.Scene(); // 创建相机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; // 创建渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建球体 var geometry = new THREE.SphereGeometry(1, 32, 32); // 创建材质 var material = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load('earth.jpg') }); // 创建网格 var earth = new THREE.Mesh(geometry, material); // 添加网格到场景中 scene.add(earth); // 渲染场景 function render() { requestAnimationFrame(render); earth.rotation.y += 0.01; renderer.render(scene, camera); } render(); ``` 在上面的代码中,我们使用 SphereGeometry 类创建了一个球体,设置了 32 个水平和垂直分段。然后我们使用 MeshBasicMaterial 类创建了一个材质,将地球贴图加载到材质中。最后,我们创建了一个网格,将球体和材质结合起来,并将网格添加到场景中。 在渲染函数中,我们使用 requestAnimationFrame 方法进行动画循环,并且每帧旋转地球一定的角度。最后,我们使用渲染器将场景渲染到屏幕上。 希望这个例子能够帮助您创建一个带有贴图的地球!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值