m33_ammo_vehicle.html 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0,minimum-scale=1.0,maximum-scale=1.0" />
  6. <meta name="author" content="火星科技 http://mars3d.cn " />
  7. <meta name="apple-touch-fullscreen" content="yes" />
  8. <meta name="apple-mobile-web-app-capable" content="yes" />
  9. <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  10. <meta name="format-detection" content="telephone=no" />
  11. <meta name="x5-fullscreen" content="true" />
  12. <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
  13. <!-- 标题及搜索关键字 -->
  14. <meta name="keywords" content="火星科技,cesium,3D,GIS,marsgis,三维,地球,地图,开发,框架,系统,示例,资料,模型,离线,外包,合肥,安徽,中国" />
  15. <meta
  16. name="description"
  17. content="火星科技 合肥火星 合肥火星科技 合肥火星科技有限公司 leaflet leaflet框架 leaflet开发 cesium cesium开发 cesium框架 三维 地球 模型 gis marsgis 地图离线 地图开发 地图框架 地图外包 框架 开发 外包 地图离线 二维地图 三维地图 全景漫游 地理信息系统 云GIS 三维GIS GIS平台 WebGIS"
  18. />
  19. <link rel="shortcut icon" type="image/x-icon" href="" />
  20. <title>ammo物理引擎扩展支持 </title>
  21. <!--第三方lib-->
  22. <script
  23. type="text/javascript"
  24. src="../lib/include-lib.js"
  25. libpath="../lib/"
  26. include="jquery,font-awesome,bootstrap,layer,haoutil,turf,mars3d,cesium-meshVisualizer"
  27. ></script>
  28. <link href="css/style.css" rel="stylesheet" />
  29. </head>
  30. <body class="dark">
  31. <div id="mars3dContainer" class="mars3d-container"></div>
  32. <!-- 面板 -->
  33. <div class="infoview">操作提示:W 前进、S 后退、 A 左转弯、D 右转弯</div>
  34. <script src="./js/common.js"></script>
  35. <script type="text/javascript">
  36. "use script"; //开发环境建议开启严格模式
  37. var map;
  38. function initMap(options) {
  39. //合并属性参数,可覆盖config.json中的对应配置
  40. var mapOptions = mars3d.Util.merge(options, {
  41. scene: {
  42. center: { lat: 31.835256, lng: 117.219292, alt: 128, heading: 120, pitch: -41 },
  43. fxaa: true,
  44. },
  45. });
  46. //创建三维地球场景
  47. map = new mars3d.Map("mars3dContainer", mapOptions);
  48. var center = Cesium.Cartesian3.fromDegrees(117.220206, 31.834866, 50);
  49. var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
  50. var meshVisualizer = new Cesium.MeshVisualizer({
  51. modelMatrix: modelMatrix,
  52. up: { y: 1 },
  53. referenceAxisParameter: {
  54. length: 100,
  55. width: 0.05,
  56. headLength: 2,
  57. headWidth: 0.1,
  58. },
  59. });
  60. map.scene.primitives.add(meshVisualizer);
  61. meshVisualizer.showReference = true; //显示坐标轴
  62. Cesium.Cartesian3.prototype.set = function (x, y, z) {
  63. this.x = x;
  64. this.y = y;
  65. this.z = z;
  66. };
  67. Cesium.Quaternion.prototype.set = function (x, y, z, w) {
  68. this.x = x;
  69. this.y = y;
  70. this.z = z;
  71. this.w = w;
  72. };
  73. Ammo().then(function () {
  74. // - Global variables -
  75. var DISABLE_DEACTIVATION = 4;
  76. var TRANSFORM_AUX = new Ammo.btTransform();
  77. var ZERO_QUATERNION = new Cesium.Quaternion(0, 0, 0, 1);
  78. // Graphics variables
  79. var materialDynamic, materialStatic, materialInteractive;
  80. // Physics variables
  81. var collisionConfiguration;
  82. var dispatcher;
  83. var broadphase;
  84. var solver;
  85. var physicsWorld;
  86. var syncList = [];
  87. var time = 0;
  88. var objectTimePeriod = 3;
  89. var timeNextSpawn = time + objectTimePeriod;
  90. var maxNumObjects = 30;
  91. // Keybord actions
  92. var actions = {};
  93. var keysActions = {
  94. KeyW: "acceleration",
  95. KeyS: "braking",
  96. KeyA: "left",
  97. KeyD: "right",
  98. };
  99. // - Functions -
  100. function initGraphics() {
  101. materialDynamic = createMaterial();
  102. materialStatic = createMaterial();
  103. materialInteractive = createMaterial();
  104. window.addEventListener("keydown", keydown);
  105. window.addEventListener("keyup", keyup);
  106. }
  107. function initPhysics() {
  108. // Physics configuration
  109. collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
  110. dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
  111. broadphase = new Ammo.btDbvtBroadphase();
  112. solver = new Ammo.btSequentialImpulseConstraintSolver();
  113. physicsWorld = new Ammo.btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
  114. physicsWorld.setGravity(new Ammo.btVector3(0, -9.82, 0));
  115. }
  116. function updatePhysics(deltTime) {
  117. for (var i = 0; i < syncList.length; i++) {
  118. syncList[i](deltTime);
  119. }
  120. physicsWorld.stepSimulation(deltTime, 10);
  121. time += deltTime;
  122. }
  123. function keyup(e) {
  124. if (keysActions[e.code]) {
  125. actions[keysActions[e.code]] = false;
  126. e.preventDefault();
  127. e.stopPropagation();
  128. return false;
  129. }
  130. }
  131. function keydown(e) {
  132. if (keysActions[e.code]) {
  133. actions[keysActions[e.code]] = true;
  134. e.preventDefault();
  135. e.stopPropagation();
  136. return false;
  137. }
  138. }
  139. function createBox(pos, quat, w, l, h, mass, friction) {
  140. var material = createMaterial(); //= mass > 0 ? materialDynamic : materialStatic;
  141. var shape = Cesium.BoxGeometry.fromDimensions({
  142. dimensions: new Cesium.Cartesian3(w, l, h),
  143. vertexFormat: new Cesium.VertexFormat({
  144. position: true,
  145. normal: true,
  146. }),
  147. });
  148. var geometry = new Ammo.btBoxShape(new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5));
  149. if (!mass) {
  150. mass = 0;
  151. }
  152. if (!friction) {
  153. friction = 1;
  154. }
  155. var mesh = new Cesium.Mesh(shape, material);
  156. Cesium.Cartesian3.clone(pos, mesh.position);
  157. mesh.quaternion = new Cesium.Quaternion(quat.x, quat.y, quat.z, quat.w);
  158. meshVisualizer.add(mesh);
  159. var transform = new Ammo.btTransform();
  160. transform.setIdentity();
  161. transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
  162. transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
  163. var motionState = new Ammo.btDefaultMotionState(transform);
  164. var localInertia = new Ammo.btVector3(0, 0, 0);
  165. geometry.calculateLocalInertia(mass, localInertia);
  166. var rbInfo = new Ammo.btRigidBodyConstructionInfo(mass, motionState, geometry, localInertia);
  167. var body = new Ammo.btRigidBody(rbInfo);
  168. body.setFriction(friction);
  169. //body.setRestitution(.9);
  170. //body.setDamping(0.2, 0.2);
  171. physicsWorld.addRigidBody(body);
  172. if (mass > 0) {
  173. body.setActivationState(DISABLE_DEACTIVATION);
  174. // Sync physics and graphics
  175. // eslint-disable-next-line no-inner-declarations
  176. function sync(dt) {
  177. var ms = body.getMotionState();
  178. if (ms) {
  179. ms.getWorldTransform(TRANSFORM_AUX);
  180. var p = TRANSFORM_AUX.getOrigin();
  181. var q = TRANSFORM_AUX.getRotation();
  182. mesh.position.set(p.x(), p.y(), p.z());
  183. mesh.quaternion.set(q.x(), q.y(), q.z(), q.w());
  184. mesh.modelMatrixNeedsUpdate = true;
  185. }
  186. }
  187. syncList.push(sync);
  188. }
  189. }
  190. function createWheelMesh(radius, width) {
  191. var t = new Cesium.CylinderGeometry({
  192. length: width,
  193. topRadius: radius,
  194. bottomRadius: radius,
  195. slices: 24,
  196. });
  197. //var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
  198. var mesh = new Cesium.Mesh(t, materialInteractive);
  199. Cesium.GeometryUtils.rotateY(mesh.geometry, Math.PI / 2);
  200. mesh.quaternion = new Cesium.Quaternion(); // Cesium.Quaternion.fromAxisAngle(new Cesium.Cartesian3(0, 0, 1), Math.PI / 2);
  201. var shape = Cesium.BoxGeometry.fromDimensions({
  202. dimensions: new Cesium.Cartesian3(width * 1.5, radius * 1.75, radius * 0.25),
  203. vertexFormat: new Cesium.VertexFormat({
  204. position: true,
  205. normal: true,
  206. }),
  207. });
  208. var meshShape = new Cesium.Mesh(shape, materialInteractive);
  209. meshShape.quaternion = new Cesium.Quaternion(); //.fromAxisAngle(new Cesium.Cartesian3(0, 0, 1), 0);
  210. mesh.add(meshShape);
  211. meshVisualizer.add(mesh);
  212. return mesh;
  213. }
  214. function createChassisMesh(w, l, h) {
  215. var shape = Cesium.BoxGeometry.fromDimensions({
  216. dimensions: new Cesium.Cartesian3(w, l, h),
  217. vertexFormat: new Cesium.VertexFormat({
  218. position: true,
  219. normal: true,
  220. }),
  221. });
  222. var mesh = new Cesium.Mesh(shape, materialInteractive);
  223. mesh.quaternion = new Cesium.Quaternion(0, 0, 0, 1);
  224. meshVisualizer.add(mesh);
  225. return mesh;
  226. }
  227. function createVehicle(pos, quat) {
  228. // Vehicle contants
  229. var chassisWidth = 1.8;
  230. var chassisHeight = 0.6;
  231. var chassisLength = 4;
  232. var massVehicle = 800;
  233. var wheelAxisPositionBack = -1;
  234. var wheelRadiusBack = 0.4;
  235. var wheelWidthBack = 0.3;
  236. var wheelHalfTrackBack = 1;
  237. var wheelAxisHeightBack = 0.3;
  238. var wheelAxisFrontPosition = 1.7;
  239. var wheelHalfTrackFront = 1;
  240. var wheelAxisHeightFront = 0.3;
  241. var wheelRadiusFront = 0.35;
  242. var wheelWidthFront = 0.2;
  243. var friction = 1000;
  244. var suspensionStiffness = 20.0;
  245. var suspensionDamping = 2.3;
  246. var suspensionCompression = 4.4;
  247. var suspensionRestLength = 0.6;
  248. var rollInfluence = 0.2;
  249. var steeringIncrement = 0.04;
  250. var steeringClamp = 0.5;
  251. var maxEngineForce = 2000;
  252. var maxBreakingForce = 100;
  253. // Chassis
  254. var geometry = new Ammo.btBoxShape(new Ammo.btVector3(chassisWidth * 0.5, chassisHeight * 0.5, chassisLength * 0.5));
  255. var transform = new Ammo.btTransform();
  256. transform.setIdentity();
  257. transform.setOrigin(new Ammo.btVector3(pos.x, pos.y, pos.z));
  258. transform.setRotation(new Ammo.btQuaternion(quat.x, quat.y, quat.z, quat.w));
  259. var motionState = new Ammo.btDefaultMotionState(transform);
  260. var localInertia = new Ammo.btVector3(0, 0, 0);
  261. geometry.calculateLocalInertia(massVehicle, localInertia);
  262. var body = new Ammo.btRigidBody(new Ammo.btRigidBodyConstructionInfo(massVehicle, motionState, geometry, localInertia));
  263. body.setActivationState(DISABLE_DEACTIVATION);
  264. physicsWorld.addRigidBody(body);
  265. var chassisMesh = createChassisMesh(chassisWidth, chassisHeight, chassisLength);
  266. // Raycast Vehicle
  267. var engineForce = 0;
  268. var vehicleSteering = 0;
  269. var breakingForce = 0;
  270. var tuning = new Ammo.btVehicleTuning();
  271. var rayCaster = new Ammo.btDefaultVehicleRaycaster(physicsWorld);
  272. var vehicle = new Ammo.btRaycastVehicle(tuning, body, rayCaster);
  273. vehicle.setCoordinateSystem(0, 1, 2);
  274. physicsWorld.addAction(vehicle);
  275. // Wheels
  276. var FRONT_LEFT = 0;
  277. var FRONT_RIGHT = 1;
  278. var BACK_LEFT = 2;
  279. var BACK_RIGHT = 3;
  280. var wheelMeshes = [];
  281. var wheelDirectionCS0 = new Ammo.btVector3(0, -1, 0);
  282. var wheelAxleCS = new Ammo.btVector3(-1, 0, 0);
  283. function addWheel(isFront, pos, radius, width, index) {
  284. var wheelInfo = vehicle.addWheel(pos, wheelDirectionCS0, wheelAxleCS, suspensionRestLength, radius, tuning, isFront);
  285. wheelInfo.set_m_suspensionStiffness(suspensionStiffness);
  286. wheelInfo.set_m_wheelsDampingRelaxation(suspensionDamping);
  287. wheelInfo.set_m_wheelsDampingCompression(suspensionCompression);
  288. wheelInfo.set_m_frictionSlip(friction);
  289. wheelInfo.set_m_rollInfluence(rollInfluence);
  290. wheelMeshes[index] = createWheelMesh(radius, width);
  291. }
  292. addWheel(
  293. true,
  294. new Ammo.btVector3(wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition),
  295. wheelRadiusFront,
  296. wheelWidthFront,
  297. FRONT_LEFT
  298. );
  299. addWheel(
  300. true,
  301. new Ammo.btVector3(-wheelHalfTrackFront, wheelAxisHeightFront, wheelAxisFrontPosition),
  302. wheelRadiusFront,
  303. wheelWidthFront,
  304. FRONT_RIGHT
  305. );
  306. addWheel(
  307. false,
  308. new Ammo.btVector3(-wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack),
  309. wheelRadiusBack,
  310. wheelWidthBack,
  311. BACK_LEFT
  312. );
  313. addWheel(
  314. false,
  315. new Ammo.btVector3(wheelHalfTrackBack, wheelAxisHeightBack, wheelAxisPositionBack),
  316. wheelRadiusBack,
  317. wheelWidthBack,
  318. BACK_RIGHT
  319. );
  320. // Sync keybord actions and physics and graphics
  321. function sync(dt) {
  322. var speed = vehicle.getCurrentSpeedKmHour();
  323. //console.log((speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h')
  324. //speedometer.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h';
  325. breakingForce = 0;
  326. engineForce = 0;
  327. if (actions.acceleration) {
  328. if (speed < -1) {
  329. breakingForce = maxBreakingForce;
  330. } else {
  331. engineForce = maxEngineForce;
  332. }
  333. }
  334. if (actions.braking) {
  335. if (speed > 1) {
  336. breakingForce = maxBreakingForce;
  337. } else {
  338. engineForce = -maxEngineForce / 2;
  339. }
  340. }
  341. if (actions.left) {
  342. if (vehicleSteering < steeringClamp) {
  343. vehicleSteering += steeringIncrement;
  344. }
  345. } else {
  346. if (actions.right) {
  347. if (vehicleSteering > -steeringClamp) {
  348. vehicleSteering -= steeringIncrement;
  349. }
  350. } else {
  351. if (vehicleSteering < -steeringIncrement) {
  352. vehicleSteering += steeringIncrement;
  353. } else {
  354. if (vehicleSteering > steeringIncrement) {
  355. vehicleSteering -= steeringIncrement;
  356. } else {
  357. vehicleSteering = 0;
  358. }
  359. }
  360. }
  361. }
  362. vehicle.applyEngineForce(engineForce, BACK_LEFT);
  363. vehicle.applyEngineForce(engineForce, BACK_RIGHT);
  364. vehicle.setBrake(breakingForce / 2, FRONT_LEFT);
  365. vehicle.setBrake(breakingForce / 2, FRONT_RIGHT);
  366. vehicle.setBrake(breakingForce, BACK_LEFT);
  367. vehicle.setBrake(breakingForce, BACK_RIGHT);
  368. vehicle.setSteeringValue(vehicleSteering, FRONT_LEFT);
  369. vehicle.setSteeringValue(vehicleSteering, FRONT_RIGHT);
  370. var tm, p, q, i;
  371. var n = vehicle.getNumWheels();
  372. for (i = 0; i < n; i++) {
  373. vehicle.updateWheelTransform(i, true);
  374. tm = vehicle.getWheelTransformWS(i);
  375. p = tm.getOrigin();
  376. q = tm.getRotation();
  377. wheelMeshes[i].position.set(p.x(), p.y(), p.z());
  378. wheelMeshes[i].quaternion.set(q.x(), q.y(), q.z(), q.w());
  379. wheelMeshes[i].modelMatrixNeedsUpdate = true;
  380. }
  381. tm = vehicle.getChassisWorldTransform();
  382. p = tm.getOrigin();
  383. q = tm.getRotation();
  384. chassisMesh.position.set(p.x(), p.y(), p.z());
  385. chassisMesh.quaternion.set(q.x(), q.y(), q.z(), q.w());
  386. chassisMesh.modelMatrixNeedsUpdate = true;
  387. }
  388. syncList.push(sync);
  389. }
  390. function createObjects() {
  391. createBox(new Cesium.Cartesian3(0, -0.5, 0), ZERO_QUATERNION, 75, 1, 75, 0, 2);
  392. var quaternion = new Cesium.Quaternion(0, 0, 0, 1);
  393. Cesium.Quaternion.fromAxisAngle(new Cesium.Cartesian3(1, 0, 0), -Math.PI / 18, quaternion);
  394. createBox(new Cesium.Cartesian3(0, -1.5, 0), quaternion, 8, 4, 10, 0);
  395. var size = 0.75;
  396. var nw = 8;
  397. var nh = 6;
  398. for (var j = 0; j < nw; j++) {
  399. for (var i = 0; i < nh; i++) {
  400. createBox(new Cesium.Cartesian3(size * j - (size * (nw - 1)) / 2, size * i, 10), ZERO_QUATERNION, size, size, size, 10);
  401. }
  402. }
  403. createVehicle(new Cesium.Cartesian3(0, 4, -20), ZERO_QUATERNION);
  404. }
  405. var start = false;
  406. var init = false;
  407. var startTime = new Date();
  408. function update(frameState) {
  409. var deltaTime = (new Date() - startTime) / 1000.0;
  410. updatePhysics(deltaTime);
  411. startTime = new Date();
  412. }
  413. setTimeout(function () {
  414. if (!init) {
  415. // - Init -
  416. initGraphics();
  417. initPhysics();
  418. createObjects();
  419. init = true;
  420. }
  421. if (!start) {
  422. meshVisualizer.beforeUpdate.addEventListener(update);
  423. start = true;
  424. } else {
  425. meshVisualizer.beforeUpdate.removeEventListener(update);
  426. start = false;
  427. }
  428. }, 1000 * 3);
  429. });
  430. }
  431. function createRandomColor() {
  432. return Cesium.Color.fromRandom({ alpha: 1 }); //fromRgba(Math.floor(Math.random() * (1 << 24)));
  433. }
  434. function createMaterial() {
  435. return new Cesium.MeshPhongMaterial({
  436. defaultColor: createRandomColor(),
  437. side: Cesium.MeshMaterial.Sides.DOUBLE,
  438. translucent: false,
  439. });
  440. }
  441. </script>
  442. </body>
  443. </html>