Skip to content

Commit

Permalink
Merge pull request #7907 from AnalyticalGraphicsInc/entity-articulations
Browse files Browse the repository at this point in the history
CZML and Entity articulations API
  • Loading branch information
shunter authored Jun 11, 2019
2 parents 0c0307a + 6e8789b commit 4d86826
Show file tree
Hide file tree
Showing 10 changed files with 336 additions and 7 deletions.
107 changes: 107 additions & 0 deletions Apps/Sandcastle/gallery/CZML Model Articulations.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="CZML Model Articulations">
<meta name="cesium-sandcastle-labels" content="CZML">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
if(typeof require === 'function') {
require.config({
baseUrl : '../../../Source',
waitSeconds : 120
});
}
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>

<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var czml = [{
"id" : "document",
"name" : "CZML Model",
"version" : "1.0",
"clock" : {
"interval" : "2019-06-01T16:00:00Z/2019-06-01T16:10:00Z",
"currentTime" : "2019-06-01T16:00:00Z",
"multiplier" : 60,
"range" : "LOOP_STOP",
"step" : "SYSTEM_CLOCK_MULTIPLIER"
}
}, {
"id" : "test model",
"name" : "Cesium Air",
"position" : {
"cartographicDegrees" : [-77, 37, 10000]
},
"model": {
"gltf" : "https://assets.agi.com/models/launchvehicle.glb",
"scale" : 2.0,
"minimumPixelSize" : 128,
"runAnimations" : false,
"articulations" : {
"Fairing Open" : {
"epoch" : "2019-06-01T16:00:00Z",
"number" : [
0, 0,
600, 120
]
},
"Fairing Separate" : {
"epoch" : "2019-06-01T16:00:00Z",
"number" : [
0, 0,
400, -50
]
},
"Fairing Drop" : {
"epoch" : "2019-06-01T16:00:00Z",
"interpolationAlgorithm" : "LAGRANGE",
"interpolationDegree" : 2,
"number" : [
0, 0,
80, 0,
100, 0,
120, -1,
600, -120
]
}
}
}
}];

var viewer = new Cesium.Viewer('cesiumContainer', {
shouldAnimate : true
});

var dataSourcePromise = viewer.dataSources.add(Cesium.CzmlDataSource.load(czml));

dataSourcePromise.then(function(dataSource){
viewer.trackedEntity = dataSource.entities.getById('test model');
}).otherwise(function(error){
console.error(error);
});
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== 'undefined') {
startup(Cesium);
} else if (typeof require === 'function') {
require(['Cesium'], startup);
}
</script>
</body>
</html>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ Change Log

### 1.59 - 2019-07-01

