Cesium-Examples/examples/cesiumEx/6.1.1、车辆运动.html
2025-06-12 14:10:21 +08:00

603 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--********************************************************************
* 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>
<!-- 操作提示W 前进、S 后退、 A 左转弯、D 右转弯 -->
<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, 100]; //初始位置
look(homePosition[0], homePosition[1], homePosition[2]);
viewer.scene.debugShowFramesPerSecond = true; //查看帧率
var center = Cesium.Cartesian3.fromDegrees(
homePosition[0],
homePosition[1],
10
);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);
var meshVisualizer = new Cesium.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; //显示坐标轴
Cesium.Cartesian3.prototype.set = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
Cesium.Quaternion.prototype.set = function (x, y, z, w) {
this.x = x;
this.y = y;
this.z = z;
this.w = w;
};
Ammo().then(function () {
// - Global variables -
var DISABLE_DEACTIVATION = 4;
var TRANSFORM_AUX = new Ammo.btTransform();
var ZERO_QUATERNION = new Cesium.Quaternion(0, 0, 0, 1);
// Graphics variables
var materialDynamic, materialStatic, materialInteractive;
// Physics variables
var collisionConfiguration;
var dispatcher;
var broadphase;
var solver;
var physicsWorld;
var syncList = [];
var time = 0;
var objectTimePeriod = 3;
var timeNextSpawn = time + objectTimePeriod;
var maxNumObjects = 30;
// Keybord actions
var actions = {};
var keysActions = {
KeyW: "acceleration",
KeyS: "braking",
KeyA: "left",
KeyD: "right",
};
// - Functions -
function initGraphics() {
materialDynamic = createMaterial();
materialStatic = createMaterial();
materialInteractive = createMaterial();
top.window.addEventListener("keydown", keydown);
top.window.addEventListener("keyup", keyup);
}
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, -9.82, 0));
}
function updatePhysics(deltTime) {
for (var i = 0; i < syncList.length; i++) syncList[i](deltTime);
physicsWorld.stepSimulation(deltTime, 10);
time += deltTime;
}
function keyup(e) {
if (keysActions[e.code]) {
actions[keysActions[e.code]] = false;
e.preventDefault();
e.stopPropagation();
return false;
}
}
function keydown(e) {
if (keysActions[e.code]) {
actions[keysActions[e.code]] = true;
e.preventDefault();
e.stopPropagation();
return false;
}
}
//创建立方体盒子
function createBox(pos, quat, w, l, h, mass, friction) {
var material = createMaterial(); //= mass > 0 ? materialDynamic : materialStatic;
var shape = Cesium.BoxGeometry.fromDimensions({
dimensions: new Cesium.Cartesian3(w, l, h),
vertexFormat: new Cesium.VertexFormat({
position: true,
normal: true,
}),
});
var geometry = new Ammo.btBoxShape(
new Ammo.btVector3(w * 0.5, l * 0.5, h * 0.5)
);
if (!mass) mass = 0;
if (!friction) friction = 1;
var mesh = new Cesium.Mesh(shape, material);
Cesium.Cartesian3.clone(pos, mesh.position);
mesh.quaternion = new Cesium.Quaternion(
quat.x,
quat.y,
quat.z,
quat.w
);
meshVisualizer.add(mesh);
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);
geometry.calculateLocalInertia(mass, localInertia);
var rbInfo = new Ammo.btRigidBodyConstructionInfo(
mass,
motionState,
geometry,
localInertia
);
var body = new Ammo.btRigidBody(rbInfo);
body.setFriction(friction);
//body.setRestitution(.9);
//body.setDamping(0.2, 0.2);
physicsWorld.addRigidBody(body);
if (mass > 0) {
body.setActivationState(DISABLE_DEACTIVATION);
// Sync physics and graphics
function sync(dt) {
var ms = body.getMotionState();
if (ms) {
ms.getWorldTransform(TRANSFORM_AUX);
var p = TRANSFORM_AUX.getOrigin();
var q = TRANSFORM_AUX.getRotation();
mesh.position.set(p.x(), p.y(), p.z());
mesh.quaternion.set(q.x(), q.y(), q.z(), q.w());
mesh.modelMatrixNeedsUpdate = true;
}
}
syncList.push(sync);
}
}
//创建车轮
function createWheelMesh(radius, width) {
var t = new Cesium.CylinderGeometry({
length: width,
topRadius: radius,
bottomRadius: radius,
slices: 24,
});
//var t = new THREE.CylinderGeometry(radius, radius, width, 24, 1);
var mesh = new Cesium.Mesh(t, materialInteractive);
Cesium.GeometryUtils.rotateY(mesh.geometry, Math.PI / 2);
mesh.quaternion = new Cesium.Quaternion(); // Cesium.Quaternion.fromAxisAngle(new Cesium.Cartesian3(0, 0, 1), Math.PI / 2);
var shape = Cesium.BoxGeometry.fromDimensions({
dimensions: new Cesium.Cartesian3(
width * 1.5,
radius * 1.75,
radius * 0.25
),
vertexFormat: new Cesium.VertexFormat({
position: true,
normal: true,
}),
});
var meshShape = new Cesium.Mesh(shape, materialInteractive);
meshShape.quaternion = new Cesium.Quaternion(); //.fromAxisAngle(new Cesium.Cartesian3(0, 0, 1), 0);
mesh.add(meshShape);
meshVisualizer.add(mesh);
return mesh;
}
//创建车体
function createChassisMesh(w, l, h) {
var shape = Cesium.BoxGeometry.fromDimensions({
dimensions: new Cesium.Cartesian3(w, l, h),
vertexFormat: new Cesium.VertexFormat({
position: true,
normal: true,
}),
});
var mesh = new Cesium.Mesh(shape, materialInteractive);
mesh.quaternion = new Cesium.Quaternion(0, 0, 0, 1);
meshVisualizer.add(mesh);
return mesh;
}
//创建小车
function createVehicle(pos, quat) {
// Vehicle contants
var chassisWidth = 1.8;
var chassisHeight = 0.6;
var chassisLength = 4;
var massVehicle = 800;
var wheelAxisPositionBack = -1;
var wheelRadiusBack = 0.4;
var wheelWidthBack = 0.3;
var wheelHalfTrackBack = 1;
var wheelAxisHeightBack = 0.3;
var wheelAxisFrontPosition = 1.7;
var wheelHalfTrackFront = 1;
var wheelAxisHeightFront = 0.3;
var wheelRadiusFront = 0.35;
var wheelWidthFront = 0.2;
var friction = 1000;
var suspensionStiffness = 20.0;
var suspensionDamping = 2.3;
var suspensionCompression = 4.4;
var suspensionRestLength = 0.6;
var rollInfluence = 0.2;
var steeringIncrement = 0.04;
var steeringClamp = 0.5;
var maxEngineForce = 2000;
var maxBreakingForce = 100;
// Chassis
var geometry = new Ammo.btBoxShape(
new Ammo.btVector3(
chassisWidth * 0.5,
chassisHeight * 0.5,
chassisLength * 0.5
)
);
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);
geometry.calculateLocalInertia(massVehicle, localInertia);
var body = new Ammo.btRigidBody(
new Ammo.btRigidBodyConstructionInfo(
massVehicle,
motionState,
geometry,
localInertia
)
);
body.setActivationState(DISABLE_DEACTIVATION);
physicsWorld.addRigidBody(body);
var chassisMesh = createChassisMesh(
chassisWidth,
chassisHeight,
chassisLength
);
// Raycast Vehicle
var engineForce = 0;
var vehicleSteering = 0;
var breakingForce = 0;
var tuning = new Ammo.btVehicleTuning();
var rayCaster = new Ammo.btDefaultVehicleRaycaster(physicsWorld);
var vehicle = new Ammo.btRaycastVehicle(tuning, body, rayCaster);
vehicle.setCoordinateSystem(0, 1, 2);
physicsWorld.addAction(vehicle);
// Wheels
var FRONT_LEFT = 0;
var FRONT_RIGHT = 1;
var BACK_LEFT = 2;
var BACK_RIGHT = 3;
var wheelMeshes = [];
var wheelDirectionCS0 = new Ammo.btVector3(0, -1, 0);
var wheelAxleCS = new Ammo.btVector3(-1, 0, 0);
//添加轮子
function addWheel(isFront, pos, radius, width, index) {
var wheelInfo = vehicle.addWheel(
pos,
wheelDirectionCS0,
wheelAxleCS,
suspensionRestLength,
radius,
tuning,
isFront
);
wheelInfo.set_m_suspensionStiffness(suspensionStiffness);
wheelInfo.set_m_wheelsDampingRelaxation(suspensionDamping);
wheelInfo.set_m_wheelsDampingCompression(suspensionCompression);
wheelInfo.set_m_frictionSlip(friction);
wheelInfo.set_m_rollInfluence(rollInfluence);
wheelMeshes[index] = createWheelMesh(radius, width);
}
addWheel(
true,
new Ammo.btVector3(
wheelHalfTrackFront,
wheelAxisHeightFront,
wheelAxisFrontPosition
),
wheelRadiusFront,
wheelWidthFront,
FRONT_LEFT
);
addWheel(
true,
new Ammo.btVector3(
-wheelHalfTrackFront,
wheelAxisHeightFront,
wheelAxisFrontPosition
),
wheelRadiusFront,
wheelWidthFront,
FRONT_RIGHT
);
addWheel(
false,
new Ammo.btVector3(
-wheelHalfTrackBack,
wheelAxisHeightBack,
wheelAxisPositionBack
),
wheelRadiusBack,
wheelWidthBack,
BACK_LEFT
);
addWheel(
false,
new Ammo.btVector3(
wheelHalfTrackBack,
wheelAxisHeightBack,
wheelAxisPositionBack
),
wheelRadiusBack,
wheelWidthBack,
BACK_RIGHT
);
// Sync keybord actions and physics and graphics
function sync(dt) {
var speed = vehicle.getCurrentSpeedKmHour();
//console.log((speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h')
//speedometer.innerHTML = (speed < 0 ? '(R) ' : '') + Math.abs(speed).toFixed(1) + ' km/h';
breakingForce = 0;
engineForce = 0;
if (actions.acceleration) {
if (speed < -1) breakingForce = maxBreakingForce;
else engineForce = maxEngineForce;
}
if (actions.braking) {
if (speed > 1) breakingForce = maxBreakingForce;
else engineForce = -maxEngineForce / 2;
}
if (actions.left) {
if (vehicleSteering < steeringClamp)
vehicleSteering += steeringIncrement;
} else {
if (actions.right) {
if (vehicleSteering > -steeringClamp)
vehicleSteering -= steeringIncrement;
} else {
if (vehicleSteering < -steeringIncrement)
vehicleSteering += steeringIncrement;
else {
if (vehicleSteering > steeringIncrement)
vehicleSteering -= steeringIncrement;
else {
vehicleSteering = 0;
}
}
}
}
vehicle.applyEngineForce(engineForce, BACK_LEFT);
vehicle.applyEngineForce(engineForce, BACK_RIGHT);
vehicle.setBrake(breakingForce / 2, FRONT_LEFT);
vehicle.setBrake(breakingForce / 2, FRONT_RIGHT);
vehicle.setBrake(breakingForce, BACK_LEFT);
vehicle.setBrake(breakingForce, BACK_RIGHT);
vehicle.setSteeringValue(vehicleSteering, FRONT_LEFT);
vehicle.setSteeringValue(vehicleSteering, FRONT_RIGHT);
var tm, p, q, i;
var n = vehicle.getNumWheels();
for (i = 0; i < n; i++) {
vehicle.updateWheelTransform(i, true);
tm = vehicle.getWheelTransformWS(i);
p = tm.getOrigin();
q = tm.getRotation();
wheelMeshes[i].position.set(p.x(), p.y(), p.z());
wheelMeshes[i].quaternion.set(q.x(), q.y(), q.z(), q.w());
wheelMeshes[i].modelMatrixNeedsUpdate = true;
}
tm = vehicle.getChassisWorldTransform();
p = tm.getOrigin();
q = tm.getRotation();
chassisMesh.position.set(p.x(), p.y(), p.z());
chassisMesh.quaternion.set(q.x(), q.y(), q.z(), q.w());
chassisMesh.modelMatrixNeedsUpdate = true;
}
syncList.push(sync);
}
function createObjects() {
//创建平台
createBox(
new Cesium.Cartesian3(0, -0.5, 0),
ZERO_QUATERNION,
75,
1,
75,
0,
2
);
//创建坡道
var quaternion = new Cesium.Quaternion(0, 0, 0, 1);
Cesium.Quaternion.fromAxisAngle(
new Cesium.Cartesian3(1, 0, 0),
-Math.PI / 18,
quaternion
);
createBox(new Cesium.Cartesian3(0, -1.5, 0), quaternion, 8, 4, 10, 0);
//创建马赛克墙
var size = 0.75;
var nw = 8;
var nh = 6;
for (var j = 0; j < nw; j++)
for (var i = 0; i < nh; i++)
createBox(
new Cesium.Cartesian3(
size * j - (size * (nw - 1)) / 2,
size * i,
10
),
ZERO_QUATERNION,
size,
size,
size,
10
);
//创建小车
createVehicle(new Cesium.Cartesian3(0, 4, -20), ZERO_QUATERNION);
}
var start = false;
var init = false;
var startTime = new Date();
function update(frameState) {
var deltaTime = (new Date() - startTime) / 1000.0;
updatePhysics(deltaTime);
startTime = new Date();
}
setTimeout(function () {
if (!init) {
// - Init -
initGraphics();
initPhysics();
createObjects();
init = true;
}
if (!start) {
meshVisualizer.beforeUpdate.addEventListener(update);
start = true;
} else {
meshVisualizer.beforeUpdate.removeEventListener(update);
start = false;
}
}, 1000 * 3);
});
function createRandomColor() {
return Cesium.Color.fromRandom({
alpha: 1,
}); //fromRgba(Math.floor(Math.random() * (1 << 24)));
}
function createMaterial() {
return new Cesium.MeshPhongMaterial({
defaultColor: createRandomColor(),
side: Cesium.MeshMaterial.Sides.DOUBLE,
translucent: false,
});
}
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>