I’m trying to set the camera to the modelMatrix of a model primitive
that was created from a loaded czml so that the camera will be fixed relative to the 3D model. I tried a bunch of things and tested the
concept with the following sandcastle example but this uses a model fromGltf and doesn’t seem to work when I use my czml.
Example of desired behavior:
var viewer = new Cesium.Viewer(‘cesiumContainer’);
var scene = viewer.scene;
var degreesToRadians = function(val) {
return val*Math.PI/180;
}
var lon = -60;
var lat = -52;
var alt = 100;
var heading = 0;
var pitch = 0;
var roll = 0;
var primitives = scene.primitives;
var ellipsoid = viewer.scene.globe.ellipsoid;
var positionModel = function(model, lon, lat, alt, heading, pitch, roll) {
var point = Cesium.Cartographic.fromDegrees(lon, lat, alt / 3);
var epoint = ellipsoid.cartographicToCartesian(point);
var heading = degreesToRadians((heading));
var pitch = degreesToRadians(pitch);
var roll = degreesToRadians(roll);
var currentTranslation = new Cesium.Cartesian3();
var currentRotation = new Cesium.Matrix3();
var eastNorthUp = Cesium.Transforms.eastNorthUpToFixedFrame(epoint);
var p = new Cesium.Cartesian3(lon, lat, alt);
Cesium.Matrix4.getRotation(eastNorthUp, currentRotation);
Cesium.Matrix4.getTranslation(eastNorthUp, currentTranslation);
var headingQuaternion = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, -heading);
var pitchQuaternion = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Y, -pitch);
var rollQuaternion = Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_X, -roll);
var headingPitchQuaternion = Cesium.Quaternion.multiply(headingQuaternion, pitchQuaternion, new Cesium.Quaternion());
var finalQuaternion = new Cesium.Quaternion();
Cesium.Quaternion.multiply(headingPitchQuaternion, rollQuaternion, finalQuaternion);
var rM = new Cesium.Matrix3();
Cesium.Matrix3.fromQuaternion(finalQuaternion, rM);
Cesium.Matrix3.multiply(currentRotation, rM, currentRotation);
var modelMatrix = new Cesium.Matrix4();
Cesium.Matrix4.fromRotationTranslation(
currentRotation,
currentTranslation,
modelMatrix
);
model.modelMatrix = modelMatrix;
};
var positionCamera = function(model) {
var camera = scene.camera;
camera.lookAtTransform(model.modelMatrix, new Cesium.Cartesian3(-25,0,10))
var controller = scene.screenSpaceCameraController;
var r = 2.0 * Math.max(model.boundingSphere.radius, camera.frustum.near);
controller.minimumZoomDistance = r * 0.5;
};
var createModel = function(lon, lat, alt, heading, pitch, roll) {
var model = scene.primitives.add(Cesium.Model.fromGltf({
url : ‘…/…/SampleData/models/CesiumAir/Cesium_Air.gltf’
}));
model.readyToRender.addEventListener(function(model) {
model.activeAnimations.addAll({
speedup : 1,
loop : Cesium.ModelAnimationLoop.REPEAT
});
viewer.clock.onTick.addEventListener(function() {
positionModel(model, lon, lat, alt, heading, pitch, roll);
positionCamera(model);
heading += 0.01;
pitch += 0.05;
roll += 0.1;
});
});
};
createModel(lon, lat, alt, heading, pitch, roll);
``
Now, here is my attempt from the loaded czml which kind of works but as the
camera is tracking the moving entity there is a lot of jittering of the camera
about the entity. I also tried to use just the model.modelMatrix instead of the _modelMatrix but I kept ending up inside the Earth. Any ideas what I’m doing wrong? I can provide an actual sandcastle example if needed.
czmlDataSource.processUrl("…/test.czml");
function findPrimitive(entity) {
var id = entity.id;
for (var i = 0; i < scene.primitives.length; i++) {
var primitive = scene.primitives.get(i);
if (primitive.hasOwnProperty(‘id’)){
if (primitive.id.id == id) {
return primitive;
}
}
}
}
function cameraBodyAxes(entity) {
var primitive = findPrimitive(entity);
viewer.clock.onTick.addEventListener(function() {
camera.lookAtTransform(primitive._modelMatrix, new Cesium.Cartesian3(-20, 0, 8));
});
}
cameraBodyAxes(czmlDataSource.entities.values[0]);