Cesium-Examples/examples/cesiumEx/6.1.1、车辆运动.html

603 lines
22 KiB
HTML
Raw Permalink Normal View History

2025-03-11 08:25:45 +00:00
<!--********************************************************************
* by jiawanlong
*********************************************************************-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
2025-03-19 03:00:22 +00:00
<link rel="stylesheet" href="./../../libs/cesium/Cesium1.72/Widgets/widgets.css" />
<script type="text/javascript" src="./../../libs/cesium/Cesium1.72/Cesium.js"></script>
2025-03-11 08:25:45 +00:00
<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 =
2025-06-07 11:30:00 +00:00
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyMjBhMzcxMC0wNjBiLTRmYjItYjY1MC0wMzAwMzMyMGUyMmEiLCJpZCI6MzAzNzc3LCJpYXQiOjE3NDc2Mzk0NTV9.E_90aKtVdzRGlU2z48VwJ4mWvl-uuDkfQBCOO6zbzn4";
2025-03-11 08:25:45 +00:00
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>