##### Additions :tada:
* Added support for the [AGI_articulations](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/AGI_articulations) vendor extension of glTF 2.0 to the Entity API and CZML. [#7907](https://github.com/AnalyticalGraphicsInc/cesium/pull/7907)

##### Fixes :wrench:
* Fixed a bug that caused missing segments for ground polylines with coplanar points over large distances and problems with polylines containing duplicate points. [#7885](https://github.com/AnalyticalGraphicsInc/cesium//pull/7885)
* Fixed a bug where billboards were not pickable when zoomed out completely in 2D View. [#7908](https://github.com/AnalyticalGraphicsInc/cesium/pull/7908)
Expand Down
54 changes: 53 additions & 1 deletion Source/DataSources/CzmlDataSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -1713,16 +1713,28 @@ define([
processPacketData(Number, model, 'colorBlendAmount', modelData.colorBlendAmount, interval, sourceUri, entityCollection);
processPacketData(DistanceDisplayCondition, model, 'distanceDisplayCondition', modelData.distanceDisplayCondition, interval, sourceUri, entityCollection);

var i, len;
var nodeTransformationsData = modelData.nodeTransformations;
if (defined(nodeTransformationsData)) {
if (isArray(nodeTransformationsData)) {
for (var i = 0, len = nodeTransformationsData.length; i < len; i++) {
for (i = 0, len = nodeTransformationsData.length; i < len; i++) {
processNodeTransformations(model, nodeTransformationsData[i], interval, sourceUri, entityCollection);
}
} else {
processNodeTransformations(model, nodeTransformationsData, interval, sourceUri, entityCollection);
}
}

var articulationsData = modelData.articulations;
if (defined(articulationsData)) {
if (isArray(articulationsData)) {
for (i = 0, len = articulationsData.length; i < len; i++) {
processArticulations(model, articulationsData[i], interval, sourceUri, entityCollection);
}
} else {
processArticulations(model, articulationsData, interval, sourceUri, entityCollection);
}
}
}

function processNodeTransformations(model, nodeTransformationsData, constrainedInterval, sourceUri, entityCollection) {
Expand Down Expand Up @@ -1772,6 +1784,46 @@ define([
}
}

function processArticulations(model, articulationsData, constrainedInterval, sourceUri, entityCollection) {
var combinedInterval;
var packetInterval = articulationsData.interval;
if (defined(packetInterval)) {
iso8601Scratch.iso8601 = packetInterval;
combinedInterval = TimeInterval.fromIso8601(iso8601Scratch);
if (defined(constrainedInterval)) {
combinedInterval = TimeInterval.intersect(combinedInterval, constrainedInterval, scratchTimeInterval);
}
} else if (defined(constrainedInterval)) {
combinedInterval = constrainedInterval;
}

var articulations = model.articulations;
var keys = Object.keys(articulationsData);
for (var i = 0, len = keys.length; i < len; ++i) {
var key = keys[i];

if (key === 'interval') {
continue;
}

var articulationStageData = articulationsData[key];

if (!defined(articulationStageData)) {
continue;
}

if (!defined(articulations)) {
model.articulations = articulations = new PropertyBag();
}

if (!articulations.hasProperty(key)) {
articulations.addProperty(key);
}

processPacketData(Number, articulations, key, articulationStageData, combinedInterval, sourceUri, entityCollection);
}
}

function processPath(entity, packet, entityCollection, sourceUri) {
var pathData = packet.path;
if (!defined(pathData)) {
Expand Down
26 changes: 26 additions & 0 deletions Source/DataSources/ModelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ define([
return new PropertyBag(value, createNodeTransformationProperty);
}

function createArticulationStagePropertyBag(value) {
return new PropertyBag(value);
}

/**
* A 3D model based on {@link https://github.com/KhronosGroup/glTF|glTF}, the runtime asset format for WebGL, OpenGL ES, and OpenGL.
* The position and orientation of the model is determined by the containing {@link Entity}.
Expand All @@ -47,6 +51,7 @@ define([
* @param {Property} [options.runAnimations=true] A boolean Property specifying if glTF animations specified in the model should be started.
* @param {Property} [options.clampAnimations=true] A boolean Property specifying if glTF animations should hold the last pose for time durations with no keyframes.
* @param {PropertyBag} [options.nodeTransformations] An object, where keys are names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node. The transformation is applied after the node's existing transformation as specified in the glTF, and does not replace the node's existing transformation.
* @param {PropertyBag} [options.articulations] An object, where keys are composed of an articulation name, a single space, and a stage name, and the values are numeric properties.
* @param {Property} [options.shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from each light source.
* @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to.
* @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this model will be displayed.
Expand Down Expand Up @@ -82,6 +87,8 @@ define([
this._runAnimationsSubscription = undefined;
this._nodeTransformations = undefined;
this._nodeTransformationsSubscription = undefined;
this._articulations = undefined;
this._articulationsSubscription = undefined;
this._heightReference = undefined;
this._heightReferenceSubscription = undefined;
this._distanceDisplayCondition = undefined;
Expand Down Expand Up @@ -207,6 +214,14 @@ define([
*/
nodeTransformations : createPropertyDescriptor('nodeTransformations', undefined, createNodeTransformationPropertyBag),

/**
* Gets or sets the set of articulation values to apply to this model. This is represented as an {@link PropertyBag}, where keys are
* composed as the name of the articulation, a single space, and the name of the stage.
* @memberof ModelGraphics.prototype
* @type {PropertyBag}
*/
articulations : createPropertyDescriptor('articulations', undefined, createArticulationStagePropertyBag),

/**
* Gets or sets the Property specifying the {@link HeightReference}.
* @memberof ModelGraphics.prototype
Expand Down Expand Up @@ -306,6 +321,7 @@ define([
result.runAnimations = this.runAnimations;
result.clampAnimations = this.clampAnimations;
result.nodeTransformations = this.nodeTransformations;
result.articulations = this.articulations;
result.heightReference = this._heightReference;
result.distanceDisplayCondition = this.distanceDisplayCondition;
result.silhouetteColor = this.silhouetteColor;
Expand Down Expand Up @@ -362,6 +378,16 @@ define([
this.nodeTransformations = new PropertyBag(sourceNodeTransformations, createNodeTransformationProperty);
}
}

var sourceArticulations = source.articulations;
if (defined(sourceArticulations)) {
var targetArticulations = this.articulations;
if (defined(targetArticulations)) {
targetArticulations.merge(sourceArticulations);
} else {
this.articulations = new PropertyBag(sourceArticulations);
}
}
};

return ModelGraphics;
Expand Down
28 changes: 26 additions & 2 deletions Source/DataSources/ModelVisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ define([
url : resource.url,
animationsRunning : false,
nodeTransformationsScratch : {},
articulationsScratch : {},
loadFail : false
};
modelHash[entity.id] = modelData;
Expand Down Expand Up @@ -196,6 +197,28 @@ define([
modelNode.matrix = Matrix4.multiply(modelNode.originalMatrix, transformationMatrix, transformationMatrix);
}
}

// Apply articulations
var anyArticulationUpdated = false;
var articulations = Property.getValueOrUndefined(modelGraphics._articulations, time, modelData.articulationsScratch);
if (defined(articulations)) {
var articulationStageKeys = Object.keys(articulations);
for (var s = 0, numKeys = articulationStageKeys.length; s < numKeys; ++s) {
var key = articulationStageKeys[s];

var articulationStageValue = articulations[key];
if (!defined(articulationStageValue)) {
continue;
}

anyArticulationUpdated = true;
model.setArticulationStage(key, articulationStageValue);
}
}

if (anyArticulationUpdated) {
model.applyArticulations();
}
}
}

Expand Down Expand Up @@ -291,7 +314,7 @@ define([
for (i = changed.length - 1; i > -1; i--) {
entity = changed[i];
if (defined(entity._model) && defined(entity._position)) {
clearNodeTransformationsScratch(entity, modelHash);
clearNodeTransformationsArticulationsScratch(entity, modelHash);
entities.set(entity.id, entity);
} else {
removeModel(this, entity, modelHash, primitives);
Expand All @@ -314,10 +337,11 @@ define([
}
}

function clearNodeTransformationsScratch(entity, modelHash) {
function clearNodeTransformationsArticulationsScratch(entity, modelHash) {
var modelData = modelHash[entity.id];
if (defined(modelData)) {
modelData.nodeTransformationsScratch = {};
modelData.articulationsScratch = {};
}
}

Expand Down
1 change: 1 addition & 0 deletions Specs/Data/Models/Box-Articulations/Box-Articulations.gltf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
}
},
{
"name": "Mesh",
"mesh": 0
}
],
Expand Down
Loading

0 comments on commit 4d86826

Please sign in to comment.