mirror of
https://github.com/tengge1/ShadowEditor.git
synced 2026-01-18 15:02:09 +00:00
添加物理地形。
This commit is contained in:
parent
46332d7571
commit
774ae2fdcb
@ -91,7 +91,16 @@ TerrainMenu.prototype.createShaderTerrain = function () {
|
||||
// ----------------------------- 创建物理地形 ---------------------------------
|
||||
|
||||
TerrainMenu.prototype.createPhysicsTerrain = function () {
|
||||
this.app.editor.execute(new AddObjectCommand(new PhysicsTerrain()));
|
||||
var terrain = new PhysicsTerrain();
|
||||
|
||||
this.app.editor.execute(new AddObjectCommand(terrain));
|
||||
|
||||
this.app.physics.world.addRigidBody(terrain.userData.physicsBody);
|
||||
this.app.physics.rigidBodies.push(terrain);
|
||||
|
||||
// this.app.on(`animate.${this.id}`, (clock, deltaTime) => {
|
||||
// terrain.update(deltaTime, this.app.physics.world);
|
||||
// });
|
||||
};
|
||||
|
||||
// ---------------------------- 升高地形 -----------------------------------
|
||||
|
||||
@ -20,7 +20,7 @@ function PhysicsTerrain() {
|
||||
|
||||
var heightData = this.generateHeight(terrainWidth, terrainDepth, terrainMinHeight, terrainMaxHeight);
|
||||
|
||||
for (var i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
|
||||
for (var i = 0, j = 0, l = vertices.length; i < l; i++ , j += 3) {
|
||||
// j + 1 because it is the y component that we modify
|
||||
vertices[j + 1] = heightData[i];
|
||||
}
|
||||
@ -35,6 +35,7 @@ function PhysicsTerrain() {
|
||||
// 创建网格
|
||||
THREE.Mesh.call(this, geometry, material);
|
||||
|
||||
this.name = '地形';
|
||||
this.castShadow = true;
|
||||
this.receiveShadow = true;
|
||||
|
||||
@ -47,6 +48,21 @@ function PhysicsTerrain() {
|
||||
material.map = texture;
|
||||
material.needsUpdate = true;
|
||||
});
|
||||
|
||||
// 创建地形刚体
|
||||
var groundShape = this.createTerrainShape(terrainWidth, terrainDepth, terrainWidthExtents, terrainDepthExtents, heightData, terrainMinHeight, terrainMaxHeight);
|
||||
var groundTransform = new Ammo.btTransform();
|
||||
groundTransform.setIdentity();
|
||||
// 由于子弹将其重新定位在其边界框上,因此会改变地形。
|
||||
groundTransform.setOrigin(new Ammo.btVector3(0, (terrainMinHeight + terrainMaxHeight) / 2, 0));
|
||||
|
||||
// 初始化刚体参数
|
||||
var groundMass = 0;
|
||||
var groundLocalInertia = new Ammo.btVector3(0, 0, 0); // 惯性
|
||||
var groundMotionState = new Ammo.btDefaultMotionState(groundTransform);
|
||||
var groundBody = new Ammo.btRigidBody(new Ammo.btRigidBodyConstructionInfo(groundMass, groundMotionState, groundShape, groundLocalInertia));
|
||||
|
||||
this.userData.physicsBody = groundBody;
|
||||
}
|
||||
|
||||
PhysicsTerrain.prototype = Object.create(THREE.Mesh.prototype);
|
||||
@ -78,222 +94,74 @@ PhysicsTerrain.prototype.generateHeight = function (width, depth, minHeight, max
|
||||
return data;
|
||||
};
|
||||
|
||||
export default PhysicsTerrain;
|
||||
/**
|
||||
* 创建物理地形形状
|
||||
* @param {*} terrainWidth
|
||||
* @param {*} terrainDepth
|
||||
* @param {*} terrainWidthExtents
|
||||
* @param {*} terrainDepthExtents
|
||||
* @param {*} heightData
|
||||
* @param {*} terrainMinHeight
|
||||
* @param {*} terrainMaxHeight
|
||||
*/
|
||||
PhysicsTerrain.prototype.createTerrainShape = function (terrainWidth, terrainDepth, terrainWidthExtents, terrainDepthExtents, heightData, terrainMinHeight, terrainMaxHeight) {
|
||||
// 此参数并未真正使用,因为我们使用的是PHY_FLOAT高度数据类型,因此会被忽略。
|
||||
var heightScale = 1;
|
||||
// 向上轴 0表示X,1表示Y,2表示Z。通常使用1=Y。
|
||||
var upAxis = 1;
|
||||
// hdt,高度数据类型。 使用“PHY_FLOAT”。 可能的值为“PHY_FLOAT”,“PHY_UCHAR”,“PHY_SHORT”。
|
||||
var hdt = "PHY_FLOAT";
|
||||
// 根据您的需要设置(反转三角形)。
|
||||
var flipQuadEdges = false;
|
||||
// 在Ammo堆中创建高度数据缓冲区。
|
||||
var ammoHeightData = Ammo._malloc(4 * terrainWidth * terrainDepth);
|
||||
// 将javascript高度数据数组复制到Ammo。
|
||||
var p = 0;
|
||||
var p2 = 0;
|
||||
for (var j = 0; j < terrainDepth; j++) {
|
||||
for (var i = 0; i < terrainWidth; i++) {
|
||||
// 将32位浮点数写入内存。
|
||||
Ammo.HEAPF32[ammoHeightData + p2 >> 2] = heightData[p];
|
||||
p++;
|
||||
// 4个字节/浮点数
|
||||
p2 += 4;
|
||||
}
|
||||
}
|
||||
// 创建高度场物理形状
|
||||
var heightFieldShape = new Ammo.btHeightfieldTerrainShape(
|
||||
terrainWidth,
|
||||
terrainDepth,
|
||||
ammoHeightData,
|
||||
heightScale,
|
||||
terrainMinHeight,
|
||||
terrainMaxHeight,
|
||||
upAxis,
|
||||
hdt,
|
||||
flipQuadEdges
|
||||
);
|
||||
// 设置水平缩放
|
||||
var scaleX = terrainWidthExtents / (terrainWidth - 1);
|
||||
var scaleZ = terrainDepthExtents / (terrainDepth - 1);
|
||||
heightFieldShape.setLocalScaling(new Ammo.btVector3(scaleX, 1, scaleZ));
|
||||
heightFieldShape.setMargin(0.05);
|
||||
return heightFieldShape;
|
||||
};
|
||||
|
||||
// function init() {
|
||||
// heightData = generateHeight(terrainWidth, terrainDepth, terrainMinHeight, terrainMaxHeight);
|
||||
// initGraphics();
|
||||
// initPhysics();
|
||||
// }
|
||||
PhysicsTerrain.prototype.update = function (deltaTime, physicsWorld) {
|
||||
physicsWorld.stepSimulation(deltaTime, 10);
|
||||
|
||||
// function initGraphics() {
|
||||
// var geometry = new THREE.PlaneBufferGeometry(terrainWidthExtents, terrainDepthExtents, terrainWidth - 1, terrainDepth - 1);
|
||||
// geometry.rotateX(-Math.PI / 2);
|
||||
// var vertices = geometry.attributes.position.array;
|
||||
// for (var i = 0, j = 0, l = vertices.length; i < l; i++, j += 3) {
|
||||
// // j + 1 because it is the y component that we modify
|
||||
// vertices[j + 1] = heightData[i];
|
||||
// }
|
||||
// geometry.computeVertexNormals();
|
||||
// var groundMaterial = new THREE.MeshPhongMaterial({
|
||||
// color: 0xC7C7C7
|
||||
// });
|
||||
// terrainMesh = new THREE.Mesh(geometry, groundMaterial);
|
||||
// terrainMesh.receiveShadow = true;
|
||||
// terrainMesh.castShadow = true;
|
||||
// scene.add(terrainMesh);
|
||||
// var textureLoader = new THREE.TextureLoader();
|
||||
// textureLoader.load("textures/grid.png", function (texture) {
|
||||
// texture.wrapS = THREE.RepeatWrapping;
|
||||
// texture.wrapT = THREE.RepeatWrapping;
|
||||
// texture.repeat.set(terrainWidth - 1, terrainDepth - 1);
|
||||
// groundMaterial.map = texture;
|
||||
// groundMaterial.needsUpdate = true;
|
||||
// });
|
||||
// }
|
||||
var body = this.userData.physics.body;
|
||||
var state = body.getMotionState();
|
||||
|
||||
// function initPhysics() {
|
||||
// // Physics configuration
|
||||
// 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, -6, 0));
|
||||
// // Create the terrain body
|
||||
// var groundShape = createTerrainShape();
|
||||
// var groundTransform = new Ammo.btTransform();
|
||||
// groundTransform.setIdentity();
|
||||
// // Shifts the terrain, since bullet re-centers it on its bounding box.
|
||||
// groundTransform.setOrigin(new Ammo.btVector3(0, (terrainMaxHeight + terrainMinHeight) / 2, 0));
|
||||
// var groundMass = 0;
|
||||
// var groundLocalInertia = new Ammo.btVector3(0, 0, 0);
|
||||
// var groundMotionState = new Ammo.btDefaultMotionState(groundTransform);
|
||||
// var groundBody = new Ammo.btRigidBody(new Ammo.btRigidBodyConstructionInfo(groundMass, groundMotionState, groundShape, groundLocalInertia));
|
||||
// physicsWorld.addRigidBody(groundBody);
|
||||
// }
|
||||
if (state) {
|
||||
var transformAux1 = new Ammo.btTransform();
|
||||
|
||||
// function generateHeight(width, depth, minHeight, maxHeight) {
|
||||
// // Generates the height data (a sinus wave)
|
||||
// var size = width * depth;
|
||||
// var data = new Float32Array(size);
|
||||
// var hRange = maxHeight - minHeight;
|
||||
// var w2 = width / 2;
|
||||
// var d2 = depth / 2;
|
||||
// var phaseMult = 12;
|
||||
// var p = 0;
|
||||
// for (var j = 0; j < depth; j++) {
|
||||
// for (var i = 0; i < width; i++) {
|
||||
// var radius = Math.sqrt(
|
||||
// Math.pow((i - w2) / w2, 2.0) +
|
||||
// Math.pow((j - d2) / d2, 2.0));
|
||||
// var height = (Math.sin(radius * phaseMult) + 1) * 0.5 * hRange + minHeight;
|
||||
// data[p] = height;
|
||||
// p++;
|
||||
// }
|
||||
// }
|
||||
// return data;
|
||||
// }
|
||||
state.getWorldTransform(transformAux1);
|
||||
var p = transformAux1.getOrigin();
|
||||
var q = transformAux1.getRotation();
|
||||
this.position.set(p.x(), p.y(), p.z());
|
||||
this.quaternion.set(q.x(), q.y(), q.z(), q.w());
|
||||
}
|
||||
};
|
||||
|
||||
// function createTerrainShape() {
|
||||
// // This parameter is not really used, since we are using PHY_FLOAT height data type and hence it is ignored
|
||||
// var heightScale = 1;
|
||||
// // Up axis = 0 for X, 1 for Y, 2 for Z. Normally 1 = Y is used.
|
||||
// var upAxis = 1;
|
||||
// // hdt, height data type. "PHY_FLOAT" is used. Possible values are "PHY_FLOAT", "PHY_UCHAR", "PHY_SHORT"
|
||||
// var hdt = "PHY_FLOAT";
|
||||
// // Set this to your needs (inverts the triangles)
|
||||
// var flipQuadEdges = false;
|
||||
// // Creates height data buffer in Ammo heap
|
||||
// ammoHeightData = Ammo._malloc(4 * terrainWidth * terrainDepth);
|
||||
// // Copy the javascript height data array to the Ammo one.
|
||||
// var p = 0;
|
||||
// var p2 = 0;
|
||||
// for (var j = 0; j < terrainDepth; j++) {
|
||||
// for (var i = 0; i < terrainWidth; i++) {
|
||||
// // write 32-bit float data to memory
|
||||
// Ammo.HEAPF32[ammoHeightData + p2 >> 2] = heightData[p];
|
||||
// p++;
|
||||
// // 4 bytes/float
|
||||
// p2 += 4;
|
||||
// }
|
||||
// }
|
||||
// // Creates the heightfield physics shape
|
||||
// var heightFieldShape = new Ammo.btHeightfieldTerrainShape(
|
||||
// terrainWidth,
|
||||
// terrainDepth,
|
||||
// ammoHeightData,
|
||||
// heightScale,
|
||||
// terrainMinHeight,
|
||||
// terrainMaxHeight,
|
||||
// upAxis,
|
||||
// hdt,
|
||||
// flipQuadEdges
|
||||
// );
|
||||
// // Set horizontal scale
|
||||
// var scaleX = terrainWidthExtents / (terrainWidth - 1);
|
||||
// var scaleZ = terrainDepthExtents / (terrainDepth - 1);
|
||||
// heightFieldShape.setLocalScaling(new Ammo.btVector3(scaleX, 1, scaleZ));
|
||||
// heightFieldShape.setMargin(0.05);
|
||||
// return heightFieldShape;
|
||||
// }
|
||||
|
||||
// function generateObject() {
|
||||
// var numTypes = 4;
|
||||
// var objectType = Math.ceil(Math.random() * numTypes);
|
||||
// var threeObject = null;
|
||||
// var shape = null;
|
||||
// var objectSize = 3;
|
||||
// var margin = 0.05;
|
||||
// switch (objectType) {
|
||||
// case 1:
|
||||
// // Sphere
|
||||
// var radius = 1 + Math.random() * objectSize;
|
||||
// threeObject = new THREE.Mesh(new THREE.SphereBufferGeometry(radius, 20, 20), createObjectMaterial());
|
||||
// shape = new Ammo.btSphereShape(radius);
|
||||
// shape.setMargin(margin);
|
||||
// break;
|
||||
// case 2:
|
||||
// // Box
|
||||
// var sx = 1 + Math.random() * objectSize;
|
||||
// var sy = 1 + Math.random() * objectSize;
|
||||
// var sz = 1 + Math.random() * objectSize;
|
||||
// threeObject = new THREE.Mesh(new THREE.BoxBufferGeometry(sx, sy, sz, 1, 1, 1), createObjectMaterial());
|
||||
// shape = new Ammo.btBoxShape(new Ammo.btVector3(sx * 0.5, sy * 0.5, sz * 0.5));
|
||||
// shape.setMargin(margin);
|
||||
// break;
|
||||
// case 3:
|
||||
// // Cylinder
|
||||
// var radius = 1 + Math.random() * objectSize;
|
||||
// var height = 1 + Math.random() * objectSize;
|
||||
// threeObject = new THREE.Mesh(new THREE.CylinderBufferGeometry(radius, radius, height, 20, 1), createObjectMaterial());
|
||||
// shape = new Ammo.btCylinderShape(new Ammo.btVector3(radius, height * 0.5, radius));
|
||||
// shape.setMargin(margin);
|
||||
// break;
|
||||
// default:
|
||||
// // Cone
|
||||
// var radius = 1 + Math.random() * objectSize;
|
||||
// var height = 2 + Math.random() * objectSize;
|
||||
// threeObject = new THREE.Mesh(new THREE.ConeBufferGeometry(radius, height, 20, 2), createObjectMaterial());
|
||||
// shape = new Ammo.btConeShape(radius, height);
|
||||
// break;
|
||||
// }
|
||||
// threeObject.position.set((Math.random() - 0.5) * terrainWidth * 0.6, terrainMaxHeight + objectSize + 2, (Math.random() - 0.5) * terrainDepth * 0.6);
|
||||
// var mass = objectSize * 5;
|
||||
// var localInertia = new Ammo.btVector3(0, 0, 0);
|
||||
// shape.calculateLocalInertia(mass, localInertia);
|
||||
// var transform = new Ammo.btTransform();
|
||||
// transform.setIdentity();
|
||||
// var pos = threeObject.position;
|
||||
// transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
|
||||
// var motionState = new Ammo.btDefaultMotionState(transform);
|
||||
// var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, shape, localInertia);
|
||||
// var body = new Ammo.btRigidBody(rbInfo);
|
||||
// threeObject.userData.physicsBody = body;
|
||||
// threeObject.receiveShadow = true;
|
||||
// threeObject.castShadow = true;
|
||||
// scene.add(threeObject);
|
||||
// dynamicObjects.push(threeObject);
|
||||
// physicsWorld.addRigidBody(body);
|
||||
// }
|
||||
|
||||
// function createObjectMaterial() {
|
||||
// var c = Math.floor(Math.random() * (1 << 24));
|
||||
// return new THREE.MeshPhongMaterial({
|
||||
// color: c
|
||||
// });
|
||||
// }
|
||||
|
||||
// function animate() {
|
||||
// requestAnimationFrame(animate);
|
||||
// render();
|
||||
// stats.update();
|
||||
// }
|
||||
|
||||
// function render() {
|
||||
// var deltaTime = clock.getDelta();
|
||||
// if (dynamicObjects.length < maxNumObjects && time > timeNextSpawn) {
|
||||
// generateObject();
|
||||
// timeNextSpawn = time + objectTimePeriod;
|
||||
// }
|
||||
// updatePhysics(deltaTime);
|
||||
// renderer.render(scene, camera);
|
||||
// time += deltaTime;
|
||||
// }
|
||||
|
||||
// function updatePhysics(deltaTime) {
|
||||
// physicsWorld.stepSimulation(deltaTime, 10);
|
||||
// // Update objects
|
||||
// for (var i = 0, il = dynamicObjects.length; i < il; i++) {
|
||||
// var objThree = dynamicObjects[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());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
export default PhysicsTerrain;
|
||||
Loading…
x
Reference in New Issue
Block a user