mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 01:04:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			410 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			410 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!--********************************************************************
 | 
						||
* by jiawanlong
 | 
						||
*********************************************************************-->
 | 
						||
<!DOCTYPE html>
 | 
						||
<html>
 | 
						||
 | 
						||
<head>
 | 
						||
    <meta charset="UTF-8" />
 | 
						||
    <link rel="stylesheet" href="./../../libs/cesium/Cesium1.72/Widgets/widgets.css" />
 | 
						||
    <script type="text/javascript" src="./../../libs/cesium/Cesium1.72/Cesium.js"></script>
 | 
						||
    <script src="./ammolibs/ammo/ammo.js"></script>
 | 
						||
</head>
 | 
						||
 | 
						||
<body style="
 | 
						||
      margin: 0;
 | 
						||
      overflow: hidden;
 | 
						||
      background: #fff;
 | 
						||
      width: 100%;
 | 
						||
      height: 100%;
 | 
						||
      position: absolute;
 | 
						||
      top: 0;
 | 
						||
    ">
 | 
						||
    <div id="cesiumContainer" style="margin: 0 auto; width: 100%; height: 100%"></div>
 | 
						||
    <!-- {/* 操作提示: Q 左摆动、 A 右摆动 */} -->
 | 
						||
 | 
						||
    <script src="./ammolibs/three/three.min.js"></script>
 | 
						||
    <script src="./ammolibs/ammo/ex/ConvexObjectBreaker.js"></script>
 | 
						||
    <script src="./ammolibs/ammo/ex/QuickHull.js"></script>
 | 
						||
    <script src="./ammolibs/ammo/ex/geometries/ConvexGeometry.js"></script>
 | 
						||
    <script src="./ammolibs/meshVisualizer/CesiumMeshVisualizer.js"></script>
 | 
						||
    <script>
 | 
						||
      
 | 
						||
    Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMjBhMzcxMC0wNjBiLTRmYjItYjY1MC0wMzAwMzMyMGUyMmEiLCJpZCI6MzAzNzc3LCJpYXQiOjE3NDc2Mzk0NTV9.E_90aKtVdzRGlU2z48VwJ4mWvl-uuDkfQBCOO6zbzn4'
 | 
						||
   
 | 
						||
   const viewer = new Cesium.Viewer('cesiumContainer', {});
 | 
						||
 | 
						||
   var homePosition = [114.40184, 30.46331, 50]; //初始位置
 | 
						||
    look(homePosition[0], homePosition[1], homePosition[2]);
 | 
						||
   
 | 
						||
       viewer.scene.debugShowFramesPerSecond = true; //查看帧率
 | 
						||
   
 | 
						||
       MeshVisualizer = Cesium.MeshVisualizer;
 | 
						||
       Mesh = Cesium.Mesh;
 | 
						||
       MeshMaterial = Cesium.MeshMaterial;
 | 
						||
       FramebufferTexture = Cesium.FramebufferTexture;
 | 
						||
       GeometryUtils = Cesium.GeometryUtils;
 | 
						||
       LOD = Cesium.LOD;
 | 
						||
       PlaneBufferGeometry = Cesium.PlaneBufferGeometry;
 | 
						||
       BasicMeshMaterial = Cesium.BasicMeshMaterial;
 | 
						||
       MeshPhongMaterial = Cesium.MeshPhongMaterial;
 | 
						||
   
 | 
						||
       var center = Cesium.Cartesian3.fromDegrees(homePosition[0], homePosition[1], 10);
 | 
						||
       var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
 | 
						||
   
 | 
						||
       var meshVisualizer = new MeshVisualizer({
 | 
						||
           modelMatrix: modelMatrix,
 | 
						||
           up: {
 | 
						||
               y: 1
 | 
						||
           },
 | 
						||
           referenceAxisParameter: {
 | 
						||
               length: 100,
 | 
						||
               width: 0.05,
 | 
						||
               headLength: 2,
 | 
						||
               headWidth: 0.1
 | 
						||
           }
 | 
						||
       });
 | 
						||
       viewer.scene.primitives.add(meshVisualizer);
 | 
						||
       meshVisualizer.showReference = true; //显示坐标轴
 | 
						||
       Ammo().then(function () {
 | 
						||
           // Physics variables
 | 
						||
           var gravityConstant = -9.8;
 | 
						||
           var collisionConfiguration;
 | 
						||
           var dispatcher;
 | 
						||
           var broadphase;
 | 
						||
           var solver;
 | 
						||
           var physicsWorld;
 | 
						||
           var rigidBodies = [];
 | 
						||
           var margin = 0.05;
 | 
						||
           var hinge;
 | 
						||
           var cloth;
 | 
						||
           var transformAux1 = new Ammo.btTransform();
 | 
						||
           var armMovement = 0;
 | 
						||
   
 | 
						||
           function initPhysics() {
 | 
						||
               // Physics configuration
 | 
						||
   
 | 
						||
               collisionConfiguration = new Ammo.btSoftBodyRigidBodyCollisionConfiguration();
 | 
						||
               dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
 | 
						||
               broadphase = new Ammo.btDbvtBroadphase();
 | 
						||
               solver = new Ammo.btSequentialImpulseConstraintSolver();
 | 
						||
               softBodySolver = new Ammo.btDefaultSoftBodySolver();
 | 
						||
               physicsWorld = new Ammo.btSoftRigidDynamicsWorld(dispatcher, broadphase, solver,
 | 
						||
                   collisionConfiguration,
 | 
						||
                   softBodySolver);
 | 
						||
               physicsWorld.setGravity(new Ammo.btVector3(0, gravityConstant, 0));
 | 
						||
               physicsWorld.getWorldInfo().set_m_gravity(new Ammo.btVector3(0, gravityConstant, 0));
 | 
						||
           }
 | 
						||
   
 | 
						||
           function createRandomColor() {
 | 
						||
               return Cesium.Color.fromRandom({
 | 
						||
                   alpha: 1
 | 
						||
               }) //fromRgba(Math.floor(Math.random() * (1 << 24)));
 | 
						||
           }
 | 
						||
   
 | 
						||
           function createMaterial() {
 | 
						||
               return new MeshPhongMaterial({
 | 
						||
                   defaultColor: createRandomColor(),
 | 
						||
                   side: MeshMaterial.Sides.DOUBLE,
 | 
						||
                   translucent: false
 | 
						||
               });
 | 
						||
           }
 | 
						||
   
 | 
						||
           function createObjects() {
 | 
						||
               var pos = new Cesium.Cartesian3();
 | 
						||
               var quat = new Cesium.Quaternion();
 | 
						||
   
 | 
						||
               // Ground
 | 
						||
               pos.x = 0, pos.y = -0.5, pos.z = 0;
 | 
						||
               quat.x = 0, quat.y = 0, quat.z = 0, quat.w = 1;
 | 
						||
               var ground = createParalellepiped(40, 1, 40, 0, pos, quat, new MeshPhongMaterial({
 | 
						||
                   defaultColor: "rgb(125,125,125)",
 | 
						||
                   side: MeshMaterial.Sides.DOUBLE,
 | 
						||
                   translucent: false
 | 
						||
               }));
 | 
						||
   
 | 
						||
               // Wall
 | 
						||
               var brickMass = 0.5;
 | 
						||
               var brickLength = 1.2;
 | 
						||
               var brickDepth = 0.6;
 | 
						||
               var brickHeight = brickLength * 0.5;
 | 
						||
               var numBricksLength = 6;
 | 
						||
               var numBricksHeight = 8;
 | 
						||
               var z0 = -numBricksLength * brickLength * 0.5;
 | 
						||
   
 | 
						||
               pos.x = 0, pos.y = brickHeight * 0.5, pos.z = z0;
 | 
						||
               quat.x = 0, quat.y = 0, quat.z = 0, quat.w = 1;
 | 
						||
               for (var j = 0; j < numBricksHeight; j++) {
 | 
						||
                   var oddRow = (j % 2) == 1;
 | 
						||
                   pos.z = z0;
 | 
						||
                   if (oddRow) {
 | 
						||
                       pos.z -= 0.25 * brickLength;
 | 
						||
                   }
 | 
						||
   
 | 
						||
                   var nRow = oddRow ? numBricksLength + 1 : numBricksLength;
 | 
						||
                   for (var i = 0; i < nRow; i++) {
 | 
						||
                       var brickLengthCurrent = brickLength;
 | 
						||
                       var brickMassCurrent = brickMass;
 | 
						||
                       if (oddRow && (i == 0 || i == nRow - 1)) {
 | 
						||
                           brickLengthCurrent *= 0.5;
 | 
						||
                           brickMassCurrent *= 0.5;
 | 
						||
                       }
 | 
						||
   
 | 
						||
                       var brick = createParalellepiped(brickDepth, brickHeight, brickLengthCurrent,
 | 
						||
                           brickMassCurrent, pos,
 | 
						||
                           quat, createMaterial());
 | 
						||
   
 | 
						||
                       if (oddRow && (i == 0 || i == nRow - 2)) {
 | 
						||
                           pos.z += 0.75 * brickLength;
 | 
						||
                       } else {
 | 
						||
                           pos.z += brickLength;
 | 
						||
                       }
 | 
						||
                   }
 | 
						||
                   pos.y += brickHeight;
 | 
						||
               }
 | 
						||
   
 | 
						||
               // The cloth
 | 
						||
               // Cloth graphic object
 | 
						||
               var clothWidth = 4;
 | 
						||
               var clothHeight = 3;
 | 
						||
               var clothNumSegmentsZ = clothWidth * 5;
 | 
						||
               var clothNumSegmentsY = clothHeight * 5;
 | 
						||
               var clothSegmentLengthZ = clothWidth / clothNumSegmentsZ;
 | 
						||
               var clothSegmentLengthY = clothHeight / clothNumSegmentsY;
 | 
						||
               var clothPos = new Cesium.Cartesian3(-3, 3, 2);
 | 
						||
               var clothGeometry = new PlaneBufferGeometry(clothWidth, clothHeight, clothNumSegmentsZ,
 | 
						||
                   clothNumSegmentsY);
 | 
						||
   
 | 
						||
               var clothMaterial = new MeshPhongMaterial({
 | 
						||
                   defaultColor: "rgb(255,255,255)",
 | 
						||
                   side: MeshMaterial.Sides.DOUBLE,
 | 
						||
                   translucent: false
 | 
						||
               });
 | 
						||
   
 | 
						||
               cloth = new Mesh(clothGeometry, clothMaterial);
 | 
						||
               GeometryUtils.rotateY(cloth.geometry, Math.PI * 0.5)
 | 
						||
               GeometryUtils.translate(cloth.geometry, clothPos.x, clothPos.y + clothHeight * 0.5, clothPos.z -
 | 
						||
                   clothWidth * 0.5)
 | 
						||
               GeometryUtils.computeVertexNormals(cloth.geometry);
 | 
						||
               meshVisualizer.add(cloth);
 | 
						||
   
 | 
						||
               // Cloth physic object
 | 
						||
               var softBodyHelpers = new Ammo.btSoftBodyHelpers();
 | 
						||
               var clothCorner00 = new Ammo.btVector3(clothPos.x, clothPos.y + clothHeight, clothPos.z);
 | 
						||
               var clothCorner01 = new Ammo.btVector3(clothPos.x, clothPos.y + clothHeight, clothPos.z -
 | 
						||
                   clothWidth);
 | 
						||
               var clothCorner10 = new Ammo.btVector3(clothPos.x, clothPos.y, clothPos.z);
 | 
						||
               var clothCorner11 = new Ammo.btVector3(clothPos.x, clothPos.y, clothPos.z - clothWidth);
 | 
						||
               var clothSoftBody = softBodyHelpers.CreatePatch(physicsWorld.getWorldInfo(), clothCorner00,
 | 
						||
                   clothCorner01,
 | 
						||
                   clothCorner10, clothCorner11, clothNumSegmentsZ + 1, clothNumSegmentsY + 1, 0, true);
 | 
						||
               var sbConfig = clothSoftBody.get_m_cfg();
 | 
						||
               sbConfig.set_viterations(10);
 | 
						||
               sbConfig.set_piterations(10);
 | 
						||
   
 | 
						||
               clothSoftBody.setTotalMass(0.9, false)
 | 
						||
               Ammo.castObject(clothSoftBody, Ammo.btCollisionObject).getCollisionShape().setMargin(margin * 3);
 | 
						||
               physicsWorld.addSoftBody(clothSoftBody, 1, -1);
 | 
						||
               cloth.physicsBody = clothSoftBody;
 | 
						||
               // Disable deactivation
 | 
						||
               clothSoftBody.setActivationState(4);
 | 
						||
   
 | 
						||
               // The base
 | 
						||
               var armMass = 2;
 | 
						||
               var armLength = 3 + clothWidth;
 | 
						||
               var pylonHeight = clothPos.y + clothHeight;
 | 
						||
               var baseMaterial = new MeshPhongMaterial({
 | 
						||
                   defaultColor: "rgb(255,255,0)",
 | 
						||
                   side: MeshMaterial.Sides.DOUBLE,
 | 
						||
                   translucent: false
 | 
						||
               });
 | 
						||
               pos.x = clothPos.x, pos.y = 0.1, pos.z = clothPos.z - armLength;
 | 
						||
               quat.x = 0, quat.y = 0, quat.z = 0, quat.w = 1;
 | 
						||
               var base = createParalellepiped(1, 0.2, 1, 0, pos, quat, baseMaterial);
 | 
						||
   
 | 
						||
               pos.x = clothPos.x, pos.y = 0.5 * pylonHeight, pos.z = clothPos.z - armLength;
 | 
						||
               var pylon = createParalellepiped(0.4, pylonHeight, 0.4, 0, pos, quat, baseMaterial);
 | 
						||
   
 | 
						||
               pos.x = clothPos.x, pos.y = pylonHeight + 0.2, pos.z = clothPos.z - 0.5 * armLength;
 | 
						||
               var arm = createParalellepiped(0.4, 0.4, armLength + 0.4, armMass, pos, quat, baseMaterial);
 | 
						||
   
 | 
						||
               // Glue the cloth to the arm
 | 
						||
               var influence = 0.5;
 | 
						||
               clothSoftBody.appendAnchor(0, arm.physicsBody, false, influence);
 | 
						||
               clothSoftBody.appendAnchor(clothNumSegmentsZ, arm.physicsBody, false, influence);
 | 
						||
   
 | 
						||
               // Hinge constraint to move the arm
 | 
						||
               var pivotA = new Ammo.btVector3(0, pylonHeight * 0.5, 0);
 | 
						||
               var pivotB = new Ammo.btVector3(0, -0.2, -armLength * 0.5);
 | 
						||
               var axis = new Ammo.btVector3(0, 1, 0);
 | 
						||
               hinge = new Ammo.btHingeConstraint(pylon.physicsBody, arm.physicsBody, pivotA, pivotB, axis, axis,
 | 
						||
                   true);
 | 
						||
               physicsWorld.addConstraint(hinge, true);
 | 
						||
           }
 | 
						||
   
 | 
						||
           function createParalellepiped(sx, sy, sz, mass, pos, quat, material) {
 | 
						||
               var threeObject = new Mesh(Cesium.BoxGeometry.fromDimensions({
 | 
						||
                   dimensions: new Cesium.Cartesian3(sx, sy, sz),
 | 
						||
                   vertexFormat: new Cesium.VertexFormat({
 | 
						||
                       position: true,
 | 
						||
                       st: true,
 | 
						||
                       normal: true
 | 
						||
                   })
 | 
						||
               }), material);
 | 
						||
   
 | 
						||
               threeObject.quaternion = new Cesium.Quaternion();
 | 
						||
               threeObject.geometry.attributes.uv = threeObject.geometry.attributes.st;
 | 
						||
               threeObject.geometry.attributes.st = undefined;
 | 
						||
               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) {
 | 
						||
               Cesium.Cartesian3.clone(pos, threeObject.position);
 | 
						||
               Cesium.Quaternion.clone(quat, threeObject.quaternion);
 | 
						||
   
 | 
						||
               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.physicsBody = body;
 | 
						||
   
 | 
						||
               meshVisualizer.add(threeObject);
 | 
						||
   
 | 
						||
               if (mass > 0) {
 | 
						||
                   rigidBodies.push(threeObject);
 | 
						||
   
 | 
						||
                   // Disable deactivation
 | 
						||
                   body.setActivationState(4);
 | 
						||
               }
 | 
						||
   
 | 
						||
               physicsWorld.addRigidBody(body);
 | 
						||
           }
 | 
						||
   
 | 
						||
           //deltaTime单位是:秒/s
 | 
						||
           function updatePhysics(deltaTime) {
 | 
						||
               // Hinge control
 | 
						||
               hinge.enableAngularMotor(true, 0.8 * armMovement, 50);
 | 
						||
   
 | 
						||
               // Step world
 | 
						||
               physicsWorld.stepSimulation(deltaTime, 10);
 | 
						||
   
 | 
						||
               // Update cloth
 | 
						||
               var softBody = cloth.physicsBody;
 | 
						||
               var clothPositions = cloth.geometry.attributes.position.values;
 | 
						||
               var numVerts = clothPositions.length / 3;
 | 
						||
               var nodes = softBody.get_m_nodes();
 | 
						||
               var indexFloat = 0;
 | 
						||
               for (var i = 0; i < numVerts; i++) {
 | 
						||
                   var node = nodes.at(i);
 | 
						||
                   var nodePos = node.get_m_x();
 | 
						||
                   clothPositions[indexFloat++] = nodePos.x();
 | 
						||
                   clothPositions[indexFloat++] = nodePos.y();
 | 
						||
                   clothPositions[indexFloat++] = nodePos.z();
 | 
						||
               }
 | 
						||
   
 | 
						||
               cloth.geometry.attributes.position.needsUpdate = true;
 | 
						||
               if (cloth.geometry.primitiveType == Cesium.PrimitiveType.TRIANGLES) {
 | 
						||
                   // Cesium.GeometryPipeline.computeNormal(cloth.geometry);
 | 
						||
                   GeometryUtils.computeVertexNormals(cloth.geometry);
 | 
						||
               }
 | 
						||
   
 | 
						||
               // Update rigid bodies
 | 
						||
               for (var i = 0, il = rigidBodies.length; i < il; i++) {
 | 
						||
                   var objGraph = rigidBodies[i];
 | 
						||
                   var objPhys = objGraph.physicsBody;
 | 
						||
                   var ms = objPhys.getMotionState();
 | 
						||
                   if (ms) {
 | 
						||
                       ms.getWorldTransform(transformAux1);
 | 
						||
                       var p = transformAux1.getOrigin();
 | 
						||
                       var q = transformAux1.getRotation();
 | 
						||
                       objGraph.position.x = p.x();
 | 
						||
                       objGraph.position.y = p.y();
 | 
						||
                       objGraph.position.z = p.z();
 | 
						||
                       objGraph.quaternion.x = q.x();
 | 
						||
                       objGraph.quaternion.y = q.y();
 | 
						||
                       objGraph.quaternion.z = q.z();
 | 
						||
                       objGraph.quaternion.w = q.w();
 | 
						||
                       //objGraph.needsUpdate = true;
 | 
						||
                       objGraph.modelMatrixNeedsUpdate = true;
 | 
						||
                   }
 | 
						||
               }
 | 
						||
           }
 | 
						||
   
 | 
						||
           var start = false;
 | 
						||
   
 | 
						||
           function initInput() {
 | 
						||
               top.window.addEventListener('keydown', function (event) {
 | 
						||
                   if (!start) {
 | 
						||
                       return;
 | 
						||
                   }
 | 
						||
   
 | 
						||
                   switch (event.keyCode) {
 | 
						||
                       case 81: // Q
 | 
						||
                           armMovement = 1;
 | 
						||
                           break;
 | 
						||
                       case 65: // A
 | 
						||
                           armMovement = -1;
 | 
						||
                           break;
 | 
						||
                   }
 | 
						||
               }, false);
 | 
						||
   
 | 
						||
               top.window.addEventListener('keyup', function (event) {
 | 
						||
                   armMovement = 0;
 | 
						||
               }, false);
 | 
						||
           }
 | 
						||
   
 | 
						||
           var startTime = new Date();
 | 
						||
   
 | 
						||
           function update(frameState) {
 | 
						||
               var deltaTime = (new Date() - startTime) / 1000.0;
 | 
						||
               updatePhysics(deltaTime);
 | 
						||
               startTime = new Date();
 | 
						||
           }
 | 
						||
   
 | 
						||
           var init = false;
 | 
						||
           setTimeout(function () {
 | 
						||
               if (!init) {
 | 
						||
                   initPhysics();
 | 
						||
                   createObjects();
 | 
						||
                   initInput();
 | 
						||
                   init = true;
 | 
						||
               }
 | 
						||
   
 | 
						||
               if (!start) {
 | 
						||
                   meshVisualizer.beforeUpdate.addEventListener(update);
 | 
						||
                   start = true;
 | 
						||
               } else {
 | 
						||
                   meshVisualizer.beforeUpdate.removeEventListener(update);
 | 
						||
                   start = false;
 | 
						||
               }
 | 
						||
           }, 1000 * 3);
 | 
						||
       });
 | 
						||
   
 | 
						||
       function look(lon, lat, offset) {
 | 
						||
           var center = Cesium.Cartesian3.fromDegrees(lon, lat);
 | 
						||
           var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);
 | 
						||
   
 | 
						||
           // View in east-north-up frame
 | 
						||
           var camera = viewer.camera;
 | 
						||
           camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z;
 | 
						||
           camera.lookAtTransform(transform, new Cesium.Cartesian3(-offset, -offset, offset));
 | 
						||
           setTimeout(function () {
 | 
						||
               camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
 | 
						||
           }, 100)
 | 
						||
       }
 | 
						||
    </script>
 | 
						||
</body>
 | 
						||
 | 
						||
</html> |