Merge remote-tracking branch 'upstream/master' into fastPickingWithOctree

This commit is contained in:
Daniel Leone 2021-04-24 12:00:54 +08:00
commit e195558d9d
60 changed files with 4485 additions and 212 deletions

View File

@ -1,5 +1,5 @@
{
"contributorsPath": "CONTRIBUTORS.md",
"unitTestPath" : "Specs/",
"maxDaysSinceUpdate": 30
"maxDaysSinceUpdate": 90
}

View File

@ -6,7 +6,7 @@ about: Let us know so we can fix it!
<!--
Thanks for helping us improve Cesium! Please describe what the expected behavior is vs what actually happens.
Creating a Sandcastle example (https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/) that reproduces the issue helps us a lot in tracking down bugs. Paste the link you get from the "Share" button in Sandcastle below.
Creating a Sandcastle example (https://sandcastle.cesium.com) that reproduces the issue helps us a lot in tracking down bugs. Paste the link you get from the "Share" button in Sandcastle below.
-->
Sandcastle example:

View File

@ -3,9 +3,9 @@ releaseSchedule:
- gary, 1/4/2021
- ian, 2/1/2021
- kevin, 3/1/2021
- sam.vargas, 4/1/2021
- hpinkos, 4/1/2021
- mamato, 5/3/2021
- oshehata, 6/1/2021
- sam.vargas, 6/1/2021
- bao, 7/1/2021
- lilleyse, 8/2/2021
- sam.suhag, 9/1/2021

View File

@ -32,26 +32,13 @@
function startup(Cesium) {
"use strict";
//Sandcastle_Begin
var viewer = new Cesium.Viewer("cesiumContainer");
// Add an ArcGIS MapServer imagery layer
var imageryLayers = viewer.imageryLayers;
imageryLayers.addImageryProvider(
new Cesium.ArcGisMapServerImageryProvider({
var viewer = new Cesium.Viewer("cesiumContainer", {
imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
url:
"https://nationalmap.gov.au/proxy/http://services.ga.gov.au/site_3/rest/services/Electricity_Infrastructure/MapServer",
})
);
// Start off looking at Australia.
viewer.camera.setView({
destination: Cesium.Rectangle.fromDegrees(
114.591,
-45.837,
148.97,
-5.73
),
}); //Sandcastle_End
"https://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer/",
}),
});
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -97,7 +97,7 @@
var innerCoreRadius = 1250000;
var outerCoreRadius = 3450000;
var mantleRadius = 6350000.0;
var mantleRadius = 6300000.0;
var innerCore = viewer.entities.add({
name: "Inner Core",

View File

@ -66,7 +66,7 @@
}
var environmentMapURL =
"https://cesium.com/assets/kiara_6_afternoon_2k_ibl.ktx";
"https://cesium.com/public/SandcastleSampleData/kiara_6_afternoon_2k_ibl.ktx";
var modelURL = "../../SampleData/models/Pawns/Pawns.glb";
// This environment map was processed using Google's Filament project. To process your own:

View File

@ -38,17 +38,17 @@
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<video id="trailer" muted autoplay loop crossorigin controls>
<video id="trailer" muted="" autoplay="" loop="" crossorigin="" controls="">
<source
src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.webm"
src="https://cesium.com/public/SandcastleSampleData/big-buck-bunny_trailer.webm"
type="video/webm"
/>
<source
src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.mp4"
src="https://cesium.com/public/SandcastleSampleData/big-buck-bunny_trailer.mp4"
type="video/mp4"
/>
<source
src="https://sandcastle.cesium.com/SampleData/videos/big-buck-bunny_trailer.mov"
src="https://cesium.com/public/SandcastleSampleData/big-buck-bunny_trailer.mov"
type="video/quicktime"
/>
Your browser does not support the <code>video</code> element.

View File

@ -8,6 +8,26 @@
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
/>
<title>Cesium Sandcastle</title>
<link
rel="icon"
type="image/svg+xml"
href="https://cesium.com/cesium-logomark.svg"
/>
<link
rel="icon"
type="image/png"
sizes="192x192"
href="https://cesium.com/cesium-logomark-192.png"
/>
<link
rel="apple-touch-icon"
href="https://cesium.com/cesium-logomark-192.png"
/>
<link
rel="mask-icon"
href="https://cesium.com/cesium-logomark-mask.svg"
color="rgb(15,98,105)"
/>
<link
rel="stylesheet"
href="../../ThirdParty/codemirror-5.52.0/lib/codemirror.css"
@ -52,10 +72,7 @@
property="og:url"
content="https://sandcastle.cesium.com/index.html"
/>
<meta
property="og:image"
content="https://cesium.com/images/social-card.jpg"
/>
<meta property="og:image" content="https://cesium.com/social-card.jpg" />
<meta property="og:site_name" content="Cesium" />
<meta property="fb:admins" content="1222088662,1322006496" />
</head>

View File

@ -1,16 +1,24 @@
# Change Log
### 1.81 - 2021-05-01
##### Deprecated :hourglass_flowing_sand:
- `loadCRN` has been deprecated and will be removed in CesiumJS 1.82. It will be replaced with support for KTX2. [#9478](https://github.com/CesiumGS/cesium/pull/9478)
- `loadKTX` has been deprecated and will be removed in CesiumJS 1.82. It will be replaced with support for KTX2. [#9478](https://github.com/CesiumGS/cesium/pull/9478)
### 1.80 - 2021-04-01
##### Additions :tada:
- Added `Cesium3DTileset.pickPrimitive` for rendering primitives instead of the tileset during the pick pass.
- Added support for drawing ground primitives on translucent 3D Tiles. [#9399](https://github.com/CesiumGS/cesium/pull/9399)
### 1.79.1 - 2021-03-01
##### Fixes :wrench:
- Fixed a regression in 1.79 that broke terrain exaggeration. [#9397](https://github.com/CesiumGS/cesium/pull/9397)
- Fixed an issue where interpolating certain small rhumblines with surface distance 0.0 would not return the expected result. [#9430](https://github.com/CesiumGS/cesium/pull/9430)
### 1.79 - 2021-03-01

View File

@ -29,7 +29,7 @@ In addition to contributing core CesiumJS code, we appreciate many types of cont
- Being active on the [Cesium community forum](https://community.cesium.com/) by answering questions and providing input on Cesium's direction.
- Showcasing your Cesium apps on [Cesium blog](https://cesium.com/blog/categories/userstories/). Contact us at hello@cesium.com.
- Writing tutorials, creating examples, and improving the reference documentation. See the issues labeled [doc](https://github.com/CesiumGS/cesium/labels/doc).
- Writing tutorials, creating examples, and improving the reference documentation. See the issues labeled [category - doc](https://github.com/CesiumGS/cesium/labels/category%20-%20doc).
- Submitting issues as [described above](#submitting-an-issue).
- Triaging issues. Browse the [issues](https://github.com/CesiumGS/cesium/issues) and comment on issues that are no longer reproducible or on issues which you have additional information.
- Creating ecosystem projects for [glTF](https://github.com/KhronosGroup/glTF/issues/456), [CZML](https://github.com/CesiumGS/cesium/wiki/CZML-Guide), and [3D Tiles](https://github.com/CesiumGS/3d-tiles).
@ -37,7 +37,7 @@ In addition to contributing core CesiumJS code, we appreciate many types of cont
For ideas for CesiumJS code contributions, see:
- issues labeled [`good first issue`](https://github.com/CesiumGS/cesium/labels/good%20first%20issue) and
- issues labeled [`roadmap`](https://github.com/CesiumGS/cesium/labels/roadmap).
- issues labeled [`type - roadmap`](https://github.com/CesiumGS/cesium/labels/type%20-%20roadmap).
See the [Build Guide](Documentation/Contributors/BuildGuide/README.md) for how to build and run Cesium on your system.

View File

@ -285,3 +285,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute to Cesiu
- [Will Jadkowski](https://github.com/willjad)
- [Mac Clayton](https://github.com/mclayton7)
- [Ben Murphy](https://github.com/littlemurph)
- [Ethan Wong](https://github.com/GetToSet)

View File

@ -50,8 +50,8 @@ npm start
Then browse to [http://localhost:8080/](http://localhost:8080/). The landing page includes apps and tools commonly used during development, including:
- **Hello World** : an example using the combined and minified Cesium library to create a 3D globe. [Tutorial here](http://cesiumjs.org/tutorials/cesium-up-and-running/)
- **Sandcastle** : an app for viewing and creating [code examples](https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Hello%20World.html&label=Showcases), complete with a live preview
- **Hello World** : an example for how to create a 3D globe. [Tutorial here](https://cesium.com/docs/tutorials/quick-start//)
- **Sandcastle** : an app for viewing and creating [code examples](https://sandcastle.cesium.com?src=Hello%20World.html&label=Showcases), complete with a live preview
- **Test Suites** : tests using [Jasmine](https://jasmine.github.io/). [Testing guide here.](https://github.com/CesiumGS/cesium/blob/master/Documentation/Contributors/TestingGuide/README.md#testing-guide)
- **Documentation** : reference documentation built from source. [Documentation guide here.](https://github.com/CesiumGS/cesium/blob/master/Documentation/Contributors/DocumentationGuide/README.md#documentation-guide)
@ -124,7 +124,7 @@ Here's the full set of scripts and what they do.
## Travis and Continuous Integration
Cesium uses [Travis](https://travis-ci.org/) for continuous integration. The Travis configuration and all the steps of the build process are defined in `travis.yml`. The blog post [Cesium Continuous Integration](http://cesiumjs.org/2016/04/07/Cesium-Continuous-Integration/) contains an in-depth explaination of the travis build process.
Cesium uses [Travis](https://travis-ci.org/) for continuous integration. The Travis configuration and all the steps of the build process are defined in `travis.yml`. The blog post [Cesium Continuous Integration](http://cesium.com/blog/2016/04/07/Cesium-Continuous-Integration/) contains an in-depth explaination of the travis build process.
Travis triggers a build whenever someone opens a pull request or pushes code to the Cesium repository. After the build has completed, at the bottom on the pull request, the status of the build is shown and you can access the build by clicking the "Details" link.

View File

@ -615,7 +615,7 @@ var p = new Cartesian3(1.0, 2.0, 3.0);
p.x = "Cesium"; // Changes x to a string, slows down property access
```
- In a constructor function, consider properties as write once; do not write to them or read them multiple times. Create a local variable if they need to be ready. For example:
- In a constructor function, consider properties as write once; do not write to them or read them multiple times. Create a local variable if they need to be read. For example:
Instead of

View File

@ -1,6 +1,6 @@
# Presenter's Guide
The Cesium team gives a lot of [talks](http://cesiumjs.org/publications.html). Here's some tips, based on our experience, for delivering a great talk.
The Cesium team gives a lot of [talks](http://cesium.com/docs/presentations/). Here's some tips, based on our experience, for delivering a great talk.
- [Invest Time Preparing](#invest-time-preparing)
- [Know the Audience](#know-the-audience)

View File

@ -197,10 +197,6 @@ It is also possible for Karma to run all tests against each browser installed on
Sometimes it is useful to run a single test or suite for easier debugging purposes. To do this simply change the `it` function call for the desired test to `fit`, the `f` stands for `focused` in Jasmine speak. Likewise, to run an entire suite, use `fdescribe` instead of `describe`.
## Testing Previous Versions of CesiumJS
Sometimes it is useful to see if an issue exists in a previous version of CesiumJS. The tests for all versions of CesiumJS back to b15 (April 2013) are hosted on the CesiumJS website via the [downloads page](http://cesiumjs.org/downloads.html). Use the "Documentation, Sandcastle, tests, etc." links.
## `testfailure` Label for Issues
Despite our best efforts, sometimes tests fail. This is often due to a new browser, OS, or driver bug that breaks a test that previously passed. If this indicates a bug in CesiumJS, we strive to quickly fix it. Likewise, if it indicates that CesiumJS needs to work around the issue (for example, as we [did for Safari 9](https://github.com/CesiumGS/cesium/issues/2989)), we also strive to quickly fix it.

View File

@ -41,23 +41,23 @@ Using Cesium ion helps support CesiumJS development. :heart:
### :clap: Featured Demos
<p>
<a href="https://cesium.com/blog/2018/08/21/cybercity/"><img src="https://cesium.com/blog/images/2018/08-21/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://apps.agi.com/SatelliteViewer/?Status=Operational"><img src="https://cesium.com/blog/images/2018/03-29/comspoc-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2018/02/05/historic-pharsalia-cabin-point-cloud/"><img src="https://cesium.com/blog/images/2018/02-05/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/12/12/onesky/"><img src="https://cesium.com/blog/images/2017/12-12/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/11/20/nasa-storm-virtual-globe/"><img src="https://cesium.com/blog/images/2017/11-20/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/11/16/gefs/"><img src="https://cesium.com/blog/images/2017/11-16/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2019/01/04/norad-tracks-santa/"><img src="https://cesium.com/blog/images/2019/01-04/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/07/23/drcog/"><img src="https://cesium.com/blog/images/2017/07-23/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://demos.cesium.com/NewYork/"><img src="https://cesium.com/blog/images/2017/05-05/nyc-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2018/09/27/swisstopo-live/"><img src="https://cesium.com/blog/images/2018/09-27/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/12/12/stk-czml/"><img src="https://cesium.com/blog/images/2016/12-12/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/09/29/contextcapture/"><img src="https://cesium.com/blog/images/2016/09-29/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/04/20/flightradar24/"><img src="https://cesium.com/blog/images/2016/04-20/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/02/03/fodarearth/"><img src="https://cesium.com/blog/images/2016/02-03/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2015/08/19/mars-trek/"><img src="https://cesium.com/blog/images/2015/08-19/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2015/07/16/hiroshima-archive/"><img src="https://cesium.com/blog/images/2015/07-16/cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2019/06/13/red-bull-x-alps-in-cesium/"><img src="https://cesium.com/blog/images/2019/06-12/redbullxalps.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2018/08/21/cybercity/"><img src="https://images.prismic.io/cesium/2018-08-21-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://apps.agi.com/SatelliteViewer/?Status=Operational"><img src="https://images.prismic.io/cesium/2018-03-29-comspoc-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2018/02/05/historic-pharsalia-cabin-point-cloud/"><img src="https://images.prismic.io/cesium/2018-02-05-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/12/12/onesky/"><img src="https://images.prismic.io/cesium/2017-12-12-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/11/20/nasa-storm-virtual-globe/"><img src="https://images.prismic.io/cesium/2017-11-20-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/11/16/gefs/"><img src="https://images.prismic.io/cesium/2017-11-16-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2019/01/04/norad-tracks-santa/"><img src="https://images.prismic.io/cesium/2019-01-04-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2017/07/23/drcog/"><img src="https://images.prismic.io/cesium/2017-07-23-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://demos.cesium.com/NewYork/"><img src="https://images.prismic.io/cesium/2017-05-05-nyc-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2018/09/27/swisstopo-live/"><img src="https://images.prismic.io/cesium/2018-09-27-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/12/12/stk-czml/"><img src="https://images.prismic.io/cesium/2016-12-12-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/09/29/contextcapture/"><img src="https://images.prismic.io/cesium/2016-09-29-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/04/20/flightradar24/"><img src="https://images.prismic.io/cesium/2016-04-20-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2016/02/03/fodarearth/"><img src="https://images.prismic.io/cesium/2016-02-03-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2015/08/19/mars-trek/"><img src="https://images.prismic.io/cesium/2015-08-19-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2015/07/16/hiroshima-archive/"><img src="https://images.prismic.io/cesium/2015-07-16-cover.jpg" width="30%" /></a>&nbsp;
<a href="https://cesium.com/blog/2019/06/13/red-bull-x-alps-in-cesium/"><img src="https://images.prismic.io/cesium/2015-10-02-cover.jpg" width="30%" /></a>&nbsp;
<br/>
<br/>
</p>

View File

@ -0,0 +1,402 @@
import CesiumMath from "./Math.js";
import Check from "./Check.js";
import defined from "./defined.js";
/**
* Array-backed min-max heap implementation of a double-ended priority queue.
* This data structure allows for efficient removal of minimum and maximum elements.
*
* @alias DoubleEndedPriorityQueue
* @constructor
* @private
*
* @param {Object} options Object with the following properties:
* @param {DoubleEndedPriorityQueue.ComparatorCallback} options.comparator The comparator to use for the queue. If comparator(a, b) is less than 0, a is lower priority than b.
* @param {Number} [options.maximumLength] The maximum length of the queue. If an element is inserted when the queue is at full capacity, the minimum element is removed. By default, the size of the queue is unlimited.
*/
function DoubleEndedPriorityQueue(options) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object("options", options);
Check.defined("options.comparator", options.comparator);
if (defined(options.maximumLength)) {
Check.typeOf.number.greaterThanOrEquals(
"options.maximumLength",
options.maximumLength,
0
);
}
//>>includeEnd('debug');
this._comparator = options.comparator;
this._maximumLength = options.maximumLength;
this._array = defined(options.maximumLength)
? new Array(options.maximumLength)
: [];
this._length = 0;
}
Object.defineProperties(DoubleEndedPriorityQueue.prototype, {
/**
* Gets the number of elements in the queue.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {Number}
* @readonly
*/
length: {
get: function () {
return this._length;
},
},
/**
* Gets or sets the maximum number of elements in the queue.
* If set to a smaller value than the current length of the queue, the lowest priority elements are removed.
* If an element is inserted when the queue is at full capacity, the minimum element is removed.
* If set to undefined, the size of the queue is unlimited.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {Number}
* @readonly
*/
maximumLength: {
get: function () {
return this._maximumLength;
},
set: function (value) {
if (defined(value)) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.number.greaterThanOrEquals("maximumLength", value, 0);
//>>includeEnd('debug');
// Remove elements until the maximum length is met.
while (this._length > value) {
this.removeMinimum();
}
// The array size is fixed to the maximum length
this._array.length = value;
}
this._maximumLength = value;
},
},
/**
* Gets the internal array.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {Array}
* @readonly
*/
internalArray: {
get: function () {
return this._array;
},
},
/**
* The comparator used by the queue.
* If comparator(a, b) is less than 0, a is lower priority than b.
*
* @memberof DoubleEndedPriorityQueue.prototype
*
* @type {DoubleEndedPriorityQueue.ComparatorCallback}
* @readonly
*/
comparator: {
get: function () {
return this._comparator;
},
},
});
/**
* Clones the double ended priority queue.
*
* @returns {DoubleEndedPriorityQueue} The cloned double ended priority queue.
*/
DoubleEndedPriorityQueue.prototype.clone = function () {
var maximumLength = this._maximumLength;
var comparator = this._comparator;
var array = this._array;
var length = this._length;
var result = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: maximumLength,
});
result._length = length;
for (var i = 0; i < length; i++) {
result._array[i] = array[i];
}
return result;
};
/**
* Removes all elements from the queue.
*/
DoubleEndedPriorityQueue.prototype.reset = function () {
this._length = 0;
// Dereference elements
var maximumLength = this._maximumLength;
if (defined(maximumLength)) {
// Dereference all elements but keep the array the same size
for (var i = 0; i < maximumLength; i++) {
this._array[i] = undefined;
}
} else {
// Dereference all elements by clearing the array
this._array.length = 0;
}
};
/**
* Resort the queue.
*/
DoubleEndedPriorityQueue.prototype.resort = function () {
var length = this._length;
// Fix the queue from the top-down
for (var i = 0; i < length; i++) {
pushUp(this, i);
}
};
/**
* Inserts an element into the queue.
* If the queue is at full capacity, the minimum element is removed.
* The new element is returned (and not added) if it is less than or equal priority to the minimum element.
*
* @param {*} element
* @returns {*|undefined} The minimum element if the queue is at full capacity. Returns undefined if there is no maximum length.
*/
DoubleEndedPriorityQueue.prototype.insert = function (element) {
var removedElement;
var maximumLength = this._maximumLength;
if (defined(maximumLength)) {
if (maximumLength === 0) {
return undefined;
} else if (this._length === maximumLength) {
// It's faster to access the minimum directly instead of calling the getter
// because it avoids the length === 0 check.
var minimumElement = this._array[0];
if (this._comparator(element, minimumElement) <= 0.0) {
// The element that is being inserted is less than or equal to
// the minimum element, so don't insert anything and exit early.
return element;
}
removedElement = this.removeMinimum();
}
}
var index = this._length;
this._array[index] = element;
this._length++;
pushUp(this, index);
return removedElement;
};
/**
* Removes the minimum element from the queue and returns it.
* If the queue is empty, the return value is undefined.
*
* @returns {*|undefined} The minimum element, or undefined if the queue is empty.
*/
DoubleEndedPriorityQueue.prototype.removeMinimum = function () {
var length = this._length;
if (length === 0) {
return undefined;
}
this._length--;
// The minimum element is always the root
var minimumElement = this._array[0];
if (length >= 2) {
this._array[0] = this._array[length - 1];
pushDown(this, 0);
}
// Dereference removed element
this._array[length - 1] = undefined;
return minimumElement;
};
/**
* Removes the maximum element from the queue and returns it.
* If the queue is empty, the return value is undefined.
*
* @returns {*|undefined} The maximum element, or undefined if the queue is empty.
*/
DoubleEndedPriorityQueue.prototype.removeMaximum = function () {
var length = this._length;
if (length === 0) {
return undefined;
}
this._length--;
var maximumElement;
// If the root has no children, the maximum is the root.
// If the root has one child, the maximum is the child.
if (length <= 2) {
maximumElement = this._array[length - 1];
} else {
// Otherwise, the maximum is the larger of the root's two children.
var maximumElementIndex = greaterThan(this, 1, 2) ? 1 : 2;
maximumElement = this._array[maximumElementIndex];
// Re-balance the heap
this._array[maximumElementIndex] = this._array[length - 1];
if (length >= 4) {
pushDown(this, maximumElementIndex);
}
}
// Dereference removed element
this._array[length - 1] = undefined;
return maximumElement;
};
/**
* Gets the minimum element in the queue.
* If the queue is empty, the result is undefined.
*
* @returns {*|undefined} element
*/
DoubleEndedPriorityQueue.prototype.getMinimum = function () {
var length = this._length;
if (length === 0) {
return undefined;
}
// The minimum element is always the root
return this._array[0];
};
/**
* Gets the maximum element in the queue.
* If the queue is empty, the result is undefined.
*
* @returns {*|undefined} element
*/
DoubleEndedPriorityQueue.prototype.getMaximum = function () {
var length = this._length;
if (length === 0) {
return undefined;
}
// If the root has no children, the maximum is the root.
// If the root has one child, the maximum is the child.
if (length <= 2) {
return this._array[length - 1];
}
// Otherwise, the maximum is the larger of the root's two children.
return this._array[greaterThan(this, 1, 2) ? 1 : 2];
};
// Helper functions
function swap(that, indexA, indexB) {
var array = that._array;
var temp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = temp;
}
function lessThan(that, indexA, indexB) {
return that._comparator(that._array[indexA], that._array[indexB]) < 0.0;
}
function greaterThan(that, indexA, indexB) {
return that._comparator(that._array[indexA], that._array[indexB]) > 0.0;
}
function pushUp(that, index) {
if (index === 0) {
return;
}
var onMinLevel = Math.floor(CesiumMath.log2(index + 1)) % 2 === 0;
var parentIndex = Math.floor((index - 1) / 2);
var lessThanParent = lessThan(that, index, parentIndex);
// Get the element onto the correct level if it's not already
if (lessThanParent !== onMinLevel) {
swap(that, index, parentIndex);
index = parentIndex;
}
// Swap element with grandparent as long as it:
// 1) has a grandparent
// 2A) is less than the grandparent when on a min level
// 2B) is greater than the grandparent when on a max level
while (index >= 3) {
var grandparentIndex = Math.floor((index - 3) / 4);
if (lessThan(that, index, grandparentIndex) !== lessThanParent) {
break;
}
swap(that, index, grandparentIndex);
index = grandparentIndex;
}
}
function pushDown(that, index) {
var length = that._length;
var onMinLevel = Math.floor(CesiumMath.log2(index + 1)) % 2 === 0;
// Loop as long as there is a left child.
var leftChildIndex;
while ((leftChildIndex = 2 * index + 1) < length) {
// Find the minimum (or maximum) child or grandchild
var target = leftChildIndex;
var rightChildIndex = leftChildIndex + 1;
if (rightChildIndex < length) {
if (lessThan(that, rightChildIndex, target) === onMinLevel) {
target = rightChildIndex;
}
var grandChildStart = 2 * leftChildIndex + 1;
var grandChildCount = Math.max(Math.min(length - grandChildStart, 4), 0);
for (var i = 0; i < grandChildCount; i++) {
var grandChildIndex = grandChildStart + i;
if (lessThan(that, grandChildIndex, target) === onMinLevel) {
target = grandChildIndex;
}
}
}
// Swap the element into the correct spot
if (lessThan(that, target, index) === onMinLevel) {
swap(that, target, index);
if (target !== leftChildIndex && target !== rightChildIndex) {
var parentOfGrandchildIndex = Math.floor((target - 1) / 2);
if (greaterThan(that, target, parentOfGrandchildIndex) === onMinLevel) {
swap(that, target, parentOfGrandchildIndex);
}
}
}
index = target;
}
}
/**
* The comparator to use for the queue.
* @callback DoubleEndedPriorityQueue.ComparatorCallback
* @param {*} a An element in the queue.
* @param {*} b An element in the queue.
* @returns {Number} If the result of the comparison is less than 0, a is lower priority than b.
*/
export default DoubleEndedPriorityQueue;

View File

@ -300,6 +300,10 @@ function interpolateUsingSurfaceDistance(
ellipticity,
result
) {
if (distance === 0.0) {
return Cartographic.clone(start, result);
}
var ellipticitySquared = ellipticity * ellipticity;
var longitude;

View File

@ -4,7 +4,7 @@ import Resource from "./Resource.js";
var defaultTokenCredit;
var defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4NTVhMjg4My1iNGI2LTRhNzgtOTQ0My1mYjA4MTNjMTJiYjQiLCJpZCI6MjU5LCJpYXQiOjE2MTQ1ODE4MDB9.FeIKU_q_xmSAPeRgrOYaJAWmHFGIvy6i-p_Zk9mweEw";
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlNzhiOGFmZi0wMDhkLTQyZGItODMxYi1jZTE1Yzc1YWU5NDAiLCJpZCI6MjU5LCJpYXQiOjE2MTcyOTExODV9.ZMm6ggSpVEnvlUfE_sa-ZQ5AXhPAFVjshKZMB48w0AE";
/**
* Default settings for accessing the Cesium ion API.
*

View File

@ -0,0 +1,51 @@
import AttributeCompression from "./AttributeCompression.js";
import Cartesian3 from "./Cartesian3.js";
import Cartographic from "./Cartographic.js";
import CesiumMath from "./Math.js";
var maxShort = 32767;
var scratchBVCartographic = new Cartographic();
var scratchEncodedPosition = new Cartesian3();
function decodeVectorPolylinePositions(
positions,
rectangle,
minimumHeight,
maximumHeight,
ellipsoid
) {
var positionsLength = positions.length / 3;
var uBuffer = positions.subarray(0, positionsLength);
var vBuffer = positions.subarray(positionsLength, 2 * positionsLength);
var heightBuffer = positions.subarray(
2 * positionsLength,
3 * positionsLength
);
AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
var decoded = new Float64Array(positions.length);
for (var i = 0; i < positionsLength; ++i) {
var u = uBuffer[i];
var v = vBuffer[i];
var h = heightBuffer[i];
var lon = CesiumMath.lerp(rectangle.west, rectangle.east, u / maxShort);
var lat = CesiumMath.lerp(rectangle.south, rectangle.north, v / maxShort);
var alt = CesiumMath.lerp(minimumHeight, maximumHeight, h / maxShort);
var cartographic = Cartographic.fromRadians(
lon,
lat,
alt,
scratchBVCartographic
);
var decodedPosition = ellipsoid.cartographicToCartesian(
cartographic,
scratchEncodedPosition
);
Cartesian3.pack(decodedPosition, decoded, i * 3);
}
return decoded;
}
export default decodeVectorPolylinePositions;

View File

@ -4,6 +4,7 @@ import defined from "./defined.js";
import DeveloperError from "./DeveloperError.js";
import Resource from "./Resource.js";
import TaskProcessor from "./TaskProcessor.js";
import deprecationWarning from "./deprecationWarning.js";
var transcodeTaskProcessor = new TaskProcessor("transcodeCRNToDXT");
@ -36,8 +37,13 @@ var transcodeTaskProcessor = new TaskProcessor("transcodeCRNToDXT");
* @see {@link https://github.com/BinomialLLC/crunch|crunch DXTc texture compression and transcoding library}
* @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
* @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
* @deprecated This function has been deprecated and will be removed in CesiumJS 1.82.
*/
function loadCRN(resourceOrUrlOrBuffer) {
deprecationWarning(
"loadCRN",
"loadCRN is deprecated and will be removed in CesiumJS 1.82."
);
//>>includeStart('debug', pragmas.debug);
if (!defined(resourceOrUrlOrBuffer)) {
throw new DeveloperError("resourceOrUrlOrBuffer is required.");

View File

@ -6,6 +6,7 @@ import PixelFormat from "./PixelFormat.js";
import Resource from "./Resource.js";
import RuntimeError from "./RuntimeError.js";
import WebGLConstants from "./WebGLConstants.js";
import deprecationWarning from "./deprecationWarning.js";
/**
* Asynchronously loads and parses the given URL to a KTX file or parses the raw binary data of a KTX file.
@ -57,8 +58,13 @@ import WebGLConstants from "./WebGLConstants.js";
* @see {@link https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/|KTX file format}
* @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}
* @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}
* @deprecated This function has been deprecated and will be removed in CesiumJS 1.82.
*/
function loadKTX(resourceOrUrlOrBuffer) {
deprecationWarning(
"loadKTX",
"loadKTX is deprecated and will be removed in CesiumJS 1.82."
);
//>>includeStart('debug', pragmas.debug);
Check.defined("resourceOrUrlOrBuffer", resourceOrUrlOrBuffer);
//>>includeEnd('debug');

View File

@ -43,6 +43,11 @@ function DrawCommand(options) {
this._pickId = options.pickId;
this._pickOnly = defaultValue(options.pickOnly, false);
this._depthForTranslucentClassification = defaultValue(
options.depthForTranslucentClassification,
false
);
this.dirty = true;
this.lastDirtyTime = 0;
@ -513,6 +518,24 @@ Object.defineProperties(DrawCommand.prototype, {
}
},
},
/**
* Whether this command should be derived to draw depth for classification of translucent primitives.
*
* @memberof DrawCommand.prototype
* @type {Boolean}
* @default false
*/
depthForTranslucentClassification: {
get: function () {
return this._depthForTranslucentClassification;
},
set: function (value) {
if (this._depthForTranslucentClassification !== value) {
this._depthForTranslucentClassification = value;
this.dirty = true;
}
},
},
});
/**
@ -549,6 +572,8 @@ DrawCommand.shallowClone = function (command, result) {
result._receiveShadows = command._receiveShadows;
result._pickId = command._pickId;
result._pickOnly = command._pickOnly;
result._depthForTranslucentClassification =
command._depthForTranslucentClassification;
result.dirty = true;
result.lastDirtyTime = 0;

View File

@ -47,6 +47,10 @@ function Batched3DModel3DTileContent(
this._batchTable = undefined;
this._features = undefined;
this._classificationType = tileset.vectorClassificationOnly
? undefined
: tileset.classificationType;
// Populate from gltf when available
this._batchIdAttributeName = undefined;
this._diffuseAttributeOrUniformName = {};
@ -161,7 +165,7 @@ function getBatchIdAttributeName(gltf) {
function getVertexShaderCallback(content) {
return function (vs, programId) {
var batchTable = content._batchTable;
var handleTranslucent = !defined(content._tileset.classificationType);
var handleTranslucent = !defined(content._classificationType);
var gltf = content._model.gltf;
if (defined(gltf)) {
@ -183,7 +187,7 @@ function getVertexShaderCallback(content) {
function getFragmentShaderCallback(content) {
return function (fs, programId) {
var batchTable = content._batchTable;
var handleTranslucent = !defined(content._tileset.classificationType);
var handleTranslucent = !defined(content._classificationType);
var gltf = content._model.gltf;
if (defined(gltf)) {
@ -193,7 +197,8 @@ function getFragmentShaderCallback(content) {
}
var callback = batchTable.getFragmentShaderCallback(
handleTranslucent,
content._diffuseAttributeOrUniformName[programId]
content._diffuseAttributeOrUniformName[programId],
false
);
return defined(callback) ? callback(fs) : fs;
};
@ -348,7 +353,7 @@ function initialize(content, arrayBuffer, byteOffset) {
}
var colorChangedCallback;
if (defined(tileset.classificationType)) {
if (defined(content._classificationType)) {
colorChangedCallback = createColorChangedCallback(content);
}
@ -403,7 +408,7 @@ function initialize(content, arrayBuffer, byteOffset) {
new Matrix4()
);
if (!defined(tileset.classificationType)) {
if (!defined(content._classificationType)) {
// PERFORMANCE_IDEA: patch the shader on demand, e.g., the first time show/color changes.
// The pick shader still needs to be patched.
content._model = new Model({
@ -455,7 +460,7 @@ function initialize(content, arrayBuffer, byteOffset) {
),
uniformMapLoaded: batchTable.getUniformMapCallback(),
pickIdLoaded: getPickIdCallback(content),
classificationType: tileset._classificationType,
classificationType: content._classificationType,
batchTable: batchTable,
});
}
@ -571,7 +576,7 @@ Batched3DModel3DTileContent.prototype.update = function (tileset, frameState) {
if (
commandStart < commandEnd &&
(frameState.passes.render || frameState.passes.pick) &&
!defined(tileset.classificationType)
!defined(this._classificationType)
) {
this._batchTable.addDerivedCommands(frameState, commandStart);
}

View File

@ -34,6 +34,7 @@ import SceneMode from "./SceneMode.js";
import TileBoundingRegion from "./TileBoundingRegion.js";
import TileBoundingSphere from "./TileBoundingSphere.js";
import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
import Pass from "../Renderer/Pass.js";
/**
* A tile in a {@link Cesium3DTileset}. When a tile is first created, its content is not loaded;
@ -1611,11 +1612,21 @@ function updateClippingPlanes(tile, tileset) {
* @private
*/
Cesium3DTile.prototype.update = function (tileset, frameState, passOptions) {
var initCommandLength = frameState.commandList.length;
var commandStart = frameState.commandList.length;
updateClippingPlanes(this, tileset);
applyDebugSettings(this, tileset, frameState, passOptions);
updateContent(this, tileset, frameState);
this._commandsLength = frameState.commandList.length - initCommandLength;
var commandEnd = frameState.commandList.length;
var commandsLength = commandEnd - commandStart;
this._commandsLength = commandsLength;
for (var i = 0; i < commandsLength; ++i) {
var command = frameState.commandList[commandStart + i];
var translucent = command.pass === Pass.TRANSLUCENT;
command.depthForTranslucentClassification = translucent;
}
this.clippingPlanesDirty = false; // reset after content update
};

View File

@ -1195,7 +1195,8 @@ function modifyDiffuse(source, diffuseAttributeOrUniformName, applyHighlight) {
Cesium3DTileBatchTable.prototype.getFragmentShaderCallback = function (
handleTranslucent,
diffuseAttributeOrUniformName
diffuseAttributeOrUniformName,
hasPremultipliedAlpha
) {
if (this.featuresLength === 0) {
return;
@ -1210,8 +1211,13 @@ Cesium3DTileBatchTable.prototype.getFragmentShaderCallback = function (
"varying vec4 tile_featureColor; \n" +
"void main() \n" +
"{ \n" +
" tile_color(tile_featureColor); \n" +
"}";
" tile_color(tile_featureColor); \n";
if (hasPremultipliedAlpha) {
source += " gl_FragColor.rgb *= gl_FragColor.a; \n";
}
source += "}";
} else {
if (handleTranslucent) {
source += "uniform bool tile_translucentCommand; \n";
@ -1246,7 +1252,13 @@ Cesium3DTileBatchTable.prototype.getFragmentShaderCallback = function (
" } \n";
}
source += " tile_color(featureProperties); \n" + "} \n";
source += " tile_color(featureProperties); \n";
if (hasPremultipliedAlpha) {
source += " gl_FragColor.rgb *= gl_FragColor.a; \n";
}
source += "} \n";
}
return source;
};
@ -1268,6 +1280,7 @@ Cesium3DTileBatchTable.prototype.getClassificationFragmentShaderCallback = funct
"{ \n" +
" tile_main(); \n" +
" gl_FragColor = tile_featureColor; \n" +
" gl_FragColor.rgb *= gl_FragColor.a; \n" +
"}";
} else {
source +=
@ -1282,6 +1295,7 @@ Cesium3DTileBatchTable.prototype.getClassificationFragmentShaderCallback = funct
" discard; \n" +
" } \n" +
" gl_FragColor = featureProperties; \n" +
" gl_FragColor.rgb *= gl_FragColor.a; \n" +
"} \n";
}
return source;
@ -1607,6 +1621,8 @@ function getTranslucentRenderState(renderState) {
rs.depthTest.enabled = true;
rs.depthMask = false;
rs.blending = BlendingState.ALPHA_BLEND;
rs.stencilTest = StencilConstants.setCesium3DTileBit();
rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;
return RenderState.fromCache(rs);
}

View File

@ -90,8 +90,8 @@ import TileOrientedBoundingBox from "./TileOrientedBoundingBox.js";
* @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.
* @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.
* @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.
* @param {Boolean} [options.vectorClassificationOnly=false] Indicates that only the tileset's vector tiles should be used for classification.
* @param {String} [options.debugHeatmapTilePropertyName] The tile variable to colorize as a heatmap. All rendered tiles will be colorized relative to each other's specified variable value.
* @param {Object} [options.pickPrimitive] The primitive to be rendered during the pick pass instead of the tileset.
* @param {Boolean} [options.debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.
* @param {Boolean} [options.debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.
* @param {Boolean} [options.debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.
@ -274,6 +274,11 @@ function Cesium3DTileset(options) {
this._clippingPlanesOriginMatrix = undefined; // Combines the above with any run-time transforms.
this._clippingPlanesOriginMatrixDirty = true;
this._vectorClassificationOnly = defaultValue(
options.vectorClassificationOnly,
false
);
/**
* Preload tiles when <code>tileset.show</code> is <code>false</code>. Loads tiles as if the tileset is visible but does not render them.
*
@ -762,13 +767,6 @@ function Cesium3DTileset(options) {
*/
this.backFaceCulling = defaultValue(options.backFaceCulling, true);
/**
* The primitive to be rendered during the pick pass instead of the tileset.
*
* @type {Object}
*/
this.pickPrimitive = options.pickPrimitive;
/**
* This property is for debugging only; it is not optimized for production use.
* <p>
@ -906,6 +904,15 @@ function Cesium3DTileset(options) {
*/
this.debugShowUrl = defaultValue(options.debugShowUrl, false);
/**
* Function for examining vector lines as they are being streamed.
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @type {Function}
*/
this.examineVectorLinesFunction = undefined;
var that = this;
var resource;
when(options.url)
@ -1662,6 +1669,22 @@ Object.defineProperties(Cesium3DTileset.prototype, {
Cartesian2.clone(value, this._imageBasedLightingFactor);
},
},
/**
* Indicates that only the tileset's vector tiles should be used for classification.
*
* @memberof Cesium3DTileset.prototype
*
* @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.
*
* @type {Boolean}
* @default false
*/
vectorClassificationOnly: {
get: function () {
return this._vectorClassificationOnly;
},
},
});
/**
@ -2552,17 +2575,13 @@ Cesium3DTileset.prototype.updateForPass = function (
var passStatistics = this._statisticsPerPass[pass];
if (this.show || ignoreCommands) {
if (frameState.passes.pick && defined(this.pickPrimitive)) {
this.pickPrimitive.update(frameState);
} else {
this._pass = pass;
tilesetPassState.ready = update(
this,
frameState,
passStatistics,
passOptions
);
}
this._pass = pass;
tilesetPassState.ready = update(
this,
frameState,
passStatistics,
passOptions
);
}
if (ignoreCommands) {

View File

@ -76,6 +76,7 @@ import processModelMaterialsCommon from "./processModelMaterialsCommon.js";
import processPbrMaterials from "./processPbrMaterials.js";
import SceneMode from "./SceneMode.js";
import ShadowMode from "./ShadowMode.js";
import StencilConstants from "./StencilConstants.js";
var boundingSphereCartesian3Scratch = new Cartesian3();
@ -4482,20 +4483,26 @@ function updateShadows(model) {
}
}
function getTranslucentRenderState(renderState) {
function getTranslucentRenderState(model, renderState) {
var rs = clone(renderState, true);
rs.cull.enabled = false;
rs.depthTest.enabled = true;
rs.depthMask = false;
rs.blending = BlendingState.ALPHA_BLEND;
if (model.opaquePass === Pass.CESIUM_3D_TILE) {
rs.stencilTest = StencilConstants.setCesium3DTileBit();
rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;
}
return RenderState.fromCache(rs);
}
function deriveTranslucentCommand(command) {
function deriveTranslucentCommand(model, command) {
var translucentCommand = DrawCommand.shallowClone(command);
translucentCommand.pass = Pass.TRANSLUCENT;
translucentCommand.renderState = getTranslucentRenderState(
model,
command.renderState
);
return translucentCommand;
@ -4515,10 +4522,14 @@ function updateColor(model, frameState, forceDerive) {
for (var i = 0; i < length; ++i) {
var nodeCommand = nodeCommands[i];
var command = nodeCommand.command;
nodeCommand.translucentCommand = deriveTranslucentCommand(command);
nodeCommand.translucentCommand = deriveTranslucentCommand(
model,
command
);
if (!scene3DOnly) {
var command2D = nodeCommand.command2D;
nodeCommand.translucentCommand2D = deriveTranslucentCommand(
model,
command2D
);
}
@ -5505,10 +5516,6 @@ Model.prototype.update = function (frameState) {
// Regenerate shaders if ClippingPlaneCollection state changed or it was removed
var clippingPlanes = this._clippingPlanes;
var currentClippingPlanesState = 0;
var useClippingPlanes =
defined(clippingPlanes) &&
clippingPlanes.enabled &&
clippingPlanes.length > 0;
// If defined, use the reference matrix to transform miscellaneous properties like
// clipping planes and IBL instead of the modelMatrix. This is so that when
@ -5516,7 +5523,7 @@ Model.prototype.update = function (frameState) {
// a common reference (such as the root).
var referenceMatrix = defaultValue(this.referenceMatrix, modelMatrix);
if (useClippingPlanes) {
if (isClippingEnabled(this)) {
var clippingPlanesMatrix = scratchClippingPlanesMatrix;
clippingPlanesMatrix = Matrix4.multiply(
context.uniformState.view3D,

View File

@ -455,7 +455,8 @@ function getFragmentShaderCallback(collection) {
);
fs = batchTable.getFragmentShaderCallback(
true,
diffuseAttributeOrUniformName
diffuseAttributeOrUniformName,
false
)(fs);
} else {
fs = "varying vec4 v_pickColor;\n" + fs;
@ -536,7 +537,8 @@ function getFragmentShaderNonInstancedCallback(collection) {
);
fs = batchTable.getFragmentShaderCallback(
true,
diffuseAttributeOrUniformName
diffuseAttributeOrUniformName,
false
)(fs);
} else {
fs = "uniform vec4 czm_pickColor;\n" + fs;

View File

@ -832,20 +832,25 @@ function createResources(pointCloud, frameState) {
},
};
if (pointCloud._opaquePass === Pass.CESIUM_3D_TILE) {
opaqueRenderState.stencilTest = StencilConstants.setCesium3DTileBit();
opaqueRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;
}
pointCloud._opaqueRenderState = RenderState.fromCache(opaqueRenderState);
pointCloud._translucentRenderState = RenderState.fromCache({
var translucentRenderState = {
depthTest: {
enabled: true,
},
depthMask: false,
blending: BlendingState.ALPHA_BLEND,
});
};
if (pointCloud._opaquePass === Pass.CESIUM_3D_TILE) {
opaqueRenderState.stencilTest = StencilConstants.setCesium3DTileBit();
opaqueRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;
translucentRenderState.stencilTest = StencilConstants.setCesium3DTileBit();
translucentRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;
}
pointCloud._opaqueRenderState = RenderState.fromCache(opaqueRenderState);
pointCloud._translucentRenderState = RenderState.fromCache(
translucentRenderState
);
pointCloud._drawCommand = new DrawCommand({
boundingVolume: new BoundingSphere(),

View File

@ -153,7 +153,8 @@ function getFragmentShaderLoaded(content) {
if (defined(content._batchTable)) {
return content._batchTable.getFragmentShaderCallback(
false,
undefined
undefined,
false
)(fs);
}
return "uniform vec4 czm_pickColor;\n" + fs;

View File

@ -2658,6 +2658,28 @@ function executeCommands(scene, passState) {
invertClassification
);
// Classification for translucent 3D Tiles
var has3DTilesClassificationCommands =
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] > 0;
if (
has3DTilesClassificationCommands &&
view.translucentTileClassification.isSupported()
) {
view.translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
commands,
globeDepth.framebuffer
);
view.translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
}
if (
context.depthTexture &&
scene.useDepthPicking &&
@ -3545,6 +3567,14 @@ Scene.prototype.resolveFramebuffers = function (passState) {
view.oit.execute(context, passState);
}
var translucentTileClassification = view.translucentTileClassification;
if (
translucentTileClassification.hasTranslucentDepth &&
translucentTileClassification.isSupported()
) {
translucentTileClassification.execute(this, passState);
}
if (usePostProcess) {
var inputFramebuffer = sceneFramebuffer;
if (useGlobeDepthFramebuffer && !useOIT) {

View File

@ -0,0 +1,587 @@
import BoundingRectangle from "../Core/BoundingRectangle.js";
import Color from "../Core/Color.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import PixelFormat from "../Core/PixelFormat.js";
import ClearCommand from "../Renderer/ClearCommand.js";
import DrawCommand from "../Renderer/DrawCommand.js";
import Framebuffer from "../Renderer/Framebuffer.js";
import Pass from "../Renderer/Pass.js";
import PixelDatatype from "../Renderer/PixelDatatype.js";
import RenderState from "../Renderer/RenderState.js";
import Sampler from "../Renderer/Sampler.js";
import ShaderSource from "../Renderer/ShaderSource.js";
import Texture from "../Renderer/Texture.js";
import CompareAndPackTranslucentDepth from "../Shaders/CompareAndPackTranslucentDepth.js";
import CompositeTranslucentClassification from "../Shaders/PostProcessStages/CompositeTranslucentClassification.js";
import BlendingState from "./BlendingState.js";
import StencilConstants from "./StencilConstants.js";
import StencilFunction from "./StencilFunction.js";
var debugShowPackedDepth = false;
/**
* Handles buffers, drawing, and deriving commands needed for classifying translucent 3D Tiles.
* Uses a depth texture, so classification on translucent 3D Tiles is not available in Internet Explorer.
*
* @private
*/
function TranslucentTileClassification(context) {
this._drawClassificationFBO = undefined;
this._accumulationFBO = undefined;
this._packFBO = undefined;
this._opaqueDepthStencilTexture = undefined;
this._colorTexture = undefined;
this._accumulationTexture = undefined;
// Reference to either colorTexture or accumulationTexture
this._textureToComposite = undefined;
this._translucentDepthStencilTexture = undefined;
this._packedTranslucentDepth = undefined;
this._packDepthCommand = undefined;
this._accumulateCommand = undefined;
this._compositeCommand = undefined;
this._copyCommand = undefined;
this._clearColorCommand = new ClearCommand({
color: new Color(0.0, 0.0, 0.0, 0.0),
owner: this,
});
this._clearDepthStencilCommand = new ClearCommand({
depth: 1.0,
stencil: 0,
owner: this,
});
this._supported = context.depthTexture;
this._viewport = new BoundingRectangle();
this._rsDepth = undefined;
this._rsAccumulate = undefined;
this._rsComp = undefined;
this._useScissorTest = undefined;
this._scissorRectangle = undefined;
this._hasTranslucentDepth = false;
this._frustumsDrawn = 0;
}
Object.defineProperties(TranslucentTileClassification.prototype, {
/**
* Gets whether or not translucent depth was rendered.
* @memberof TranslucentTileClassification.prototype
*
* @type {Boolean}
* @readonly
*/
hasTranslucentDepth: {
get: function () {
return this._hasTranslucentDepth;
},
},
});
function destroyTextures(transpClass) {
transpClass._colorTexture =
transpClass._colorTexture &&
!transpClass._colorTexture.isDestroyed() &&
transpClass._colorTexture.destroy();
transpClass._accumulationTexture =
transpClass._accumulationTexture &&
!transpClass._accumulationTexture.isDestroyed() &&
transpClass._accumulationTexture.destroy();
transpClass._textureToComposite = undefined;
transpClass._translucentDepthStencilTexture =
transpClass._translucentDepthStencilTexture &&
!transpClass._translucentDepthStencilTexture.isDestroyed() &&
transpClass._translucentDepthStencilTexture.destroy();
transpClass._packedTranslucentDepth =
transpClass._packedTranslucentDepth &&
!transpClass._packedTranslucentDepth.isDestroyed() &&
transpClass._packedTranslucentDepth.destroy();
}
function destroyFramebuffers(transpClass) {
transpClass._drawClassificationFBO =
transpClass._drawClassificationFBO &&
!transpClass._drawClassificationFBO.isDestroyed() &&
transpClass._drawClassificationFBO.destroy();
transpClass._accumulationFBO =
transpClass._accumulationFBO &&
!transpClass._accumulationFBO.isDestroyed() &&
transpClass._accumulationFBO.destroy();
transpClass._packFBO =
transpClass._packFBO &&
!transpClass._packFBO.isDestroyed() &&
transpClass._packFBO.destroy();
}
function rgbaTexture(context, width, height) {
return new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
sampler: Sampler.NEAREST,
});
}
function updateTextures(transpClass, context, width, height) {
destroyTextures(transpClass);
transpClass._colorTexture = rgbaTexture(context, width, height);
transpClass._accumulationTexture = rgbaTexture(context, width, height);
transpClass._translucentDepthStencilTexture = new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.DEPTH_STENCIL,
pixelDatatype: PixelDatatype.UNSIGNED_INT_24_8,
sampler: Sampler.NEAREST,
});
transpClass._packedTranslucentDepth = new Texture({
context: context,
width: width,
height: height,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
sampler: Sampler.NEAREST,
});
}
function updateFramebuffers(transpClass, context) {
destroyFramebuffers(transpClass);
transpClass._drawClassificationFBO = new Framebuffer({
context: context,
colorTextures: [transpClass._colorTexture],
depthStencilTexture: transpClass._translucentDepthStencilTexture,
destroyAttachments: false,
});
transpClass._accumulationFBO = new Framebuffer({
context: context,
colorTextures: [transpClass._accumulationTexture],
depthStencilTexture: transpClass._translucentDepthStencilTexture,
destroyAttachments: false,
});
transpClass._packFBO = new Framebuffer({
context: context,
colorTextures: [transpClass._packedTranslucentDepth],
destroyAttachments: false,
});
}
function updateResources(
transpClass,
context,
passState,
globeDepthFramebuffer
) {
if (!transpClass.isSupported()) {
return;
}
transpClass._opaqueDepthStencilTexture =
globeDepthFramebuffer.depthStencilTexture;
var width = transpClass._opaqueDepthStencilTexture.width;
var height = transpClass._opaqueDepthStencilTexture.height;
var colorTexture = transpClass._colorTexture;
var textureChanged =
!defined(colorTexture) ||
colorTexture.width !== width ||
colorTexture.height !== height;
if (textureChanged) {
updateTextures(transpClass, context, width, height);
}
if (!defined(transpClass._drawClassificationFBO) || textureChanged) {
updateFramebuffers(transpClass, context);
}
var fs;
var uniformMap;
if (!defined(transpClass._packDepthCommand)) {
fs = new ShaderSource({
sources: [CompareAndPackTranslucentDepth],
});
uniformMap = {
u_opaqueDepthTexture: function () {
return transpClass._opaqueDepthStencilTexture;
},
u_translucentDepthTexture: function () {
return transpClass._translucentDepthStencilTexture;
},
};
transpClass._packDepthCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap,
owner: transpClass,
});
}
if (!defined(transpClass._compositeCommand)) {
fs = new ShaderSource({
sources: [CompositeTranslucentClassification],
});
uniformMap = {
colorTexture: function () {
return transpClass._textureToComposite;
},
};
if (debugShowPackedDepth) {
fs.defines = ["DEBUG_SHOW_DEPTH"];
uniformMap.u_packedTranslucentDepth = function () {
return transpClass._packedTranslucentDepth;
};
}
transpClass._compositeCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap,
owner: transpClass,
});
var compositeCommand = transpClass._compositeCommand;
var compositeProgram = compositeCommand.shaderProgram;
var compositePickProgram = context.shaderCache.createDerivedShaderProgram(
compositeProgram,
"pick",
{
vertexShaderSource: compositeProgram.vertexShaderSource,
fragmentShaderSource: new ShaderSource({
sources: fs.sources,
defines: ["PICK"],
}),
attributeLocations: compositeProgram._attributeLocations,
}
);
var compositePickCommand = DrawCommand.shallowClone(compositeCommand);
compositePickCommand.shaderProgram = compositePickProgram;
compositeCommand.derivedCommands.pick = compositePickCommand;
}
if (!defined(transpClass._copyCommand)) {
fs = new ShaderSource({
sources: [CompositeTranslucentClassification],
});
uniformMap = {
colorTexture: function () {
return transpClass._colorTexture;
},
};
transpClass._copyCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap,
owner: transpClass,
});
}
if (!defined(transpClass._accumulateCommand)) {
fs = new ShaderSource({
sources: [CompositeTranslucentClassification],
});
uniformMap = {
colorTexture: function () {
return transpClass._colorTexture;
},
};
transpClass._accumulateCommand = context.createViewportQuadCommand(fs, {
uniformMap: uniformMap,
owner: transpClass,
});
}
transpClass._viewport.width = width;
transpClass._viewport.height = height;
var useScissorTest = !BoundingRectangle.equals(
transpClass._viewport,
passState.viewport
);
var updateScissor = useScissorTest !== transpClass._useScissorTest;
transpClass._useScissorTest = useScissorTest;
if (
!BoundingRectangle.equals(transpClass._scissorRectangle, passState.viewport)
) {
transpClass._scissorRectangle = BoundingRectangle.clone(
passState.viewport,
transpClass._scissorRectangle
);
updateScissor = true;
}
if (
!defined(transpClass._rsDepth) ||
!BoundingRectangle.equals(
transpClass._viewport,
transpClass._rsDepth.viewport
) ||
updateScissor
) {
transpClass._rsDepth = RenderState.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle,
},
});
}
if (defined(transpClass._packDepthCommand)) {
transpClass._packDepthCommand.renderState = transpClass._rsDepth;
}
if (
!defined(transpClass._rsAccumulate) ||
!BoundingRectangle.equals(
transpClass._viewport,
transpClass._rsAccumulate.viewport
) ||
updateScissor
) {
transpClass._rsAccumulate = RenderState.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle,
},
stencilTest: {
enabled: true,
frontFunction: StencilFunction.EQUAL,
reference: StencilConstants.CESIUM_3D_TILE_MASK,
},
});
}
if (defined(transpClass._accumulateCommand)) {
transpClass._accumulateCommand.renderState = transpClass._rsAccumulate;
}
if (
!defined(transpClass._rsComp) ||
!BoundingRectangle.equals(
transpClass._viewport,
transpClass._rsComp.viewport
) ||
updateScissor
) {
transpClass._rsComp = RenderState.fromCache({
viewport: transpClass._viewport,
scissorTest: {
enabled: transpClass._useScissorTest,
rectangle: transpClass._scissorRectangle,
},
blending: BlendingState.ALPHA_BLEND,
});
}
if (defined(transpClass._compositeCommand)) {
transpClass._compositeCommand.renderState = transpClass._rsComp;
transpClass._compositeCommand.derivedCommands.pick.renderState =
transpClass._rsComp;
}
}
TranslucentTileClassification.prototype.executeTranslucentCommands = function (
scene,
executeCommand,
passState,
commands,
globeDepthFramebuffer
) {
// Check for translucent commands that should be classified
var length = commands.length;
var command;
var i;
var useLogDepth = scene.frameState.useLogDepth;
var context = scene.context;
var framebuffer = passState.framebuffer;
for (i = 0; i < length; ++i) {
command = commands[i];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (command.depthForTranslucentClassification) {
this._hasTranslucentDepth = true;
break;
}
}
if (!this._hasTranslucentDepth) {
return;
}
updateResources(this, context, passState, globeDepthFramebuffer);
// Get translucent depth
passState.framebuffer = this._drawClassificationFBO;
// Clear depth for multifrustum
this._clearDepthStencilCommand.execute(context, passState);
for (i = 0; i < length; ++i) {
command = commands[i];
command = useLogDepth ? command.derivedCommands.logDepth.command : command;
if (!command.depthForTranslucentClassification) {
continue;
}
// Depth-only commands are created for all translucent 3D Tiles commands
var depthOnlyCommand = command.derivedCommands.depth.depthOnlyCommand;
executeCommand(depthOnlyCommand, scene, context, passState);
}
this._frustumsDrawn += this._hasTranslucentDepth ? 1 : 0;
// Pack depth if any translucent depth commands were performed
if (this._hasTranslucentDepth) {
passState.framebuffer = this._packFBO;
this._packDepthCommand.execute(context, passState);
}
passState.framebuffer = framebuffer;
};
TranslucentTileClassification.prototype.executeClassificationCommands = function (
scene,
executeCommand,
passState,
frustumCommands
) {
if (!this._hasTranslucentDepth) {
return;
}
var context = scene.context;
var us = context.uniformState;
var framebuffer = passState.framebuffer;
if (this._frustumsDrawn === 2) {
// copy classification from first frustum
passState.framebuffer = this._accumulationFBO;
this._copyCommand.execute(context, passState);
}
passState.framebuffer = this._drawClassificationFBO;
if (this._frustumsDrawn > 1) {
this._clearColorCommand.execute(context, passState);
}
us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);
var swapGlobeDepth = us.globeDepthTexture;
us.globeDepthTexture = this._packedTranslucentDepth;
var commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION];
var length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION];
for (var i = 0; i < length; ++i) {
executeCommand(commands[i], scene, context, passState);
}
us.globeDepthTexture = swapGlobeDepth;
passState.framebuffer = framebuffer;
if (this._frustumsDrawn === 1) {
return;
}
passState.framebuffer = this._accumulationFBO;
this._accumulateCommand.execute(context, passState);
passState.framebuffer = framebuffer;
};
TranslucentTileClassification.prototype.execute = function (scene, passState) {
if (!this._hasTranslucentDepth) {
return;
}
if (this._frustumsDrawn === 1) {
this._textureToComposite = this._colorTexture;
} else {
this._textureToComposite = this._accumulationTexture;
}
var command = scene.frameState.passes.pick
? this._compositeCommand.derivedCommands.pick
: this._compositeCommand;
command.execute(scene.context, passState);
clear(this, scene, passState);
};
function clear(translucentTileClassification, scene, passState) {
if (!translucentTileClassification._hasTranslucentDepth) {
return;
}
var framebuffer = passState.framebuffer;
passState.framebuffer = translucentTileClassification._drawClassificationFBO;
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState
);
passState.framebuffer = framebuffer;
if (translucentTileClassification._frustumsDrawn > 1) {
passState.framebuffer = translucentTileClassification._accumulationFBO;
translucentTileClassification._clearColorCommand.execute(
scene._context,
passState
);
}
translucentTileClassification._hasTranslucentDepth = false;
translucentTileClassification._frustumsDrawn = 0;
}
TranslucentTileClassification.prototype.isSupported = function () {
return this._supported;
};
TranslucentTileClassification.prototype.isDestroyed = function () {
return false;
};
TranslucentTileClassification.prototype.destroy = function () {
destroyTextures(this);
destroyFramebuffers(this);
if (defined(this._compositeCommand)) {
this._compositeCommand.shaderProgram =
this._compositeCommand.shaderProgram &&
this._compositeCommand.shaderProgram.destroy();
}
if (defined(this._packDepthCommand)) {
this._packDepthCommand.shaderProgram =
this._packDepthCommand.shaderProgram &&
this._packDepthCommand.shaderProgram.destroy();
}
return destroyObject(this);
};
export default TranslucentTileClassification;

View File

@ -0,0 +1,738 @@
import ApproximateTerrainHeights from "../Core/ApproximateTerrainHeights.js";
import arraySlice from "../Core/arraySlice.js";
import Cartesian2 from "../Core/Cartesian2.js";
import Cartesian3 from "../Core/Cartesian3.js";
import Color from "../Core/Color.js";
import ComponentDatatype from "../Core/ComponentDatatype.js";
import defaultValue from "../Core/defaultValue.js";
import defined from "../Core/defined.js";
import destroyObject from "../Core/destroyObject.js";
import Ellipsoid from "../Core/Ellipsoid.js";
import FeatureDetection from "../Core/FeatureDetection.js";
import IndexDatatype from "../Core/IndexDatatype.js";
import OrientedBoundingBox from "../Core/OrientedBoundingBox.js";
import Matrix4 from "../Core/Matrix4.js";
import Rectangle from "../Core/Rectangle.js";
import TaskProcessor from "../Core/TaskProcessor.js";
import Buffer from "../Renderer/Buffer.js";
import BufferUsage from "../Renderer/BufferUsage.js";
import DrawCommand from "../Renderer/DrawCommand.js";
import Pass from "../Renderer/Pass.js";
import RenderState from "../Renderer/RenderState.js";
import ShaderProgram from "../Renderer/ShaderProgram.js";
import ShaderSource from "../Renderer/ShaderSource.js";
import VertexArray from "../Renderer/VertexArray.js";
import PolylineCommon from "../Shaders/PolylineCommon.js";
import Vector3DTileClampedPolylinesVS from "../Shaders/Vector3DTileClampedPolylinesVS.js";
import Vector3DTileClampedPolylinesFS from "../Shaders/Vector3DTileClampedPolylinesFS.js";
import when from "../ThirdParty/when.js";
import BlendingState from "./BlendingState.js";
import Cesium3DTileFeature from "./Cesium3DTileFeature.js";
import ClassificationType from "./ClassificationType.js";
import CullFace from "./CullFace.js";
import StencilConstants from "./StencilConstants.js";
import StencilFunction from "./StencilFunction.js";
import StencilOperation from "./StencilOperation.js";
/**
* Creates a batch of polylines as volumes with shader-adjustable width.
*
* @alias Vector3DTileClampedPolylines
* @constructor
*
* @param {Object} options An object with following properties:
* @param {Uint16Array} options.positions The positions of the polylines
* @param {Uint32Array} options.counts The number or positions in the each polyline.
* @param {Uint16Array} options.widths The width of each polyline.
* @param {Number} options.minimumHeight The minimum height of the tile's region.
* @param {Number} options.maximumHeight The maximum height of the tile's region.
* @param {Rectangle} options.rectangle The rectangle containing the tile.
* @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.
* @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polylines.
* @param {Uint16Array} options.batchIds The batch ids for each polyline.
* @param {Cesium3DTileset} options.tileset Tileset carrying minimum and maximum clamping heights.
*
* @private
*/
function Vector3DTileClampedPolylines(options) {
// these arrays hold data from the tile payload
// and are all released after the first update.
this._positions = options.positions;
this._widths = options.widths;
this._counts = options.counts;
this._batchIds = options.batchIds;
this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);
this._minimumHeight = options.minimumHeight;
this._maximumHeight = options.maximumHeight;
this._center = options.center;
this._rectangle = options.rectangle;
this._batchTable = options.batchTable;
this._va = undefined;
this._sp = undefined;
this._rs = undefined;
this._uniformMap = undefined;
this._command = undefined;
this._transferrableBatchIds = undefined;
this._packedBuffer = undefined;
this._tileset = options.tileset;
this._minimumMaximumVectorHeights = new Cartesian2(
ApproximateTerrainHeights._defaultMinTerrainHeight,
ApproximateTerrainHeights._defaultMaxTerrainHeight
);
this._boundingVolume = OrientedBoundingBox.fromRectangle(
options.rectangle,
ApproximateTerrainHeights._defaultMinTerrainHeight,
ApproximateTerrainHeights._defaultMaxTerrainHeight,
this._ellipsoid
);
// Fat vertices - all information for each volume packed to a vec3 and 5 vec4s
this._startEllipsoidNormals = undefined;
this._endEllipsoidNormals = undefined;
this._startPositionAndHeights = undefined;
this._startFaceNormalAndVertexCornerIds = undefined;
this._endPositionAndHeights = undefined;
this._endFaceNormalAndHalfWidths = undefined;
this._vertexBatchIds = undefined;
this._indices = undefined;
this._constantColor = Color.clone(Color.WHITE);
this._highlightColor = this._constantColor;
this._trianglesLength = 0;
this._geometryByteLength = 0;
this._ready = false;
this._readyPromise = when.defer();
this._verticesPromise = undefined;
var that = this;
ApproximateTerrainHeights.initialize()
.then(function () {
updateMinimumMaximumHeights(that, that._rectangle, that._ellipsoid);
})
.otherwise(function (error) {
this._readyPromise.reject(error);
});
}
Object.defineProperties(Vector3DTileClampedPolylines.prototype, {
/**
* Gets the number of triangles.
*
* @memberof Vector3DTileClampedPolylines.prototype
*
* @type {Number}
* @readonly
*/
trianglesLength: {
get: function () {
return this._trianglesLength;
},
},
/**
* Gets the geometry memory in bytes.
*
* @memberof Vector3DTileClampedPolylines.prototype
*
* @type {Number}
* @readonly
*/
geometryByteLength: {
get: function () {
return this._geometryByteLength;
},
},
/**
* Gets a promise that resolves when the primitive is ready to render.
* @memberof Vector3DTileClampedPolylines.prototype
* @type {Promise}
* @readonly
*/
readyPromise: {
get: function () {
return this._readyPromise.promise;
},
},
});
function updateMinimumMaximumHeights(polylines, rectangle, ellipsoid) {
var result = ApproximateTerrainHeights.getMinimumMaximumHeights(
rectangle,
ellipsoid
);
var min = result.minimumTerrainHeight;
var max = result.maximumTerrainHeight;
var minimumMaximumVectorHeights = polylines._minimumMaximumVectorHeights;
minimumMaximumVectorHeights.x = min;
minimumMaximumVectorHeights.y = max;
var obb = polylines._boundingVolume;
var rect = polylines._rectangle;
OrientedBoundingBox.fromRectangle(rect, min, max, ellipsoid, obb);
}
function packBuffer(polylines) {
var rectangle = polylines._rectangle;
var minimumHeight = polylines._minimumHeight;
var maximumHeight = polylines._maximumHeight;
var ellipsoid = polylines._ellipsoid;
var center = polylines._center;
var packedLength =
2 +
Rectangle.packedLength +
Ellipsoid.packedLength +
Cartesian3.packedLength;
var packedBuffer = new Float64Array(packedLength);
var offset = 0;
packedBuffer[offset++] = minimumHeight;
packedBuffer[offset++] = maximumHeight;
Rectangle.pack(rectangle, packedBuffer, offset);
offset += Rectangle.packedLength;
Ellipsoid.pack(ellipsoid, packedBuffer, offset);
offset += Ellipsoid.packedLength;
Cartesian3.pack(center, packedBuffer, offset);
return packedBuffer;
}
var createVerticesTaskProcessor = new TaskProcessor(
"createVectorTileClampedPolylines"
);
var attributeLocations = {
startEllipsoidNormal: 0,
endEllipsoidNormal: 1,
startPositionAndHeight: 2,
endPositionAndHeight: 3,
startFaceNormalAndVertexCorner: 4,
endFaceNormalAndHalfWidth: 5,
a_batchId: 6,
};
function createVertexArray(polylines, context) {
if (defined(polylines._va)) {
return;
}
if (!defined(polylines._verticesPromise)) {
var positions = polylines._positions;
var widths = polylines._widths;
var counts = polylines._counts;
var batchIds = polylines._transferrableBatchIds;
var packedBuffer = polylines._packedBuffer;
if (!defined(packedBuffer)) {
// Copy because they may be the views on the same buffer.
positions = polylines._positions = arraySlice(positions);
widths = polylines._widths = arraySlice(widths);
counts = polylines._counts = arraySlice(counts);
batchIds = polylines._transferrableBatchIds = arraySlice(
polylines._batchIds
);
packedBuffer = polylines._packedBuffer = packBuffer(polylines);
}
var transferrableObjects = [
positions.buffer,
widths.buffer,
counts.buffer,
batchIds.buffer,
packedBuffer.buffer,
];
var parameters = {
positions: positions.buffer,
widths: widths.buffer,
counts: counts.buffer,
batchIds: batchIds.buffer,
packedBuffer: packedBuffer.buffer,
};
var verticesPromise = (polylines._verticesPromise = createVerticesTaskProcessor.scheduleTask(
parameters,
transferrableObjects
));
if (!defined(verticesPromise)) {
// Postponed
return;
}
when(verticesPromise, function (result) {
polylines._startEllipsoidNormals = new Float32Array(
result.startEllipsoidNormals
);
polylines._endEllipsoidNormals = new Float32Array(
result.endEllipsoidNormals
);
polylines._startPositionAndHeights = new Float32Array(
result.startPositionAndHeights
);
polylines._startFaceNormalAndVertexCornerIds = new Float32Array(
result.startFaceNormalAndVertexCornerIds
);
polylines._endPositionAndHeights = new Float32Array(
result.endPositionAndHeights
);
polylines._endFaceNormalAndHalfWidths = new Float32Array(
result.endFaceNormalAndHalfWidths
);
polylines._vertexBatchIds = new Uint16Array(result.vertexBatchIds);
var indexDatatype = result.indexDatatype;
polylines._indices =
indexDatatype === IndexDatatype.UNSIGNED_SHORT
? new Uint16Array(result.indices)
: new Uint32Array(result.indices);
polylines._ready = true;
}).otherwise(function (error) {
polylines._readyPromise.reject(error);
});
}
if (polylines._ready && !defined(polylines._va)) {
var startEllipsoidNormals = polylines._startEllipsoidNormals;
var endEllipsoidNormals = polylines._endEllipsoidNormals;
var startPositionAndHeights = polylines._startPositionAndHeights;
var endPositionAndHeights = polylines._endPositionAndHeights;
var startFaceNormalAndVertexCornerIds =
polylines._startFaceNormalAndVertexCornerIds;
var endFaceNormalAndHalfWidths = polylines._endFaceNormalAndHalfWidths;
var batchIdAttribute = polylines._vertexBatchIds;
var indices = polylines._indices;
var byteLength =
startEllipsoidNormals.byteLength + endEllipsoidNormals.byteLength;
byteLength +=
startPositionAndHeights.byteLength + endPositionAndHeights.byteLength;
byteLength +=
startFaceNormalAndVertexCornerIds.byteLength +
endFaceNormalAndHalfWidths.byteLength;
byteLength += batchIdAttribute.byteLength + indices.byteLength;
polylines._trianglesLength = indices.length / 3;
polylines._geometryByteLength = byteLength;
var startEllipsoidNormalsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: startEllipsoidNormals,
usage: BufferUsage.STATIC_DRAW,
});
var endEllipsoidNormalsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: endEllipsoidNormals,
usage: BufferUsage.STATIC_DRAW,
});
var startPositionAndHeightsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: startPositionAndHeights,
usage: BufferUsage.STATIC_DRAW,
});
var endPositionAndHeightsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: endPositionAndHeights,
usage: BufferUsage.STATIC_DRAW,
});
var startFaceNormalAndVertexCornerIdsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: startFaceNormalAndVertexCornerIds,
usage: BufferUsage.STATIC_DRAW,
});
var endFaceNormalAndHalfWidthsBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: endFaceNormalAndHalfWidths,
usage: BufferUsage.STATIC_DRAW,
});
var batchIdAttributeBuffer = Buffer.createVertexBuffer({
context: context,
typedArray: batchIdAttribute,
usage: BufferUsage.STATIC_DRAW,
});
var indexBuffer = Buffer.createIndexBuffer({
context: context,
typedArray: indices,
usage: BufferUsage.STATIC_DRAW,
indexDatatype:
indices.BYTES_PER_ELEMENT === 2
? IndexDatatype.UNSIGNED_SHORT
: IndexDatatype.UNSIGNED_INT,
});
var vertexAttributes = [
{
index: attributeLocations.startEllipsoidNormal,
vertexBuffer: startEllipsoidNormalsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
},
{
index: attributeLocations.endEllipsoidNormal,
vertexBuffer: endEllipsoidNormalsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 3,
},
{
index: attributeLocations.startPositionAndHeight,
vertexBuffer: startPositionAndHeightsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 4,
},
{
index: attributeLocations.endPositionAndHeight,
vertexBuffer: endPositionAndHeightsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 4,
},
{
index: attributeLocations.startFaceNormalAndVertexCorner,
vertexBuffer: startFaceNormalAndVertexCornerIdsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 4,
},
{
index: attributeLocations.endFaceNormalAndHalfWidth,
vertexBuffer: endFaceNormalAndHalfWidthsBuffer,
componentDatatype: ComponentDatatype.FLOAT,
componentsPerAttribute: 4,
},
{
index: attributeLocations.a_batchId,
vertexBuffer: batchIdAttributeBuffer,
componentDatatype: ComponentDatatype.UNSIGNED_SHORT,
componentsPerAttribute: 1,
},
];
polylines._va = new VertexArray({
context: context,
attributes: vertexAttributes,
indexBuffer: indexBuffer,
});
polylines._positions = undefined;
polylines._widths = undefined;
polylines._counts = undefined;
polylines._ellipsoid = undefined;
polylines._minimumHeight = undefined;
polylines._maximumHeight = undefined;
polylines._rectangle = undefined;
polylines._transferrableBatchIds = undefined;
polylines._packedBuffer = undefined;
polylines._startEllipsoidNormals = undefined;
polylines._endEllipsoidNormals = undefined;
polylines._startPositionAndHeights = undefined;
polylines._startFaceNormalAndVertexCornerIds = undefined;
polylines._endPositionAndHeights = undefined;
polylines._endFaceNormalAndHalfWidths = undefined;
polylines._vertexBatchIds = undefined;
polylines._indices = undefined;
polylines._readyPromise.resolve();
}
}
var modifiedModelViewScratch = new Matrix4();
var rtcScratch = new Cartesian3();
function createUniformMap(primitive, context) {
if (defined(primitive._uniformMap)) {
return;
}
primitive._uniformMap = {
u_modifiedModelView: function () {
var viewMatrix = context.uniformState.view;
Matrix4.clone(viewMatrix, modifiedModelViewScratch);
Matrix4.multiplyByPoint(
modifiedModelViewScratch,
primitive._center,
rtcScratch
);
Matrix4.setTranslation(
modifiedModelViewScratch,
rtcScratch,
modifiedModelViewScratch
);
return modifiedModelViewScratch;
},
u_highlightColor: function () {
return primitive._highlightColor;
},
u_minimumMaximumVectorHeights: function () {
return primitive._minimumMaximumVectorHeights;
},
};
}
function getRenderState(mask3DTiles) {
/**
* Cull front faces of each volume (relative to camera) to prevent
* classification drawing from both the front and back faces, double-draw.
* The geometry is "inverted" (inside-out winding order for the indices) but
* the vertex shader seems to re-invert so that the triangles face "out" again.
* So cull FRONT faces.
*/
return RenderState.fromCache({
cull: {
enabled: true,
face: CullFace.FRONT,
},
blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
depthMask: false,
stencilTest: {
enabled: mask3DTiles,
frontFunction: StencilFunction.EQUAL,
frontOperation: {
fail: StencilOperation.KEEP,
zFail: StencilOperation.KEEP,
zPass: StencilOperation.KEEP,
},
backFunction: StencilFunction.EQUAL,
backOperation: {
fail: StencilOperation.KEEP,
zFail: StencilOperation.KEEP,
zPass: StencilOperation.KEEP,
},
reference: StencilConstants.CESIUM_3D_TILE_MASK,
mask: StencilConstants.CESIUM_3D_TILE_MASK,
},
});
}
function createRenderStates(primitive) {
if (defined(primitive._rs)) {
return;
}
primitive._rs = getRenderState(false);
primitive._rs3DTiles = getRenderState(true);
}
function createShaders(primitive, context) {
if (defined(primitive._sp)) {
return;
}
var batchTable = primitive._batchTable;
var vsSource = batchTable.getVertexShaderCallback(
false,
"a_batchId",
undefined
)(Vector3DTileClampedPolylinesVS);
var fsSource = batchTable.getFragmentShaderCallback(
false,
undefined,
true
)(Vector3DTileClampedPolylinesFS);
var vs = new ShaderSource({
defines: [
"VECTOR_TILE",
!FeatureDetection.isInternetExplorer() ? "CLIP_POLYLINE" : "",
],
sources: [PolylineCommon, vsSource],
});
var fs = new ShaderSource({
defines: ["VECTOR_TILE"],
sources: [fsSource],
});
primitive._sp = ShaderProgram.fromCache({
context: context,
vertexShaderSource: vs,
fragmentShaderSource: fs,
attributeLocations: attributeLocations,
});
}
function queueCommands(primitive, frameState) {
var command = primitive._command;
if (!defined(primitive._command)) {
var uniformMap = primitive._batchTable.getUniformMapCallback()(
primitive._uniformMap
);
command = primitive._command = new DrawCommand({
owner: primitive,
vertexArray: primitive._va,
renderState: primitive._rs,
shaderProgram: primitive._sp,
uniformMap: uniformMap,
boundingVolume: primitive._boundingVolume,
pass: Pass.TERRAIN_CLASSIFICATION,
pickId: primitive._batchTable.getPickId(),
});
var derivedTilesetCommand = DrawCommand.shallowClone(
command,
command.derivedCommands.tileset
);
derivedTilesetCommand.renderState = primitive._rs3DTiles;
derivedTilesetCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;
command.derivedCommands.tileset = derivedTilesetCommand;
}
var classificationType = primitive._tileset.classificationType;
if (
classificationType === ClassificationType.TERRAIN ||
classificationType === ClassificationType.BOTH
) {
frameState.commandList.push(command);
}
if (
classificationType === ClassificationType.CESIUM_3D_TILE ||
classificationType === ClassificationType.BOTH
) {
frameState.commandList.push(command.derivedCommands.tileset);
}
}
/**
* Creates features for each polyline and places it at the batch id index of features.
*
* @param {Vector3DTileContent} content The vector tile content.
* @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.
*/
Vector3DTileClampedPolylines.prototype.createFeatures = function (
content,
features
) {
var batchIds = this._batchIds;
var length = batchIds.length;
for (var i = 0; i < length; ++i) {
var batchId = batchIds[i];
features[batchId] = new Cesium3DTileFeature(content, batchId);
}
};
/**
* Colors the entire tile when enabled is true. The resulting color will be (polyline batch table color * color).
*
* @param {Boolean} enabled Whether to enable debug coloring.
* @param {Color} color The debug color.
*/
Vector3DTileClampedPolylines.prototype.applyDebugSettings = function (
enabled,
color
) {
this._highlightColor = enabled ? color : this._constantColor;
};
function clearStyle(polygons, features) {
var batchIds = polygons._batchIds;
var length = batchIds.length;
for (var i = 0; i < length; ++i) {
var batchId = batchIds[i];
var feature = features[batchId];
feature.show = true;
feature.color = Color.WHITE;
}
}
var scratchColor = new Color();
var DEFAULT_COLOR_VALUE = Color.WHITE;
var DEFAULT_SHOW_VALUE = true;
/**
* Apply a style to the content.
*
* @param {Cesium3DTileStyle} style The style.
* @param {Cesium3DTileFeature[]} features The dictionary of features.
*/
Vector3DTileClampedPolylines.prototype.applyStyle = function (style, features) {
if (!defined(style)) {
clearStyle(this, features);
return;
}
var batchIds = this._batchIds;
var length = batchIds.length;
for (var i = 0; i < length; ++i) {
var batchId = batchIds[i];
var feature = features[batchId];
feature.color = defined(style.color)
? style.color.evaluateColor(feature, scratchColor)
: DEFAULT_COLOR_VALUE;
feature.show = defined(style.show)
? style.show.evaluate(feature)
: DEFAULT_SHOW_VALUE;
}
};
/**
* Updates the batches and queues the commands for rendering.
*
* @param {FrameState} frameState The current frame state.
*/
Vector3DTileClampedPolylines.prototype.update = function (frameState) {
var context = frameState.context;
createVertexArray(this, context);
createUniformMap(this, context);
createShaders(this, context);
createRenderStates(this);
if (!this._ready) {
return;
}
var passes = frameState.passes;
if (passes.render || passes.pick) {
queueCommands(this, frameState);
}
};
/**
* Returns true if this object was destroyed; otherwise, false.
* <p>
* If this object was destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
* </p>
*
* @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
*/
Vector3DTileClampedPolylines.prototype.isDestroyed = function () {
return false;
};
/**
* Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
* release of WebGL resources, instead of relying on the garbage collector to destroy this object.
* <p>
* Once an object is destroyed, it should not be used; calling any function other than
* <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
* assign the return value (<code>undefined</code>) to the object as done in the example.
* </p>
*
* @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
*/
Vector3DTileClampedPolylines.prototype.destroy = function () {
this._va = this._va && this._va.destroy();
this._sp = this._sp && this._sp.destroy();
return destroyObject(this);
};
export default Vector3DTileClampedPolylines;

View File

@ -16,6 +16,8 @@ import Cesium3DTileFeatureTable from "./Cesium3DTileFeatureTable.js";
import Vector3DTilePoints from "./Vector3DTilePoints.js";
import Vector3DTilePolygons from "./Vector3DTilePolygons.js";
import Vector3DTilePolylines from "./Vector3DTilePolylines.js";
import Vector3DTileClampedPolylines from "./Vector3DTileClampedPolylines.js";
import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions.js";
/**
* Represents the contents of a
@ -248,6 +250,14 @@ function getBatchIds(featureTableJson, featureTableBinary) {
var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
function createFloatingPolylines(options) {
return new Vector3DTilePolylines(options);
}
function createClampedPolylines(options) {
return new Vector3DTileClampedPolylines(options);
}
function initialize(content, arrayBuffer, byteOffset) {
byteOffset = defaultValue(byteOffset, 0);
@ -533,7 +543,32 @@ function initialize(content, arrayBuffer, byteOffset) {
);
byteOffset += polylinePositionByteLength;
content._polylines = new Vector3DTilePolylines({
var tileset = content._tileset;
var examineVectorLinesFunction = tileset.examineVectorLinesFunction;
if (defined(examineVectorLinesFunction)) {
var decodedPositions = decodeVectorPolylinePositions(
new Uint16Array(polylinePositions),
rectangle,
minHeight,
maxHeight,
Ellipsoid.WGS84
);
examineVectorLines(
decodedPositions,
polylineCounts,
batchIds.polylines,
batchTable,
content.url,
examineVectorLinesFunction
);
}
var createPolylines = createFloatingPolylines;
if (defined(tileset.classificationType)) {
createPolylines = createClampedPolylines;
}
content._polylines = createPolylines({
positions: polylinePositions,
widths: widths,
counts: polylineCounts,
@ -544,6 +579,7 @@ function initialize(content, arrayBuffer, byteOffset) {
rectangle: rectangle,
boundingVolume: content.tile.boundingVolume.boundingVolume,
batchTable: batchTable,
tileset: tileset,
});
}
@ -664,6 +700,9 @@ Vector3DTileContent.prototype.update = function (tileset, frameState) {
.all([pointsPromise, polygonPromise, polylinePromise])
.then(function () {
that._readyPromise.resolve(that);
})
.otherwise(function (error) {
that._readyPromise.reject(error);
});
}
};
@ -679,4 +718,24 @@ Vector3DTileContent.prototype.destroy = function () {
this._batchTable = this._batchTable && this._batchTable.destroy();
return destroyObject(this);
};
function examineVectorLines(
positions,
counts,
batchIds,
batchTable,
url,
callback
) {
var countsLength = counts.length;
var polylineStart = 0;
for (var i = 0; i < countsLength; i++) {
var count = counts[i] * 3;
var linePositions = positions.slice(polylineStart, polylineStart + count);
polylineStart += count;
callback(linePositions, batchIds[i], url, batchTable);
}
}
export default Vector3DTileContent;

View File

@ -432,11 +432,11 @@ function createShaders(primitive, context) {
"a_batchId",
undefined
)(Vector3DTilePolylinesVS);
var fsSource = batchTable.getFragmentShaderCallback()(
PolylineFS,
var fsSource = batchTable.getFragmentShaderCallback(
false,
undefined
);
undefined,
false
)(PolylineFS);
var vs = new ShaderSource({
defines: [

View File

@ -302,11 +302,11 @@ function createShaders(primitive, context) {
"a_batchId",
undefined
)(VectorTileVS);
var fsSource = batchTable.getFragmentShaderCallback()(
ShadowVolumeFS,
var fsSource = batchTable.getFragmentShaderCallback(
false,
undefined
);
undefined,
true
)(ShadowVolumeFS);
pickId = batchTable.getPickId();
@ -427,7 +427,7 @@ var colorRenderState = {
enabled: false,
},
depthMask: false,
blending: BlendingState.ALPHA_BLEND,
blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,
};
var pickRenderState = {

View File

@ -19,6 +19,7 @@ import PickFramebuffer from "./PickFramebuffer.js";
import SceneFramebuffer from "./SceneFramebuffer.js";
import SceneMode from "./SceneMode.js";
import ShadowMap from "./ShadowMap.js";
import TranslucentTileClassification from "./TranslucentTileClassification.js";
function CommandExtent() {
this.command = undefined;
@ -58,6 +59,9 @@ function View(scene, camera, viewport) {
this.globeDepth = globeDepth;
this.globeTranslucencyFramebuffer = new GlobeTranslucencyFramebuffer();
this.oit = oit;
this.translucentTileClassification = new TranslucentTileClassification(
context
);
this.pickDepths = [];
this.debugGlobeDepths = [];
this.frustumCommandsList = [];
@ -411,6 +415,9 @@ View.prototype.destroy = function () {
this.sceneFramebuffer && this.sceneFramebuffer.destroy();
this.globeDepth = this.globeDepth && this.globeDepth.destroy();
this.oit = this.oit && this.oit.destroy();
this.translucentTileClassification =
this.translucentTileClassification &&
this.translucentTileClassification.destroy();
this.globeTranslucencyFramebuffer =
this.globeTranslucencyFramebuffer &&
this.globeTranslucencyFramebuffer.destroy();

View File

@ -0,0 +1,12 @@
uniform sampler2D u_opaqueDepthTexture;
uniform sampler2D u_translucentDepthTexture;
varying vec2 v_textureCoordinates;
void main()
{
float opaqueDepth = texture2D(u_opaqueDepthTexture, v_textureCoordinates).r;
float translucentDepth = texture2D(u_translucentDepthTexture, v_textureCoordinates).r;
translucentDepth = czm_branchFreeTernary(translucentDepth > opaqueDepth, 1.0, translucentDepth);
gl_FragColor = czm_packDepth(translucentDepth);
}

View File

@ -0,0 +1,31 @@
uniform sampler2D colorTexture;
#ifdef DEBUG_SHOW_DEPTH
uniform sampler2D u_packedTranslucentDepth;
#endif
varying vec2 v_textureCoordinates;
void main()
{
#ifdef DEBUG_SHOW_DEPTH
if (v_textureCoordinates.x < 0.5)
{
gl_FragColor.rgb = vec3(czm_unpackDepth(texture2D(u_packedTranslucentDepth, v_textureCoordinates)));
gl_FragColor.a = 1.0;
}
#else
vec4 color = texture2D(colorTexture, v_textureCoordinates);
#ifdef PICK
if (color == vec4(0.0))
{
discard;
}
#else
// Reverse premultiplication process to get the correct composited result of the classification primitives
color.rgb /= color.a;
#endif
gl_FragColor = color;
#endif
}

View File

@ -71,7 +71,11 @@ void main(void)
#ifdef PICK
#ifdef CULL_FRAGMENTS
if (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0) {
// When classifying translucent geometry, logDepthOrDepth == 0.0
// indicates a region that should not be classified, possibly due to there
// being opaque pixels there in another buffer.
// Check for logDepthOrDepth != 0.0 to make sure this should be classified.
if (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0 || logDepthOrDepth != 0.0) {
gl_FragColor.a = 1.0; // 0.0 alpha leads to discard from ShaderSource.createPickFragmentShaderSource
czm_writeDepthClamp();
}
@ -81,7 +85,10 @@ void main(void)
#else // PICK
#ifdef CULL_FRAGMENTS
if (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y) {
// When classifying translucent geometry, logDepthOrDepth == 0.0
// indicates a region that should not be classified, possibly due to there
// being opaque pixels there in another buffer.
if (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y || logDepthOrDepth == 0.0) {
discard;
}
#endif

View File

@ -0,0 +1,52 @@
#ifdef GL_EXT_frag_depth
#extension GL_EXT_frag_depth : enable
#endif
varying vec4 v_startPlaneEC;
varying vec4 v_endPlaneEC;
varying vec4 v_rightPlaneEC;
varying float v_halfWidth;
varying vec3 v_volumeUpEC;
uniform vec4 u_highlightColor;
void main()
{
float logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)));
// Discard for sky
if (logDepthOrDepth == 0.0) {
#ifdef DEBUG_SHOW_VOLUME
gl_FragColor = vec4(0.0, 0.0, 1.0, 0.5);
return;
#else // DEBUG_SHOW_VOLUME
discard;
#endif // DEBUG_SHOW_VOLUME
}
vec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);
eyeCoordinate /= eyeCoordinate.w;
float halfMaxWidth = v_halfWidth * czm_metersPerPixel(eyeCoordinate);
// Expand halfMaxWidth if direction to camera is almost perpendicular with the volume's up direction
halfMaxWidth += halfMaxWidth * (1.0 - dot(-normalize(eyeCoordinate.xyz), v_volumeUpEC));
// Check distance of the eye coordinate against the right-facing plane
float widthwiseDistance = czm_planeDistance(v_rightPlaneEC, eyeCoordinate.xyz);
// Check eye coordinate against the mitering planes
float distanceFromStart = czm_planeDistance(v_startPlaneEC, eyeCoordinate.xyz);
float distanceFromEnd = czm_planeDistance(v_endPlaneEC, eyeCoordinate.xyz);
if (abs(widthwiseDistance) > halfMaxWidth || distanceFromStart < 0.0 || distanceFromEnd < 0.0) {
#ifdef DEBUG_SHOW_VOLUME
gl_FragColor = vec4(logDepthOrDepth, 0.0, 0.0, 0.5);
return;
#else // DEBUG_SHOW_VOLUME
discard;
#endif // DEBUG_SHOW_VOLUME
}
gl_FragColor = u_highlightColor;
czm_writeDepthClamp();
}

View File

@ -0,0 +1,85 @@
attribute vec3 startEllipsoidNormal;
attribute vec3 endEllipsoidNormal;
attribute vec4 startPositionAndHeight;
attribute vec4 endPositionAndHeight;
attribute vec4 startFaceNormalAndVertexCorner;
attribute vec4 endFaceNormalAndHalfWidth;
attribute float a_batchId;
uniform mat4 u_modifiedModelView;
uniform vec2 u_minimumMaximumVectorHeights;
varying vec4 v_startPlaneEC;
varying vec4 v_endPlaneEC;
varying vec4 v_rightPlaneEC;
varying float v_halfWidth;
varying vec3 v_volumeUpEC;
void main()
{
// vertex corner IDs
// 3-----------7
// /| left /|
// / | 1 / |
// 2-----------6 5 end
// | / | /
// start |/ right |/
// 0-----------4
//
float isEnd = floor(startFaceNormalAndVertexCorner.w * 0.251); // 0 for front, 1 for end
float isTop = floor(startFaceNormalAndVertexCorner.w * mix(0.51, 0.19, isEnd)); // 0 for bottom, 1 for top
vec3 forward = endPositionAndHeight.xyz - startPositionAndHeight.xyz;
vec3 right = normalize(cross(forward, startEllipsoidNormal));
vec4 position = vec4(startPositionAndHeight.xyz, 1.0);
position.xyz += forward * isEnd;
v_volumeUpEC = czm_normal * normalize(cross(right, forward));
// Push for volume height
float offset;
vec3 ellipsoidNormal = mix(startEllipsoidNormal, endEllipsoidNormal, isEnd);
// offset height to create volume
offset = mix(startPositionAndHeight.w, endPositionAndHeight.w, isEnd);
offset = mix(u_minimumMaximumVectorHeights.y, u_minimumMaximumVectorHeights.x, isTop) - offset;
position.xyz += offset * ellipsoidNormal;
// move from RTC to EC
position = u_modifiedModelView * position;
right = czm_normal * right;
// Push for width in a direction that is in the start or end plane and in a plane with right
// N = normalEC ("right-facing" direction for push)
// R = right
// p = angle between N and R
// w = distance to push along R if R == N
// d = distance to push along N
//
// N R
// { \ p| } * cos(p) = dot(N, R) = w / d
// d\ \ | |w * d = w / dot(N, R)
// { \| }
// o---------- polyline segment ---->
//
vec3 scratchNormal = mix(-startFaceNormalAndVertexCorner.xyz, endFaceNormalAndHalfWidth.xyz, isEnd);
scratchNormal = cross(scratchNormal, mix(startEllipsoidNormal, endEllipsoidNormal, isEnd));
vec3 miterPushNormal = czm_normal * normalize(scratchNormal);
offset = 2.0 * endFaceNormalAndHalfWidth.w * max(0.0, czm_metersPerPixel(position)); // offset = widthEC
offset = offset / dot(miterPushNormal, right);
position.xyz += miterPushNormal * (offset * sign(0.5 - mod(startFaceNormalAndVertexCorner.w, 2.0)));
gl_Position = czm_depthClamp(czm_projection * position);
position = u_modifiedModelView * vec4(startPositionAndHeight.xyz, 1.0);
vec3 startNormalEC = czm_normal * startFaceNormalAndVertexCorner.xyz;
v_startPlaneEC = vec4(startNormalEC, -dot(startNormalEC, position.xyz));
v_rightPlaneEC = vec4(right, -dot(right, position.xyz));
position = u_modifiedModelView * vec4(endPositionAndHeight.xyz, 1.0);
vec3 endNormalEC = czm_normal * endFaceNormalAndHalfWidth.xyz;
v_endPlaneEC = vec4(endNormalEC, -dot(endNormalEC, position.xyz));
v_halfWidth = endFaceNormalAndHalfWidth.w;
}

View File

@ -0,0 +1,508 @@
import AttributeCompression from "../Core/AttributeCompression.js";
import Cartesian3 from "../Core/Cartesian3.js";
import Cartographic from "../Core/Cartographic.js";
import Ellipsoid from "../Core/Ellipsoid.js";
import IndexDatatype from "../Core/IndexDatatype.js";
import CesiumMath from "../Core/Math.js";
import Rectangle from "../Core/Rectangle.js";
import createTaskProcessorWorker from "./createTaskProcessorWorker.js";
var MAX_SHORT = 32767;
var MITER_BREAK = Math.cos(CesiumMath.toRadians(150.0));
var scratchBVCartographic = new Cartographic();
var scratchEncodedPosition = new Cartesian3();
function decodePositionsToRtc(
uBuffer,
vBuffer,
heightBuffer,
rectangle,
minimumHeight,
maximumHeight,
ellipsoid,
center
) {
var positionsLength = uBuffer.length;
var decodedPositions = new Float32Array(positionsLength * 3);
for (var i = 0; i < positionsLength; ++i) {
var u = uBuffer[i];
var v = vBuffer[i];
var h = heightBuffer[i];
var lon = CesiumMath.lerp(rectangle.west, rectangle.east, u / MAX_SHORT);
var lat = CesiumMath.lerp(rectangle.south, rectangle.north, v / MAX_SHORT);
var alt = CesiumMath.lerp(minimumHeight, maximumHeight, h / MAX_SHORT);
var cartographic = Cartographic.fromRadians(
lon,
lat,
alt,
scratchBVCartographic
);
var decodedPosition = ellipsoid.cartographicToCartesian(
cartographic,
scratchEncodedPosition
);
var rtc = Cartesian3.subtract(
decodedPosition,
center,
scratchEncodedPosition
);
Cartesian3.pack(rtc, decodedPositions, i * 3);
}
return decodedPositions;
}
var previousCompressedCartographicScratch = new Cartographic();
var currentCompressedCartographicScratch = new Cartographic();
function removeDuplicates(uBuffer, vBuffer, heightBuffer, counts) {
var countsLength = counts.length;
var positionsLength = uBuffer.length;
var markRemoval = new Uint8Array(positionsLength);
var previous = previousCompressedCartographicScratch;
var current = currentCompressedCartographicScratch;
var offset = 0;
for (var i = 0; i < countsLength; i++) {
var count = counts[i];
var updatedCount = count;
for (var j = 1; j < count; j++) {
var index = offset + j;
var previousIndex = index - 1;
current.longitude = uBuffer[index];
current.latitude = vBuffer[index];
previous.longitude = uBuffer[previousIndex];
previous.latitude = vBuffer[previousIndex];
if (Cartographic.equals(current, previous)) {
updatedCount--;
markRemoval[previousIndex] = 1;
}
}
counts[i] = updatedCount;
offset += count;
}
var nextAvailableIndex = 0;
for (var k = 0; k < positionsLength; k++) {
if (markRemoval[k] !== 1) {
uBuffer[nextAvailableIndex] = uBuffer[k];
vBuffer[nextAvailableIndex] = vBuffer[k];
heightBuffer[nextAvailableIndex] = heightBuffer[k];
nextAvailableIndex++;
}
}
}
function VertexAttributesAndIndices(volumesCount) {
var vertexCount = volumesCount * 8;
var vec3Floats = vertexCount * 3;
var vec4Floats = vertexCount * 4;
this.startEllipsoidNormals = new Float32Array(vec3Floats);
this.endEllipsoidNormals = new Float32Array(vec3Floats);
this.startPositionAndHeights = new Float32Array(vec4Floats);
this.startFaceNormalAndVertexCornerIds = new Float32Array(vec4Floats);
this.endPositionAndHeights = new Float32Array(vec4Floats);
this.endFaceNormalAndHalfWidths = new Float32Array(vec4Floats);
this.vertexBatchIds = new Uint16Array(vertexCount);
this.indices = IndexDatatype.createTypedArray(vertexCount, 36 * volumesCount);
this.vec3Offset = 0;
this.vec4Offset = 0;
this.batchIdOffset = 0;
this.indexOffset = 0;
this.volumeStartIndex = 0;
}
var towardCurrScratch = new Cartesian3();
var towardNextScratch = new Cartesian3();
function computeMiteredNormal(
previousPosition,
position,
nextPosition,
ellipsoidSurfaceNormal,
result
) {
var towardNext = Cartesian3.subtract(
nextPosition,
position,
towardNextScratch
);
var towardCurr = Cartesian3.subtract(
position,
previousPosition,
towardCurrScratch
);
Cartesian3.normalize(towardNext, towardNext);
Cartesian3.normalize(towardCurr, towardCurr);
if (Cartesian3.dot(towardNext, towardCurr) < MITER_BREAK) {
towardCurr = Cartesian3.multiplyByScalar(
towardCurr,
-1.0,
towardCurrScratch
);
}
Cartesian3.add(towardNext, towardCurr, result);
if (Cartesian3.equals(result, Cartesian3.ZERO)) {
result = Cartesian3.subtract(previousPosition, position);
}
// Make sure the normal is orthogonal to the ellipsoid surface normal
Cartesian3.cross(result, ellipsoidSurfaceNormal, result);
Cartesian3.cross(ellipsoidSurfaceNormal, result, result);
Cartesian3.normalize(result, result);
return result;
}
// Winding order is reversed so each segment's volume is inside-out
// 3-----------7
// /| left /|
// / | 1 / |
// 2-----------6 5 end
// | / | /
// start |/ right |/
// 0-----------4
//
var REFERENCE_INDICES = [
0,
2,
6,
0,
6,
4, // right
0,
1,
3,
0,
3,
2, // start face
0,
4,
5,
0,
5,
1, // bottom
5,
3,
1,
5,
7,
3, // left
7,
5,
4,
7,
4,
6, // end face
7,
6,
2,
7,
2,
3, // top
];
var REFERENCE_INDICES_LENGTH = REFERENCE_INDICES.length;
var positionScratch = new Cartesian3();
var scratchStartEllipsoidNormal = new Cartesian3();
var scratchStartFaceNormal = new Cartesian3();
var scratchEndEllipsoidNormal = new Cartesian3();
var scratchEndFaceNormal = new Cartesian3();
VertexAttributesAndIndices.prototype.addVolume = function (
preStartRTC,
startRTC,
endRTC,
postEndRTC,
startHeight,
endHeight,
halfWidth,
batchId,
center,
ellipsoid
) {
var position = Cartesian3.add(startRTC, center, positionScratch);
var startEllipsoidNormal = ellipsoid.geodeticSurfaceNormal(
position,
scratchStartEllipsoidNormal
);
position = Cartesian3.add(endRTC, center, positionScratch);
var endEllipsoidNormal = ellipsoid.geodeticSurfaceNormal(
position,
scratchEndEllipsoidNormal
);
var startFaceNormal = computeMiteredNormal(
preStartRTC,
startRTC,
endRTC,
startEllipsoidNormal,
scratchStartFaceNormal
);
var endFaceNormal = computeMiteredNormal(
postEndRTC,
endRTC,
startRTC,
endEllipsoidNormal,
scratchEndFaceNormal
);
var startEllipsoidNormals = this.startEllipsoidNormals;
var endEllipsoidNormals = this.endEllipsoidNormals;
var startPositionAndHeights = this.startPositionAndHeights;
var startFaceNormalAndVertexCornerIds = this
.startFaceNormalAndVertexCornerIds;
var endPositionAndHeights = this.endPositionAndHeights;
var endFaceNormalAndHalfWidths = this.endFaceNormalAndHalfWidths;
var vertexBatchIds = this.vertexBatchIds;
var batchIdOffset = this.batchIdOffset;
var vec3Offset = this.vec3Offset;
var vec4Offset = this.vec4Offset;
var i;
for (i = 0; i < 8; i++) {
Cartesian3.pack(startEllipsoidNormal, startEllipsoidNormals, vec3Offset);
Cartesian3.pack(endEllipsoidNormal, endEllipsoidNormals, vec3Offset);
Cartesian3.pack(startRTC, startPositionAndHeights, vec4Offset);
startPositionAndHeights[vec4Offset + 3] = startHeight;
Cartesian3.pack(endRTC, endPositionAndHeights, vec4Offset);
endPositionAndHeights[vec4Offset + 3] = endHeight;
Cartesian3.pack(
startFaceNormal,
startFaceNormalAndVertexCornerIds,
vec4Offset
);
startFaceNormalAndVertexCornerIds[vec4Offset + 3] = i;
Cartesian3.pack(endFaceNormal, endFaceNormalAndHalfWidths, vec4Offset);
endFaceNormalAndHalfWidths[vec4Offset + 3] = halfWidth;
vertexBatchIds[batchIdOffset++] = batchId;
vec3Offset += 3;
vec4Offset += 4;
}
this.batchIdOffset = batchIdOffset;
this.vec3Offset = vec3Offset;
this.vec4Offset = vec4Offset;
var indices = this.indices;
var volumeStartIndex = this.volumeStartIndex;
var indexOffset = this.indexOffset;
for (i = 0; i < REFERENCE_INDICES_LENGTH; i++) {
indices[indexOffset + i] = REFERENCE_INDICES[i] + volumeStartIndex;
}
this.volumeStartIndex += 8;
this.indexOffset += REFERENCE_INDICES_LENGTH;
};
var scratchRectangle = new Rectangle();
var scratchEllipsoid = new Ellipsoid();
var scratchCenter = new Cartesian3();
var scratchPrev = new Cartesian3();
var scratchP0 = new Cartesian3();
var scratchP1 = new Cartesian3();
var scratchNext = new Cartesian3();
function createVectorTileClampedPolylines(parameters, transferableObjects) {
var encodedPositions = new Uint16Array(parameters.positions);
var widths = new Uint16Array(parameters.widths);
var counts = new Uint32Array(parameters.counts);
var batchIds = new Uint16Array(parameters.batchIds);
// Unpack tile decoding parameters
var rectangle = scratchRectangle;
var ellipsoid = scratchEllipsoid;
var center = scratchCenter;
var packedBuffer = new Float64Array(parameters.packedBuffer);
var offset = 0;
var minimumHeight = packedBuffer[offset++];
var maximumHeight = packedBuffer[offset++];
Rectangle.unpack(packedBuffer, offset, rectangle);
offset += Rectangle.packedLength;
Ellipsoid.unpack(packedBuffer, offset, ellipsoid);
offset += Ellipsoid.packedLength;
Cartesian3.unpack(packedBuffer, offset, center);
var i;
// Unpack positions and generate volumes
var positionsLength = encodedPositions.length / 3;
var uBuffer = encodedPositions.subarray(0, positionsLength);
var vBuffer = encodedPositions.subarray(positionsLength, 2 * positionsLength);
var heightBuffer = encodedPositions.subarray(
2 * positionsLength,
3 * positionsLength
);
AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
removeDuplicates(uBuffer, vBuffer, heightBuffer, counts);
// Figure out how many volumes and how many vertices there will be.
var countsLength = counts.length;
var volumesCount = 0;
for (i = 0; i < countsLength; i++) {
var polylinePositionCount = counts[i];
volumesCount += polylinePositionCount - 1;
}
var attribsAndIndices = new VertexAttributesAndIndices(volumesCount);
var positionsRTC = decodePositionsToRtc(
uBuffer,
vBuffer,
heightBuffer,
rectangle,
minimumHeight,
maximumHeight,
ellipsoid,
center
);
var currentPositionIndex = 0;
var currentHeightIndex = 0;
for (i = 0; i < countsLength; i++) {
var polylineVolumeCount = counts[i] - 1;
var halfWidth = widths[i] * 0.5;
var batchId = batchIds[i];
var volumeFirstPositionIndex = currentPositionIndex;
for (var j = 0; j < polylineVolumeCount; j++) {
var volumeStart = Cartesian3.unpack(
positionsRTC,
currentPositionIndex,
scratchP0
);
var volumeEnd = Cartesian3.unpack(
positionsRTC,
currentPositionIndex + 3,
scratchP1
);
var startHeight = heightBuffer[currentHeightIndex];
var endHeight = heightBuffer[currentHeightIndex + 1];
startHeight = CesiumMath.lerp(
minimumHeight,
maximumHeight,
startHeight / MAX_SHORT
);
endHeight = CesiumMath.lerp(
minimumHeight,
maximumHeight,
endHeight / MAX_SHORT
);
currentHeightIndex++;
var preStart = scratchPrev;
var postEnd = scratchNext;
if (j === 0) {
// Check if this volume is like a loop
var finalPositionIndex =
volumeFirstPositionIndex + polylineVolumeCount * 3;
var finalPosition = Cartesian3.unpack(
positionsRTC,
finalPositionIndex,
scratchPrev
);
if (Cartesian3.equals(finalPosition, volumeStart)) {
Cartesian3.unpack(positionsRTC, finalPositionIndex - 3, preStart);
} else {
var offsetPastStart = Cartesian3.subtract(
volumeStart,
volumeEnd,
scratchPrev
);
preStart = Cartesian3.add(offsetPastStart, volumeStart, scratchPrev);
}
} else {
Cartesian3.unpack(positionsRTC, currentPositionIndex - 3, preStart);
}
if (j === polylineVolumeCount - 1) {
// Check if this volume is like a loop
var firstPosition = Cartesian3.unpack(
positionsRTC,
volumeFirstPositionIndex,
scratchNext
);
if (Cartesian3.equals(firstPosition, volumeEnd)) {
Cartesian3.unpack(
positionsRTC,
volumeFirstPositionIndex + 3,
postEnd
);
} else {
var offsetPastEnd = Cartesian3.subtract(
volumeEnd,
volumeStart,
scratchNext
);
postEnd = Cartesian3.add(offsetPastEnd, volumeEnd, scratchNext);
}
} else {
Cartesian3.unpack(positionsRTC, currentPositionIndex + 6, postEnd);
}
attribsAndIndices.addVolume(
preStart,
volumeStart,
volumeEnd,
postEnd,
startHeight,
endHeight,
halfWidth,
batchId,
center,
ellipsoid
);
currentPositionIndex += 3;
}
currentPositionIndex += 3;
currentHeightIndex++;
}
var indices = attribsAndIndices.indices;
transferableObjects.push(attribsAndIndices.startEllipsoidNormals.buffer);
transferableObjects.push(attribsAndIndices.endEllipsoidNormals.buffer);
transferableObjects.push(attribsAndIndices.startPositionAndHeights.buffer);
transferableObjects.push(
attribsAndIndices.startFaceNormalAndVertexCornerIds.buffer
);
transferableObjects.push(attribsAndIndices.endPositionAndHeights.buffer);
transferableObjects.push(attribsAndIndices.endFaceNormalAndHalfWidths.buffer);
transferableObjects.push(attribsAndIndices.vertexBatchIds.buffer);
transferableObjects.push(indices.buffer);
return {
indexDatatype:
indices.BYTES_PER_ELEMENT === 2
? IndexDatatype.UNSIGNED_SHORT
: IndexDatatype.UNSIGNED_INT,
startEllipsoidNormals: attribsAndIndices.startEllipsoidNormals.buffer,
endEllipsoidNormals: attribsAndIndices.endEllipsoidNormals.buffer,
startPositionAndHeights: attribsAndIndices.startPositionAndHeights.buffer,
startFaceNormalAndVertexCornerIds:
attribsAndIndices.startFaceNormalAndVertexCornerIds.buffer,
endPositionAndHeights: attribsAndIndices.endPositionAndHeights.buffer,
endFaceNormalAndHalfWidths:
attribsAndIndices.endFaceNormalAndHalfWidths.buffer,
vertexBatchIds: attribsAndIndices.vertexBatchIds.buffer,
indices: indices.buffer,
};
}
export default createTaskProcessorWorker(createVectorTileClampedPolylines);

View File

@ -1,58 +1,10 @@
import AttributeCompression from "../Core/AttributeCompression.js";
import Cartesian3 from "../Core/Cartesian3.js";
import Cartographic from "../Core/Cartographic.js";
import decodeVectorPolylinePositions from "../Core/decodeVectorPolylinePositions.js";
import Ellipsoid from "../Core/Ellipsoid.js";
import IndexDatatype from "../Core/IndexDatatype.js";
import CesiumMath from "../Core/Math.js";
import Rectangle from "../Core/Rectangle.js";
import createTaskProcessorWorker from "./createTaskProcessorWorker.js";
var maxShort = 32767;
var scratchBVCartographic = new Cartographic();
var scratchEncodedPosition = new Cartesian3();
function decodePositions(
positions,
rectangle,
minimumHeight,
maximumHeight,
ellipsoid
) {
var positionsLength = positions.length / 3;
var uBuffer = positions.subarray(0, positionsLength);
var vBuffer = positions.subarray(positionsLength, 2 * positionsLength);
var heightBuffer = positions.subarray(
2 * positionsLength,
3 * positionsLength
);
AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);
var decoded = new Float64Array(positions.length);
for (var i = 0; i < positionsLength; ++i) {
var u = uBuffer[i];
var v = vBuffer[i];
var h = heightBuffer[i];
var lon = CesiumMath.lerp(rectangle.west, rectangle.east, u / maxShort);
var lat = CesiumMath.lerp(rectangle.south, rectangle.north, v / maxShort);
var alt = CesiumMath.lerp(minimumHeight, maximumHeight, h / maxShort);
var cartographic = Cartographic.fromRadians(
lon,
lat,
alt,
scratchBVCartographic
);
var decodedPosition = ellipsoid.cartographicToCartesian(
cartographic,
scratchEncodedPosition
);
Cartesian3.pack(decodedPosition, decoded, i * 3);
}
return decoded;
}
var scratchRectangle = new Rectangle();
var scratchEllipsoid = new Ellipsoid();
var scratchCenter = new Cartesian3();
@ -96,7 +48,7 @@ function createVectorTilePolylines(parameters, transferableObjects) {
var minimumHeight = scratchMinMaxHeights.min;
var maximumHeight = scratchMinMaxHeights.max;
var positions = decodePositions(
var positions = decodeVectorPolylinePositions(
encodedPositions,
rectangle,
minimumHeight,

View File

@ -0,0 +1,464 @@
import { DoubleEndedPriorityQueue } from "../../Source/Cesium.js";
describe("Core/DoubleEndedPriorityQueue", function () {
function comparator(a, b) {
return a - b;
}
it("constructor throws without options", function () {
expect(function () {
return new DoubleEndedPriorityQueue();
}).toThrowDeveloperError();
});
it("constructor throws if maximum length is less than zero", function () {
expect(function () {
return new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: -1,
});
}).toThrowDeveloperError();
});
it("constructor throws without comparator", function () {
expect(function () {
return new DoubleEndedPriorityQueue({
comparator: undefined,
});
}).toThrowDeveloperError();
});
it("gets comparator", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
var returnedComparator = queue.comparator;
expect(returnedComparator).toEqual(comparator);
});
it("uses different comparator", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: function (a, b) {
return b - a;
},
});
queue.insert(1);
queue.insert(2);
// The comparator is flipped, so 2 is considered the minimum and 1 is considered the maximum
expect(queue.length).toEqual(2);
expect(queue.getMinimum()).toEqual(2);
expect(queue.getMaximum()).toEqual(1);
});
it("checks state of default empty queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
expect(queue.length).toEqual(0);
expect(queue.maximumLength).toBeUndefined();
expect(queue.internalArray.length).toEqual(0);
expect(queue.getMinimum()).toBeUndefined();
expect(queue.getMaximum()).toBeUndefined();
});
it("inserts one element into queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
expect(queue.length).toEqual(1);
expect(queue.internalArray.length).toEqual(1);
expect(queue.getMinimum()).toEqual(1);
expect(queue.getMaximum()).toEqual(1);
});
it("inserts two elements into queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
expect(queue.length).toEqual(2);
expect(queue.internalArray.length).toEqual(2);
expect(queue.getMinimum()).toEqual(1);
expect(queue.getMaximum()).toEqual(2);
});
it("inserts three elements into queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
queue.insert(3);
expect(queue.length).toEqual(3);
expect(queue.internalArray.length).toEqual(3);
expect(queue.getMinimum()).toEqual(1);
expect(queue.getMaximum()).toEqual(3);
});
it("inserts four elements into queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
queue.insert(3);
queue.insert(4);
expect(queue.length).toEqual(4);
expect(queue.internalArray.length).toEqual(4);
expect(queue.getMinimum()).toEqual(1);
expect(queue.getMaximum()).toEqual(4);
});
it("insert removes and returns minimum element when the queue is full", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: 1,
});
var nothing = queue.insert(1);
var removed = queue.insert(2);
expect(queue.length).toEqual(1);
expect(queue.maximumLength).toEqual(1);
expect(queue.internalArray.length).toEqual(1);
expect(queue.getMinimum()).toEqual(2);
expect(queue.getMaximum()).toEqual(2);
expect(nothing).toBeUndefined();
expect(removed).toEqual(1);
});
it("insert returns undefined when new element is less than or equal priority to the minimum element and the queue is full", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: function (a, b) {
return a.value - b.value;
},
maximumLength: 2,
});
var obj1 = { value: 1, id: 0 };
var obj2 = { value: 2, id: 0 };
var obj3 = { value: 1, id: 1 };
var obj4 = { value: 0, id: 1 };
var result1 = queue.insert(obj1);
var result2 = queue.insert(obj2);
var result3 = queue.insert(obj3); // ignored because equal priority to minimum
var result4 = queue.insert(obj4); // ignored because lower priority than minimum
expect(queue.length).toEqual(2);
expect(queue.maximumLength).toEqual(2);
expect(queue.internalArray.length).toEqual(2);
expect(queue.getMinimum().id).toEqual(0);
expect(result1).toBeUndefined();
expect(result2).toBeUndefined();
expect(result3).toEqual(obj3);
expect(result4).toEqual(obj4);
});
it("remove and return minimum element", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
queue.insert(3);
var minimumValue = queue.removeMinimum();
expect(queue.length).toEqual(2);
expect(minimumValue).toEqual(1);
expect(queue.getMinimum()).toEqual(2);
// check that the element was dereferenced
expect(queue.internalArray[2]).toBeUndefined();
});
it("removeMinimum returns undefined when queue is empty", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
var minimumValue = queue.removeMinimum();
expect(minimumValue).toBeUndefined();
});
it("remove and return maximum element", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
queue.insert(3);
var maximumValue = queue.removeMaximum();
expect(queue.length).toEqual(2);
expect(maximumValue).toEqual(3);
expect(queue.getMaximum()).toEqual(2);
// check that the element was dereferenced
expect(queue.internalArray[2]).toBeUndefined();
});
it("removeMaximum returns undefined when queue is empty", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
var maximumValue = queue.removeMaximum();
expect(maximumValue).toBeUndefined();
});
it("clones queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: 4,
});
queue.insert(1);
queue.insert(2);
var clone = queue.clone();
expect(clone.length).toEqual(queue.length);
expect(clone.maximumLength).toEqual(queue.maximumLength);
expect(clone.comparator).toEqual(queue.comparator);
expect(clone.getMaximum()).toEqual(queue.getMaximum());
expect(clone.getMinimum()).toEqual(queue.getMinimum());
});
it("resets queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.insert(1);
queue.insert(2);
queue.reset();
expect(queue.length).toEqual(0);
expect(queue.getMinimum()).toBeUndefined();
expect(queue.getMaximum()).toBeUndefined();
// check that the elements were dereferenced
expect(queue.internalArray.length).toEqual(0);
});
it("resets queue with maximum length", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: 1,
});
queue.insert(1);
queue.reset();
expect(queue.length).toEqual(0);
expect(queue.getMinimum()).toBeUndefined();
expect(queue.getMaximum()).toBeUndefined();
// check that the element was dereferenced but the array stayed the same size
expect(queue.internalArray.length).toEqual(1);
expect(queue.internalArray[0]).toBeUndefined();
});
it("creates queue with maximum length of zero", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: 0,
});
queue.insert(1);
expect(queue.length).toEqual(0);
expect(queue.maximumLength).toEqual(0);
expect(queue.internalArray.length).toEqual(0);
expect(queue.getMinimum()).toBeUndefined();
expect(queue.getMaximum()).toBeUndefined();
});
it("creates queue with maximum length of one", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: 1,
});
queue.insert(1);
queue.insert(2);
expect(queue.length).toEqual(1);
expect(queue.maximumLength).toEqual(1);
expect(queue.internalArray.length).toEqual(1);
expect(queue.getMinimum()).toEqual(2);
expect(queue.getMaximum()).toEqual(2);
});
it("throws when maximum length is set to less than zero", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
expect(function () {
queue.maximumLength = -1;
}).toThrowDeveloperError();
});
it("sets maximum length to undefined", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
queue.maximumLength = 2;
queue.insert(1);
queue.insert(2);
queue.maximumLength = undefined;
queue.insert(3);
expect(queue.length).toEqual(3);
expect(queue.maximumLength).toBeUndefined();
expect(queue.getMinimum()).toEqual(1);
expect(queue.getMaximum()).toEqual(3);
});
it("sets maximum length to less than current length", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
var maximumLength = 5;
for (var i = 0; i < maximumLength * 2; i++) {
var value = i;
queue.insert(value);
}
queue.maximumLength = maximumLength;
expect(queue.length).toEqual(maximumLength);
expect(queue.maximumLength).toEqual(maximumLength);
expect(queue.internalArray.length).toEqual(maximumLength);
expect(queue.getMinimum()).toEqual(maximumLength);
expect(queue.getMaximum()).toEqual(maximumLength * 2 - 1);
});
function isValidQueue(queue) {
// 1) Remove successive minimum elements from the queue and check if they are sorted correctly
// 2) Remove successive maximum elements from the queue and check if they are sorted correctly
var minArray = [];
var maxArray = [];
var minQueue = queue.clone();
var maxQueue = queue.clone();
while (minQueue.length > 0) {
minArray.push(minQueue.removeMinimum());
}
while (maxQueue.length > 0) {
maxArray.push(maxQueue.removeMaximum());
}
if (minQueue.length !== 0 || maxQueue.length !== 0) {
return false;
}
var i;
for (i = 0; i < minArray.length - 1; i++) {
if (minArray[i] > minArray[i + 1]) {
return false;
}
}
for (i = 0; i < maxArray.length - 1; i++) {
if (maxArray[i] < maxArray[i + 1]) {
return false;
}
}
return true;
}
it("maintains priority with ascending insertions", function () {
var length = 200;
var maximumLength = 100;
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: maximumLength,
});
var pass = true;
for (var i = 0; i < length; ++i) {
var value = i;
queue.insert(value);
pass = pass && isValidQueue(queue);
}
expect(pass).toBe(true);
});
it("maintains priority with descending insertions", function () {
var length = 200;
var maximumLength = 100;
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: maximumLength,
});
var pass = true;
for (var i = 0; i < length; ++i) {
var value = length - 1 - i;
queue.insert(value);
pass = pass && isValidQueue(queue);
}
expect(pass).toBe(true);
});
it("maintains priority with random insertions", function () {
var length = 200;
var maximumLength = 100;
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
maximumLength: maximumLength,
});
var pass = true;
for (var i = 0; i < length; ++i) {
var value = Math.random();
queue.insert(value);
pass = pass && isValidQueue(queue);
}
expect(pass).toBe(true);
});
it("resorts queue", function () {
var queue = new DoubleEndedPriorityQueue({
comparator: comparator,
});
var i;
var length = 200;
for (i = 0; i < length; ++i) {
queue.insert(0);
}
// Change all of the queue values to random values to make it unsorted
var array = queue.internalArray;
for (i = 0; i < length; i++) {
array[i] = Math.random();
}
queue.resort();
var pass = isValidQueue(queue);
expect(pass).toBe(true);
});
});

View File

@ -1,3 +1,4 @@
import { Cartesian3 } from "../../Source/Cesium.js";
import { Cartographic } from "../../Source/Cesium.js";
import { Ellipsoid } from "../../Source/Cesium.js";
import { EllipsoidGeodesic } from "../../Source/Cesium.js";
@ -1023,4 +1024,27 @@ describe("Core/EllipsoidRhumbLine", function () {
)
).toBe(true);
});
it("returns the start point when interpolating at surface distance 0.0", function () {
var p0 = new Cartesian3(
899411.2767873341,
-5079219.747324299,
3738850.924729517
);
var p1 = new Cartesian3(
899411.0994891181,
-5079219.778719673,
3738850.9247295167
);
var ellipsoid = Ellipsoid.WGS84;
var c0 = ellipsoid.cartesianToCartographic(p0, new Cartographic());
var c1 = ellipsoid.cartesianToCartographic(p1, new Cartographic());
var rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);
var c = rhumb.interpolateUsingSurfaceDistance(0.0, new Cartographic());
var p = ellipsoid.cartographicToCartesian(c, new Cartesian3());
expect(p).toEqualEpsilon(p0, CesiumMath.EPSILON7);
});
});

View File

@ -742,7 +742,19 @@
]
},
"environmentIntersectionWidth":13317,
"showThroughEllipsoid":true
"showThroughEllipsoid":true,
"showViewshed":true,
"viewshedVisibleColor":{
"rgba":[
80,142,248,57
]
},
"viewshedOccludedColor":{
"rgba":[
166,20,225,110
]
},
"viewshedResolution":9164
},
"agi_customPatternSensor":{
"show":true,
@ -819,7 +831,19 @@
]
},
"environmentIntersectionWidth":53576,
"showThroughEllipsoid":true
"showThroughEllipsoid":true,
"showViewshed":true,
"viewshedVisibleColor":{
"rgba":[
38,54,223,91
]
},
"viewshedOccludedColor":{
"rgba":[
229,38,249,99
]
},
"viewshedResolution":25862
},
"agi_rectangularSensor":{
"show":true,
@ -892,7 +916,19 @@
]
},
"environmentIntersectionWidth":64839,
"showThroughEllipsoid":true
"showThroughEllipsoid":true,
"showViewshed":true,
"viewshedVisibleColor":{
"rgba":[
239,86,8,93
]
},
"viewshedOccludedColor":{
"rgba":[
20,22,45,26
]
},
"viewshedResolution":33690
},
"agi_fan":{
"show":true,
@ -5103,6 +5139,26 @@
}
}
},
{
"id":"constant_agi_conicSensor_viewshedVisibleColor_rgbaf",
"agi_conicSensor":{
"viewshedVisibleColor":{
"rgbaf":[
0.5490196078431373,0.23529411764705882,0.34509803921568627,0.20392156862745098
]
}
}
},
{
"id":"constant_agi_conicSensor_viewshedOccludedColor_rgbaf",
"agi_conicSensor":{
"viewshedOccludedColor":{
"rgbaf":[
0.9529411764705882,0.3843137254901961,0.8901960784313725,0.00784313725490196
]
}
}
},
{
"id":"constant_agi_customPatternSensor_directions_unitSpherical",
"agi_customPatternSensor":{
@ -6131,6 +6187,26 @@
}
}
},
{
"id":"constant_agi_customPatternSensor_viewshedVisibleColor_rgbaf",
"agi_customPatternSensor":{
"viewshedVisibleColor":{
"rgbaf":[
0.011764705882352941,0.3058823529411765,0.09019607843137255,0.9490196078431372
]
}
}
},
{
"id":"constant_agi_customPatternSensor_viewshedOccludedColor_rgbaf",
"agi_customPatternSensor":{
"viewshedOccludedColor":{
"rgbaf":[
0.6196078431372549,0.08627450980392157,0.47843137254901963,0.2549019607843137
]
}
}
},
{
"id":"constant_agi_rectangularSensor_intersectionColor_rgbaf",
"agi_rectangularSensor":{
@ -7126,6 +7202,26 @@
}
}
},
{
"id":"constant_agi_rectangularSensor_viewshedVisibleColor_rgbaf",
"agi_rectangularSensor":{
"viewshedVisibleColor":{
"rgbaf":[
0.9215686274509803,0.3411764705882353,0.16470588235294117,0.054901960784313725
]
}
}
},
{
"id":"constant_agi_rectangularSensor_viewshedOccludedColor_rgbaf",
"agi_rectangularSensor":{
"viewshedOccludedColor":{
"rgbaf":[
0.1843137254901961,0.6392156862745098,0.6666666666666666,0.5568627450980392
]
}
}
},
{
"id":"constant_agi_fan_directions_unitSpherical",
"agi_fan":{
@ -8482,6 +8578,18 @@
},
"showThroughEllipsoid":{
"reference":"Constant#conicSensor.showThroughEllipsoid"
},
"showViewshed":{
"reference":"Constant#conicSensor.showViewshed"
},
"viewshedVisibleColor":{
"reference":"Constant#conicSensor.viewshedVisibleColor"
},
"viewshedOccludedColor":{
"reference":"Constant#conicSensor.viewshedOccludedColor"
},
"viewshedResolution":{
"reference":"Constant#conicSensor.viewshedResolution"
}
},
"agi_customPatternSensor":{
@ -8567,6 +8675,18 @@
},
"showThroughEllipsoid":{
"reference":"Constant#customPatternSensor.showThroughEllipsoid"
},
"showViewshed":{
"reference":"Constant#customPatternSensor.showViewshed"
},
"viewshedVisibleColor":{
"reference":"Constant#customPatternSensor.viewshedVisibleColor"
},
"viewshedOccludedColor":{
"reference":"Constant#customPatternSensor.viewshedOccludedColor"
},
"viewshedResolution":{
"reference":"Constant#customPatternSensor.viewshedResolution"
}
},
"agi_rectangularSensor":{
@ -8658,6 +8778,18 @@
},
"showThroughEllipsoid":{
"reference":"Constant#rectangularSensor.showThroughEllipsoid"
},
"showViewshed":{
"reference":"Constant#rectangularSensor.showViewshed"
},
"viewshedVisibleColor":{
"reference":"Constant#rectangularSensor.viewshedVisibleColor"
},
"viewshedOccludedColor":{
"reference":"Constant#rectangularSensor.viewshedOccludedColor"
},
"viewshedResolution":{
"reference":"Constant#rectangularSensor.viewshedResolution"
}
},
"agi_fan":{
@ -12538,6 +12670,27 @@
0,54383,
3600,48814
]
},
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,219,102,126,208,
3600,165,12,88,3
]
},
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,47,229,96,105,
3600,65,153,9,64
]
},
"viewshedResolution":{
"epoch":"2016-06-17T12:00:00Z",
"number":[
0,38357,
3600,30316
]
}
},
"agi_customPatternSensor":{
@ -12630,6 +12783,27 @@
0,15461,
3600,8e3
]
},
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,221,155,36,117,
3600,249,126,78,129
]
},
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,228,27,237,134,
3600,254,162,80,84
]
},
"viewshedResolution":{
"epoch":"2016-06-17T12:00:00Z",
"number":[
0,44590,
3600,31959
]
}
},
"agi_rectangularSensor":{
@ -12736,6 +12910,27 @@
0,637,
3600,10677
]
},
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,220,157,178,92,
3600,213,65,75,26
]
},
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgba":[
0,202,44,192,10,
3600,107,226,246,207
]
},
"viewshedResolution":{
"epoch":"2016-06-17T12:00:00Z",
"number":[
0,24619,
3600,54818
]
}
},
"agi_fan":{
@ -17901,6 +18096,30 @@
}
}
},
{
"id":"sampled_conicSensor_viewshedVisibleColor_rgbaf",
"agi_conicSensor":{
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.6666666666666666,0.13333333333333333,0.2784313725490196,0.2549019607843137,
3600,0.11372549019607843,0.5372549019607843,0.4666666666666667,0.7098039215686275
]
}
}
},
{
"id":"sampled_conicSensor_viewshedOccludedColor_rgbaf",
"agi_conicSensor":{
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.32941176470588235,0.29411764705882354,0.4666666666666667,0.00784313725490196,
3600,0.2901960784313726,0.5254901960784314,0.6,0.5882352941176471
]
}
}
},
{
"id":"sampled_customPatternSensor_intersectionColor_rgbaf",
"agi_customPatternSensor":{
@ -19155,6 +19374,30 @@
}
}
},
{
"id":"sampled_customPatternSensor_viewshedVisibleColor_rgbaf",
"agi_customPatternSensor":{
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.10196078431372549,0.23529411764705882,0.5372549019607843,0.6509803921568628,
3600,0.9450980392156862,0.047058823529411764,0.3686274509803922,0.7450980392156863
]
}
}
},
{
"id":"sampled_customPatternSensor_viewshedOccludedColor_rgbaf",
"agi_customPatternSensor":{
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.6588235294117647,0.7058823529411765,0.4823529411764706,0.6078431372549019,
3600,0.9176470588235294,0.5568627450980392,0.596078431372549,0.7372549019607844
]
}
}
},
{
"id":"sampled_rectangularSensor_intersectionColor_rgbaf",
"agi_rectangularSensor":{
@ -20409,6 +20652,30 @@
}
}
},
{
"id":"sampled_rectangularSensor_viewshedVisibleColor_rgbaf",
"agi_rectangularSensor":{
"viewshedVisibleColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.26666666666666666,0.15294117647058825,0.8196078431372549,0.08235294117647059,
3600,0.19215686274509805,0.06274509803921569,0.4666666666666667,0.06274509803921569
]
}
}
},
{
"id":"sampled_rectangularSensor_viewshedOccludedColor_rgbaf",
"agi_rectangularSensor":{
"viewshedOccludedColor":{
"epoch":"2016-06-17T12:00:00Z",
"rgbaf":[
0,0.35294117647058826,0.32941176470588235,0.050980392156862744,0.1843137254901961,
3600,0.7254901960784313,0.16470588235294117,0.06666666666666667,0.27450980392156865
]
}
}
},
{
"id":"sampled_fan_material_solidColor_color",
"agi_fan":{

View File

@ -7932,6 +7932,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('constant_conicSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_conicSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_conicSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_conicSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_conicSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_directions_unitSpherical')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_directions_cartesian')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_directions_unitCartesian')).toBeDefined();
@ -7992,6 +7994,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('constant_customPatternSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_customPatternSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_customPatternSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_rectangularSensor_intersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_rectangularSensor_lateralSurfaceMaterial_solidColor_color')).toBeDefined();
expect(e = dataSource.entities.getById('material_rectangularSensor_lateralSurfaceMaterial_image')).toBeDefined();
@ -8049,6 +8053,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('constant_rectangularSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_rectangularSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_rectangularSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_rectangularSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_rectangularSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_fan_directions_unitSpherical')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_fan_directions_cartesian')).toBeDefined();
expect(e = dataSource.entities.getById('constant_agi_fan_directions_unitCartesian')).toBeDefined();
@ -9881,6 +9887,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('sampled_conicSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_conicSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_conicSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_conicSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_conicSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_intersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_lateralSurfaceMaterial_solidColor_color')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_lateralSurfaceMaterial_image')).toBeDefined();
@ -9938,6 +9946,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('sampled_customPatternSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_customPatternSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_intersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_lateralSurfaceMaterial_solidColor_color')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_lateralSurfaceMaterial_image')).toBeDefined();
@ -9995,6 +10005,8 @@ describe("DataSources/CzmlDataSource", function () {
expect(e = dataSource.entities.getById('sampled_rectangularSensor_environmentOcclusionMaterial_checkerboard_evenColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_environmentOcclusionMaterial_checkerboard_oddColor')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_environmentIntersectionColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_viewshedVisibleColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_rectangularSensor_viewshedOccludedColor_rgbaf')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_fan_material_solidColor_color')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_fan_material_image')).toBeDefined();
expect(e = dataSource.entities.getById('sampled_fan_material_grid')).toBeDefined();

View File

@ -719,29 +719,6 @@ describe(
);
});
function loadTilesetAtFullDetail(url) {
return Cesium3DTilesTester.loadTileset(scene, url).then(function (
tileset
) {
tileset.maximumScreenSpaceError = 0.0;
return Cesium3DTilesTester.waitForTilesLoaded(scene, tileset);
});
}
it("renders pickPrimitive during pick pass if defined", function () {
viewRootOnly();
return when
.all([
loadTilesetAtFullDetail(tilesetUrl),
loadTilesetAtFullDetail(withBatchTableUrl),
])
.then(function (tilesets) {
tilesets[0].pickPrimitive = tilesets[1];
expect(tilesets[0].pickPrimitive).toEqual(tilesets[1]);
expect(scene).toPickPrimitive(tilesets[1]);
});
});
it("verify statistics", function () {
options.url = tilesetUrl;
var tileset = scene.primitives.add(new Cesium3DTileset(options));

View File

@ -0,0 +1,753 @@
import { TranslucentTileClassification } from "../../Source/Cesium.js";
import { ApproximateTerrainHeights } from "../../Source/Cesium.js";
import { Cartesian3 } from "../../Source/Cesium.js";
import { Color } from "../../Source/Cesium.js";
import { ColorGeometryInstanceAttribute } from "../../Source/Cesium.js";
import { defined } from "../../Source/Cesium.js";
import { destroyObject } from "../../Source/Cesium.js";
import { Ellipsoid } from "../../Source/Cesium.js";
import { GeometryInstance } from "../../Source/Cesium.js";
import { GroundPolylineGeometry } from "../../Source/Cesium.js";
import { PixelFormat } from "../../Source/Cesium.js";
import { Rectangle } from "../../Source/Cesium.js";
import { RectangleGeometry } from "../../Source/Cesium.js";
import { ClearCommand } from "../../Source/Cesium.js";
import { Framebuffer } from "../../Source/Cesium.js";
import { Pass } from "../../Source/Cesium.js";
import { PixelDatatype } from "../../Source/Cesium.js";
import { RenderState } from "../../Source/Cesium.js";
import { Texture } from "../../Source/Cesium.js";
import { ClassificationType } from "../../Source/Cesium.js";
import { GroundPolylinePrimitive } from "../../Source/Cesium.js";
import { PerInstanceColorAppearance } from "../../Source/Cesium.js";
import { Primitive } from "../../Source/Cesium.js";
import { StencilConstants } from "../../Source/Cesium.js";
import createScene from "../createScene.js";
describe(
"Scene/TranslucentTileClassification",
function () {
var scene;
var context;
var passState;
var globeDepthFramebuffer;
var ellipsoid;
var positions = Cartesian3.fromDegreesArray([0.01, 0.0, 0.03, 0.0]);
var lookPosition = Cartesian3.fromDegrees(0.02, 0.0);
var lookOffset = new Cartesian3(0.0, 0.0, 10.0);
var translucentPrimitive;
var groundPolylinePrimitive;
beforeAll(function () {
scene = createScene();
scene.postProcessStages.fxaa.enabled = false;
scene.render(); // generate globeDepth.framebuffer
context = scene.context;
passState = scene._defaultView.passState;
if (defined(scene._defaultView.globeDepth)) {
globeDepthFramebuffer = scene._defaultView.globeDepth.framebuffer;
}
ellipsoid = Ellipsoid.WGS84;
return GroundPolylinePrimitive.initializeTerrainHeights();
});
afterAll(function () {
scene.destroyForSpecs();
// Leave ground primitive uninitialized
ApproximateTerrainHeights._initPromise = undefined;
ApproximateTerrainHeights._terrainHeights = undefined;
});
function SpecPrimitive(primitive, pass) {
this._primitive = primitive;
this._depthForTranslucentClassification = pass === Pass.TRANSLUCENT;
this._pass = pass;
this.commands = [];
}
SpecPrimitive.prototype.update = function (frameState) {
var commandList = frameState.commandList;
var startLength = commandList.length;
this._primitive.update(frameState);
this.commands = [];
for (var i = startLength; i < commandList.length; ++i) {
var command = commandList[i];
command.pass = this._pass;
command.depthForTranslucentClassification = this._depthForTranslucentClassification;
this.commands.push(command);
}
};
SpecPrimitive.prototype.isDestroyed = function () {
return false;
};
SpecPrimitive.prototype.destroy = function () {
this._primitive.destroy();
return destroyObject(this);
};
beforeEach(function () {
scene.morphTo3D(0);
scene.render(); // clear any afterRender commands
scene.camera.lookAt(lookPosition, lookOffset);
var renderState = RenderState.fromCache({
stencilTest: StencilConstants.setCesium3DTileBit(),
stencilMask: StencilConstants.CESIUM_3D_TILE_MASK,
depthTest: {
enabled: true,
},
});
var primitive = new Primitive({
geometryInstances: new GeometryInstance({
geometry: new RectangleGeometry({
ellipsoid: ellipsoid,
rectangle: Rectangle.fromDegrees(-0.1, -0.1, 0.1, 0.1),
height: 1.0,
}),
attributes: {
color: ColorGeometryInstanceAttribute.fromColor(
new Color(0.0, 0.0, 1.0, 0.5)
),
},
}),
appearance: new PerInstanceColorAppearance({
translucent: true,
flat: true,
renderState: renderState,
}),
asynchronous: false,
});
translucentPrimitive = new SpecPrimitive(primitive, Pass.TRANSLUCENT);
scene.primitives.add(translucentPrimitive);
primitive = new GroundPolylinePrimitive({
geometryInstances: new GeometryInstance({
geometry: new GroundPolylineGeometry({
positions: positions,
granularity: 0.0,
width: 1.0,
loop: false,
ellipsoid: ellipsoid,
}),
}),
asynchronous: false,
classificationType: ClassificationType.CESIUM_3D_TILE,
});
groundPolylinePrimitive = new SpecPrimitive(
primitive,
Pass.CESIUM_3D_TILE_CLASSIFICATION
);
scene.groundPrimitives.add(groundPolylinePrimitive);
});
afterEach(function () {
scene.primitives.removeAll();
scene.groundPrimitives.removeAll();
translucentPrimitive =
translucentPrimitive &&
!translucentPrimitive.isDestroyed() &&
translucentPrimitive.destroy();
groundPolylinePrimitive =
groundPolylinePrimitive &&
!groundPolylinePrimitive.isDestroyed() &&
groundPolylinePrimitive.destroy();
});
it("checks for support in the context on construction", function () {
var translucentTileClassification = new TranslucentTileClassification({
depthTexture: true,
});
expect(translucentTileClassification.isSupported()).toBe(true);
translucentTileClassification.destroy();
translucentTileClassification = new TranslucentTileClassification({
depthTexture: false,
});
expect(translucentTileClassification.isSupported()).toBe(false);
translucentTileClassification.destroy();
});
function expectResources(translucentTileClassification, toBeDefined) {
expect(
defined(translucentTileClassification._drawClassificationFBO)
).toBe(toBeDefined);
expect(defined(translucentTileClassification._packFBO)).toBe(toBeDefined);
expect(
defined(translucentTileClassification._opaqueDepthStencilTexture)
).toBe(toBeDefined);
expect(defined(translucentTileClassification._colorTexture)).toBe(
toBeDefined
);
expect(
defined(translucentTileClassification._translucentDepthStencilTexture)
).toBe(toBeDefined);
expect(
defined(translucentTileClassification._packedTranslucentDepth)
).toBe(toBeDefined);
expect(defined(translucentTileClassification._packDepthCommand)).toBe(
toBeDefined
);
expect(defined(translucentTileClassification._accumulateCommand)).toBe(
toBeDefined
);
expect(defined(translucentTileClassification._compositeCommand)).toBe(
toBeDefined
);
expect(defined(translucentTileClassification._copyCommand)).toBe(
toBeDefined
);
}
it("does not create resources if unsupported", function () {
var translucentTileClassification = new TranslucentTileClassification({
depthTexture: false,
});
expectResources(translucentTileClassification, false);
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
expectResources(translucentTileClassification, false);
translucentTileClassification.destroy();
});
it("creates resources on demand", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
expectResources(translucentTileClassification, false);
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
[],
globeDepthFramebuffer
);
expectResources(translucentTileClassification, false);
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
expectResources(translucentTileClassification, true);
translucentTileClassification.destroy();
});
function readPixels(fbo) {
return context.readPixels({
framebuffer: fbo,
});
}
function executeCommand(command, scene, context, passState) {
command.execute(context, passState);
}
it("draws translucent commands into a buffer for depth", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
var packedDepthFBO = translucentTileClassification._packFBO;
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
expect(translucentTileClassification.hasTranslucentDepth).toBe(true);
var postTranslucentPixels = readPixels(packedDepthFBO);
expect(postTranslucentPixels).not.toEqual([0, 0, 0, 0]);
translucentTileClassification.destroy();
});
it("draws classification commands into a buffer", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
var drawClassificationFBO =
translucentTileClassification._drawClassificationFBO;
var preClassifyPixels = readPixels(drawClassificationFBO);
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var postClassifyPixels = readPixels(drawClassificationFBO);
expect(postClassifyPixels).not.toEqual(preClassifyPixels);
translucentTileClassification.destroy();
});
it("draws classification commands into a separate accumulation buffer for multifrustum", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
var accumulationFBO = translucentTileClassification._accumulationFBO;
var drawClassificationFBO =
translucentTileClassification._drawClassificationFBO;
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
expect(readPixels(accumulationFBO)).toEqual([0, 0, 0, 0]);
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var secondFrustumAccumulation = accumulationFBO;
var accumulationPixels = readPixels(secondFrustumAccumulation);
var classificationPixels = readPixels(drawClassificationFBO);
var expectedPixels = [
// Multiply by two to account for premultiplied alpha
classificationPixels[0] * 2,
classificationPixels[1] * 2,
classificationPixels[2] * 2,
classificationPixels[3],
];
expect(accumulationPixels).not.toEqual([0, 0, 0, 0]);
expect(accumulationPixels).toEqualEpsilon(expectedPixels, 1);
translucentTileClassification.destroy();
});
it("does not draw classification commands if there is no translucent depth", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
var drawClassificationFBO =
translucentTileClassification._drawClassificationFBO;
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
[],
globeDepthFramebuffer
);
var preClassifyPixels = readPixels(drawClassificationFBO);
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var postClassifyPixels = readPixels(drawClassificationFBO);
expect(postClassifyPixels).toEqual(preClassifyPixels);
translucentTileClassification.destroy();
});
it("composites classification into a buffer", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
var colorTexture = new Texture({
context: context,
width: 1,
height: 1,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
});
var targetColorFBO = new Framebuffer({
context: context,
colorTextures: [colorTexture],
});
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var preCompositePixels = readPixels(targetColorFBO);
var pixelsToComposite = readPixels(
translucentTileClassification._drawClassificationFBO
);
var framebuffer = passState.framebuffer;
passState.framebuffer = targetColorFBO;
translucentTileClassification.execute(scene, passState);
passState.framebuffer = framebuffer;
var postCompositePixels = readPixels(targetColorFBO);
expect(postCompositePixels).not.toEqual(preCompositePixels);
var red = Math.round(pixelsToComposite[0]) + preCompositePixels[0];
var green = Math.round(pixelsToComposite[1]) + preCompositePixels[1];
var blue = Math.round(pixelsToComposite[2]) + preCompositePixels[2];
var alpha = pixelsToComposite[3] + preCompositePixels[3];
expect(postCompositePixels[0]).toEqual(red);
expect(postCompositePixels[1]).toEqual(green);
expect(postCompositePixels[2]).toEqual(blue);
expect(postCompositePixels[3]).toEqual(alpha);
translucentTileClassification.destroy();
targetColorFBO.destroy();
});
it("composites from an accumulation texture when there are multiple frustums", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
var clearCommandRed = new ClearCommand({
color: new Color(1.0, 0.0, 0.0, 1.0),
});
var clearCommandGreen = new ClearCommand({
color: new Color(0.0, 1.0, 0.0, 1.0),
});
var colorTexture = new Texture({
context: context,
width: 1,
height: 1,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
});
var targetColorFBO = new Framebuffer({
context: context,
colorTextures: [colorTexture],
});
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
var frustumCommands = {
commands: [],
indices: [],
};
// First Frustum
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
// Second Frustum
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var framebuffer = passState.framebuffer;
// Replace classification and accumulation colors to distinguish which is composited
passState.framebuffer =
translucentTileClassification._drawClassificationFBO;
clearCommandRed.execute(context, passState);
passState.framebuffer = translucentTileClassification._accumulationFBO;
clearCommandGreen.execute(context, passState);
passState.framebuffer = targetColorFBO;
translucentTileClassification.execute(scene, passState);
passState.framebuffer = framebuffer;
var postCompositePixels = readPixels(targetColorFBO);
expect(postCompositePixels).toEqual([0, 255, 0, 255]);
translucentTileClassification.destroy();
targetColorFBO.destroy();
});
it("does not composite classification if there is no translucent depth", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
var colorTexture = new Texture({
context: context,
width: 1,
height: 1,
pixelFormat: PixelFormat.RGBA,
pixelDatatype: PixelDatatype.UNSIGNED_BYTE,
});
var targetColorFBO = new Framebuffer({
context: context,
colorTextures: [colorTexture],
});
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
[],
globeDepthFramebuffer
);
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var preCompositePixels = readPixels(targetColorFBO);
var framebuffer = passState.framebuffer;
passState.framebuffer = targetColorFBO;
translucentTileClassification.execute(scene, passState);
passState.framebuffer = framebuffer;
var postCompositePixels = readPixels(targetColorFBO);
expect(postCompositePixels).toEqual(preCompositePixels);
translucentTileClassification.destroy();
targetColorFBO.destroy();
});
it("clears the classification buffer", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
scene.render(); // prep scene
translucentTileClassification.executeTranslucentCommands(
scene,
executeCommand,
passState,
translucentPrimitive.commands,
globeDepthFramebuffer
);
var drawClassificationFBO =
translucentTileClassification._drawClassificationFBO;
var preClassifyPixels = readPixels(drawClassificationFBO);
var frustumCommands = {
commands: [],
indices: [],
};
frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION] =
groundPolylinePrimitive.commands;
frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION] = [1];
translucentTileClassification.executeClassificationCommands(
scene,
executeCommand,
passState,
frustumCommands
);
var postClassifyPixels = readPixels(drawClassificationFBO);
expect(postClassifyPixels).not.toEqual(preClassifyPixels);
translucentTileClassification.execute(scene, passState);
var postClearPixels = readPixels(drawClassificationFBO);
expect(postClearPixels).not.toEqual(postClassifyPixels);
expect(postClearPixels).toEqual(preClassifyPixels);
translucentTileClassification.destroy();
});
it("does not clear the classification buffer if there is no translucent depth", function () {
var translucentTileClassification = new TranslucentTileClassification(
context
);
if (!translucentTileClassification.isSupported()) {
return; // don't fail because of lack of support
}
spyOn(translucentTileClassification._clearColorCommand, "execute");
translucentTileClassification.execute(scene, passState);
expect(
translucentTileClassification._clearColorCommand.execute
).not.toHaveBeenCalled();
translucentTileClassification.destroy();
});
},
"WebGL"
);

View File

@ -0,0 +1,139 @@
import { Cartesian3 } from "../../Source/Cesium.js";
import { ClassificationType } from "../../Source/Cesium.js";
import { Color } from "../../Source/Cesium.js";
import { ColorGeometryInstanceAttribute } from "../../Source/Cesium.js";
import { destroyObject } from "../../Source/Cesium.js";
import { Ellipsoid } from "../../Source/Cesium.js";
import { GeometryInstance } from "../../Source/Cesium.js";
import { Rectangle } from "../../Source/Cesium.js";
import { RectangleGeometry } from "../../Source/Cesium.js";
import { Pass } from "../../Source/Cesium.js";
import { PerInstanceColorAppearance } from "../../Source/Cesium.js";
import { Primitive } from "../../Source/Cesium.js";
import { Vector3DTileClampedPolylines } from "../../Source/Cesium.js";
import Cesium3DTilesTester from "../Cesium3DTilesTester.js";
import createScene from "../createScene.js";
describe(
"Scene/Vector3DTileClampedPolylines",
function () {
var scene;
var rectangle;
var polylines;
var ellipsoid = Ellipsoid.WGS84;
var depthRectanglePrimitive;
var vectorPolylines =
"./Data/Cesium3DTiles/Vector/VectorTilePolylines/tileset.json";
beforeAll(function () {
scene = createScene();
});
afterAll(function () {
scene.destroyForSpecs();
});
function MockGlobePrimitive(primitive) {
this._primitive = primitive;
this.pass = Pass.GLOBE;
}
MockGlobePrimitive.prototype.update = function (frameState) {
var commandList = frameState.commandList;
var startLength = commandList.length;
this._primitive.update(frameState);
for (var i = startLength; i < commandList.length; ++i) {
var command = commandList[i];
command.pass = this.pass;
}
};
MockGlobePrimitive.prototype.isDestroyed = function () {
return false;
};
MockGlobePrimitive.prototype.destroy = function () {
this._primitive.destroy();
return destroyObject(this);
};
beforeEach(function () {
rectangle = Rectangle.fromDegrees(-40.0, -40.0, 40.0, 40.0);
var depthpolylineColorAttribute = ColorGeometryInstanceAttribute.fromColor(
new Color(0.0, 0.0, 1.0, 1.0)
);
var primitive = new Primitive({
geometryInstances: new GeometryInstance({
geometry: new RectangleGeometry({
ellipsoid: ellipsoid,
rectangle: rectangle,
}),
id: "depth rectangle",
attributes: {
color: depthpolylineColorAttribute,
},
}),
appearance: new PerInstanceColorAppearance({
translucent: false,
flat: true,
}),
asynchronous: false,
});
// wrap rectangle primitive so it gets executed during the globe pass to lay down depth
depthRectanglePrimitive = new MockGlobePrimitive(primitive);
});
afterEach(function () {
scene.primitives.removeAll();
polylines = polylines && !polylines.isDestroyed() && polylines.destroy();
});
it("renders clamped polylines", function () {
scene.camera.lookAt(
Cartesian3.fromDegrees(0.0, 0.0, 1.5),
new Cartesian3(0.0, 0.0, 1.0)
);
return Cesium3DTilesTester.loadTileset(scene, vectorPolylines, {
classificationType: ClassificationType.TERRAIN,
}).then(function (tileset) {
scene.primitives.add(depthRectanglePrimitive);
tileset.show = false;
expect(scene).toRender([0, 0, 255, 255]);
tileset.show = true;
expect(scene).toRender([255, 255, 255, 255]);
});
});
it("picks a clamped polyline", function () {
scene.camera.lookAt(
Cartesian3.fromDegrees(0.0, 0.0, 1.5),
new Cartesian3(0.0, 0.0, 1.0)
);
return Cesium3DTilesTester.loadTileset(scene, vectorPolylines, {
classificationType: ClassificationType.TERRAIN,
}).then(function (tileset) {
scene.primitives.add(depthRectanglePrimitive);
tileset.show = false;
expect(scene).toPickPrimitive(depthRectanglePrimitive._primitive);
tileset.show = true;
expect(scene).toPickPrimitive(tileset);
});
});
it("isDestroyed", function () {
polylines = new Vector3DTileClampedPolylines({
rectangle: new Rectangle(),
});
expect(polylines.isDestroyed()).toEqual(false);
polylines.destroy();
expect(polylines.isDestroyed()).toEqual(true);
});
},
"WebGL"
);

View File

@ -1,4 +1,4 @@
The official [shareable ESLint config](http://eslint.org/docs/developer-guide/shareable-configs) for the [Cesium](https://cesiumjs.org/) ecosystem.
The official [shareable ESLint config](http://eslint.org/docs/developer-guide/shareable-configs) for the [Cesium](https://cesium.com/) ecosystem.
## Usage

View File

@ -2,7 +2,7 @@
"name": "eslint-config-cesium",
"version": "8.0.1",
"description": "ESLint shareable configs for Cesium",
"homepage": "http://cesiumjs.org",
"homepage": "http://cesium.com/",
"license": "Apache-2.0",
"author": {
"name": "Cesium GS, Inc.",

View File

@ -17,7 +17,7 @@
<div class="nav">
<div class="menu">
<a href="http://cesiumjs.org/" target="_top"><img id="cesium-logo" src="Images/CesiumLogo.png" class="cesiumLogo"></a>
<a href="https://cesium.com/" target="_top"><img id="cesium-logo" src="Images/CesiumLogo.png" class="cesiumLogo"></a>
<input type="text" class="classFilter" id="ClassFilter" placeholder="Search">

View File

@ -2,7 +2,7 @@
"name": "rollup-plugin-strip-pragma",
"version": "1.0.0",
"description": "A Rollup plugin to strip requirejs build pragmas from your code.",
"homepage": "http://cesiumjs.org",
"homepage": "https://cesium.com",
"license": "Apache-2.0",
"author": {
"name": "Cesium GS, Inc.",

View File

@ -1445,7 +1445,7 @@ export default "' +
}
function createCesiumJs() {
let contents = `export const VERSION = '${version}';\n`;
let contents = `export var VERSION = '${version}';\n`;
globby.sync(sourceFiles).forEach(function (file) {
file = path.relative("Source", file);

View File

@ -47,7 +47,7 @@
<div class="section">
<a href="https://cesium.com/cesiumjs/"
><img
src="https://cesium.com/images/logos/cesiumjs/cesiumjs_color_black.png"
src="./Apps/Sandcastle/images/Cesium_Logo_Color_Overlay.png"
style="width: 400px"
/></a>
</div>
@ -136,7 +136,7 @@
</tr>
<tr>
<td>
<a href="https://cesium.com/blog/categories/userstories/"
<a href="https://cesium.com/blog/categories/user-stories/"
>User Stories</a
>
</td>
@ -154,7 +154,7 @@
<div
style="padding-top: 300px; font-size: 10pt; vertical-align: bottom"
>
&copy; 2011-2020 CesiumJS Contributors
&copy; 2011-2021 CesiumJS Contributors
</div>
</div>
</div>

View File

@ -1,6 +1,6 @@
{
"name": "cesium",
"version": "1.79.1",
"version": "1.80.0",
"description": "CesiumJS is a JavaScript library for creating 3D globes and 2D maps in a web browser without a plugin.",
"homepage": "http://cesium.com/cesiumjs/",
"license": "Apache-2.0",