import { ApproximateTerrainHeights } from "../../Source/Cesium.js"; import { Cartesian2 } from "../../Source/Cesium.js"; import { Cartesian3 } from "../../Source/Cesium.js"; import { Math as CesiumMath } from "../../Source/Cesium.js"; import { Color } from "../../Source/Cesium.js"; import { ColorGeometryInstanceAttribute } from "../../Source/Cesium.js"; import { destroyObject } from "../../Source/Cesium.js"; import { DistanceDisplayConditionGeometryInstanceAttribute } from "../../Source/Cesium.js"; import { Ellipsoid } from "../../Source/Cesium.js"; import { GeometryInstance } from "../../Source/Cesium.js"; import { GroundPolylineGeometry } from "../../Source/Cesium.js"; import { HeadingPitchRange } from "../../Source/Cesium.js"; import { Rectangle } from "../../Source/Cesium.js"; import { RectangleGeometry } from "../../Source/Cesium.js"; import { ShowGeometryInstanceAttribute } from "../../Source/Cesium.js"; import { Pass } from "../../Source/Cesium.js"; import { GroundPolylinePrimitive } from "../../Source/Cesium.js"; import { PerInstanceColorAppearance } from "../../Source/Cesium.js"; import { PolylineColorAppearance } from "../../Source/Cesium.js"; import { PolylineMaterialAppearance } from "../../Source/Cesium.js"; import { Primitive } from "../../Source/Cesium.js"; import createCanvas from "../createCanvas.js"; import createScene from "../createScene.js"; import pollToPromise from "../pollToPromise.js"; describe( "Scene/GroundPolylinePrimitive", function () { var scene; var context; var ellipsoid; var depthColor; var polylineColor; var polylineColorAttribute; var groundPolylineInstance; var groundPolylinePrimitive; var depthRectanglePrimitive; var positions = Cartesian3.fromDegreesArray([0.01, 0.0, 0.03, 0.0]); var lookPosition = Cartesian3.fromDegrees(0.02, 0.0); var lookPositionOffset = Cartesian3.fromDegrees(0.02, 0.0001); var canvasWidth = 4; var canvasHeight = 4; beforeAll(function () { var canvas = createCanvas(canvasWidth, canvasHeight); scene = createScene({ canvas: canvas, }); scene.postProcessStages.fxaa.enabled = false; context = scene.context; ellipsoid = Ellipsoid.WGS84; return GroundPolylinePrimitive.initializeTerrainHeights(); }); afterAll(function () { scene.destroyForSpecs(); // Leave ground primitive uninitialized ApproximateTerrainHeights._initPromise = undefined; ApproximateTerrainHeights._terrainHeights = undefined; }); 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 () { scene.morphTo3D(0); // Other specs can mess with camera near/far, which can interfere with the // algorithm used to draw ground polylines. scene.camera.frustum.near = 0.1; scene.camera.frustum.far = 10000000000.0; var depthpolylineColorAttribute = ColorGeometryInstanceAttribute.fromColor( new Color(0.0, 0.0, 1.0, 1.0) ); depthColor = depthpolylineColorAttribute.value; var primitive = new Primitive({ geometryInstances: new GeometryInstance({ geometry: new RectangleGeometry({ ellipsoid: ellipsoid, rectangle: Rectangle.fromDegrees(-1.0, -1.0, 1.0, 1.0), }), 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); polylineColorAttribute = ColorGeometryInstanceAttribute.fromColor( new Color(0.0, 1.0, 1.0, 1.0) ); polylineColor = polylineColorAttribute.value; groundPolylineInstance = new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: positions, granularity: 0.0, width: 1.0, loop: false, ellipsoid: ellipsoid, }), id: "polyline on terrain", attributes: { color: polylineColorAttribute, }, }); }); afterEach(function () { scene.groundPrimitives.removeAll(); groundPolylinePrimitive = groundPolylinePrimitive && !groundPolylinePrimitive.isDestroyed() && groundPolylinePrimitive.destroy(); depthRectanglePrimitive = depthRectanglePrimitive && !depthRectanglePrimitive.isDestroyed() && depthRectanglePrimitive.destroy(); }); it("default constructs", function () { groundPolylinePrimitive = new GroundPolylinePrimitive(); expect(groundPolylinePrimitive.geometryInstances).not.toBeDefined(); expect(groundPolylinePrimitive.appearance).toBeInstanceOf( PolylineMaterialAppearance ); expect(groundPolylinePrimitive.show).toEqual(true); expect(groundPolylinePrimitive.interleave).toEqual(false); expect(groundPolylinePrimitive.releaseGeometryInstances).toEqual(true); expect(groundPolylinePrimitive.allowPicking).toEqual(true); expect(groundPolylinePrimitive.asynchronous).toEqual(true); expect(groundPolylinePrimitive.debugShowBoundingVolume).toEqual(false); expect(groundPolylinePrimitive.debugShowShadowVolume).toEqual(false); }); it("constructs with options", function () { var geometryInstances = []; groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: geometryInstances, show: false, interleave: true, releaseGeometryInstances: false, allowPicking: false, asynchronous: false, debugShowBoundingVolume: true, debugShowShadowVolume: true, }); expect(groundPolylinePrimitive.geometryInstances).toEqual( geometryInstances ); expect(groundPolylinePrimitive.show).toEqual(false); expect(groundPolylinePrimitive.interleave).toEqual(true); expect(groundPolylinePrimitive.releaseGeometryInstances).toEqual(false); expect(groundPolylinePrimitive.allowPicking).toEqual(false); expect(groundPolylinePrimitive.asynchronous).toEqual(false); expect(groundPolylinePrimitive.debugShowBoundingVolume).toEqual(true); expect(groundPolylinePrimitive.debugShowShadowVolume).toEqual(true); }); it("releases geometry instances when releaseGeometryInstances is true", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, releaseGeometryInstances: true, asynchronous: false, }); expect(groundPolylinePrimitive.geometryInstances).toBeDefined(); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); expect(groundPolylinePrimitive.geometryInstances).not.toBeDefined(); }); it("does not release geometry instances when releaseGeometryInstances is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, releaseGeometryInstances: false, asynchronous: false, }); expect(groundPolylinePrimitive.geometryInstances).toBeDefined(); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); expect(groundPolylinePrimitive.geometryInstances).toBeDefined(); }); it("adds afterRender promise to frame state", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, releaseGeometryInstances: false, asynchronous: false, }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); return groundPolylinePrimitive.readyPromise.then(function (param) { expect(param.ready).toBe(true); }); }); it("does not render when geometryInstances is undefined", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: undefined, asynchronous: false, }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); expect(scene.frameState.commandList.length).toEqual(0); }); it("does not render when show is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBeGreaterThan(0); groundPolylinePrimitive.show = false; scene.renderForSpecs(); expect(scene.frameState.commandList.length).toEqual(0); }); it("becomes ready when show is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = scene.groundPrimitives.add( new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, }) ); groundPolylinePrimitive.show = false; var ready = false; groundPolylinePrimitive.readyPromise.then(function () { ready = true; }); return pollToPromise(function () { scene.renderForSpecs(); return ready; }).then(function () { expect(ready).toEqual(true); }); }); it("does not render other than for the color or pick pass", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, }); var frameState = scene.frameState; frameState.passes.render = false; frameState.passes.pick = false; groundPolylinePrimitive.update(frameState); expect(frameState.commandList.length).toEqual(0); }); function coordinateOfPixelColor(rgba, color) { for (var y = 0; y < canvasHeight; y++) { for (var x = 0; x < canvasWidth; x++) { var i = (y * canvasWidth + x) * 4; if ( color[0] === rgba[i] && color[1] === rgba[i + 1] && color[2] === rgba[i + 2] && color[3] === rgba[i + 3] ) { return new Cartesian2(x, canvasHeight - y); } } } } function verifyGroundPolylinePrimitiveRender( lookPosition, primitive, color ) { scene.camera.lookAt(lookPosition, Cartesian3.UNIT_Z); scene.groundPrimitives.add(depthRectanglePrimitive); expect(scene).toRenderAndCall(function (rgba) { expect(coordinateOfPixelColor(rgba, depthColor)).toBeDefined(); }); scene.groundPrimitives.add(primitive); var coordinate; expect(scene).toRenderAndCall(function (rgba) { coordinate = coordinateOfPixelColor(rgba, color); expect(coordinate).toBeDefined(); }); return coordinate; } it("renders in 3D", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); }); it("renders in Columbus view when scene3DOnly is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); scene.morphToColumbusView(0); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); }); it("renders in 2D when scene3DOnly is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); scene.morphTo2D(0); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); }); it("renders during morph when scene3DOnly is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: Cartesian3.fromDegreesArray([-30, 0.0, 30, 0.0]), granularity: 0.0, width: 1000.0, loop: false, ellipsoid: ellipsoid, }), attributes: { color: polylineColorAttribute, }, }), asynchronous: false, appearance: new PolylineColorAppearance(), }); scene.groundPrimitives.add(depthRectanglePrimitive); scene.groundPrimitives.add(groundPolylinePrimitive); // Morph to 2D first scene.morphTo2D(0); scene.renderForSpecs(); scene.morphToColumbusView(1); // Morph changes the view distance to be very far, so: // * the mock globe may not be visible due to small canvas size // * GroundPolylinePrimitive renders its volume instead of using the // volume as a stencil for sampling the depth texture // So just check that the ground polyline primitive rendered. expect(scene).toRenderAndCall(function (rgba) { expect(coordinateOfPixelColor(rgba, polylineColor)).toBeDefined(); }); scene.completeMorph(); }); it("renders batched instances", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } var instance1 = new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: positions, granularity: 0.0, width: 1.0, loop: false, ellipsoid: ellipsoid, }), id: "polyline on terrain", attributes: { color: ColorGeometryInstanceAttribute.fromColor( new Color(1.0, 1.0, 1.0, 0.5) ), }, }); var instance2 = new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: positions, granularity: 0.0, width: 1.0, loop: false, ellipsoid: ellipsoid, }), id: "polyline on terrain", attributes: { color: ColorGeometryInstanceAttribute.fromColor( new Color(1.0, 1.0, 1.0, 0.5) ), }, }); groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: [instance1, instance2], asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, [192, 192, 255, 255] ); }); it("renders bounding volume with debugShowBoundingVolume", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), debugShowBoundingVolume: true, }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.camera.lookAt(lookPosition, Cartesian3.UNIT_Z); expect(scene).toRenderAndCall(function (rgba) { expect(rgba[1]).toBeGreaterThanOrEqualTo(0); expect(rgba[1]).toBeGreaterThanOrEqualTo(0); expect(rgba[2]).toBeGreaterThanOrEqualTo(0); expect(rgba[3]).toEqual(255); }); }); it("renders shadow volume with debugShowShadowVolume", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), debugShowShadowVolume: true, }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.camera.lookAt(lookPosition, Cartesian3.UNIT_Z); expect(scene).toRenderAndCall(function (rgba) { expect(rgba[1]).toBeGreaterThanOrEqualTo(0); expect(rgba[1]).toBeGreaterThanOrEqualTo(0); expect(rgba[2]).toBeGreaterThanOrEqualTo(0); expect(rgba[3]).toEqual(255); }); }); it("get per instance attributes", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(attributes.color).toBeDefined(); }); it("modify color instance attribute", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); // Remove so it can be re-added, but don't destroy. scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; var newColor = [255, 255, 255, 255]; var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(attributes.color).toBeDefined(); attributes.color = newColor; verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, newColor ); }); it("adds width instance attribute", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPositionOffset, groundPolylinePrimitive, polylineColor ); scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(attributes.width).toBeDefined(); attributes.width = [0]; verifyGroundPolylinePrimitiveRender( lookPositionOffset, groundPolylinePrimitive, depthColor ); }); it("modify show instance attribute", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylineInstance.attributes.show = new ShowGeometryInstanceAttribute( true ); groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(attributes.show).toBeDefined(); attributes.show = [0]; verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, depthColor ); }); it("renders with distance display condition per instance attribute", function () { if (!context.floatingPointTexture) { return; } if (!GroundPolylinePrimitive.isSupported(scene)) { return; } var near = 10.0; var far = 1000.0; var geometryInstance = new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: positions, granularity: 0.0, width: 1000.0, loop: false, ellipsoid: ellipsoid, }), id: "polyline on terrain", attributes: { distanceDisplayCondition: new DistanceDisplayConditionGeometryInstanceAttribute( near, far ), color: polylineColorAttribute, }, }); groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: geometryInstance, asynchronous: false, }); scene.groundPrimitives.add(depthRectanglePrimitive); scene.groundPrimitives.add(groundPolylinePrimitive); scene.camera.lookAt(lookPosition, Cartesian3.UNIT_Z); scene.renderForSpecs(); var boundingSphere = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ).boundingSphere; var center = boundingSphere.center; var radius = boundingSphere.radius; scene.camera.lookAt( center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius) ); expect(scene).toRenderAndCall(function (rgba) { expect(coordinateOfPixelColor(rgba, depthColor)).toBeDefined(); }); scene.camera.lookAt( center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + near + 1.0) ); expect(scene).toRenderAndCall(function (rgba) { expect(coordinateOfPixelColor(rgba, depthColor)).toBeUndefined(); }); scene.camera.lookAt( center, new HeadingPitchRange(0.0, -CesiumMath.PI_OVER_TWO, radius + far + 1.0) ); expect(scene).toRenderAndCall(function (rgba) { expect(coordinateOfPixelColor(rgba, depthColor)).toBeDefined(); }); }); it("getGeometryInstanceAttributes returns same object each time", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylineInstance.attributes.show = new ShowGeometryInstanceAttribute( true ); groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); var attributes2 = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(attributes).toBe(attributes2); }); it("picking in 3D", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); var polylineColorCoordinate = verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); expect(scene).toPickAndCall(function (result) { expect(result.id).toEqual("polyline on terrain"); }, polylineColorCoordinate); }); it("picking in 2D", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); scene.morphTo2D(0); var polylineColorCoordinate = verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); expect(scene).toPickAndCall(function (result) { expect(result.id).toEqual("polyline on terrain"); }, polylineColorCoordinate); }); it("picking in Columbus View", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); scene.morphToColumbusView(0); var polylineColorCoordinate = verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); scene.camera.lookAt(lookPosition, Cartesian3.UNIT_Z); expect(scene).toPickAndCall(function (result) { expect(result.id).toEqual("polyline on terrain"); }, polylineColorCoordinate); }); it("picking in Morph", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: Cartesian3.fromDegreesArray([-30, 0.0, 30, 0.0]), granularity: 0.0, width: 1000.0, loop: false, ellipsoid: ellipsoid, }), attributes: { color: polylineColorAttribute, }, id: "big polyline on terrain", }), asynchronous: false, appearance: new PolylineColorAppearance(), }); // Morph to 2D first scene.morphTo2D(0); scene.renderForSpecs(); scene.morphToColumbusView(1); // Morph changes the view distance to be very far, so: // * the mock globe may not be visible due to small canvas size // * GroundPolylinePrimitive renders its volume instead of using the // volume as a stencil for sampling the depth texture // So just check that the ground polyline primitive rendered. scene.groundPrimitives.add(depthRectanglePrimitive); scene.groundPrimitives.add(groundPolylinePrimitive); var polylineColorCoordinate; expect(scene).toRenderAndCall(function (rgba) { polylineColorCoordinate = coordinateOfPixelColor(rgba, polylineColor); }); scene.renderForSpecs(); expect(scene).toPickAndCall(function (result) { expect(result.id).toEqual("big polyline on terrain"); }, polylineColorCoordinate); scene.completeMorph(); }); it("does not pick when allowPicking is false", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, allowPicking: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); expect(scene).toPickAndCall(function (result) { expect(result.id).toEqual("depth rectangle"); }); }); it("update throws when batched instance colors are missing", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: new GeometryInstance({ geometry: new GroundPolylineGeometry({ positions: positions, }), }), appearance: new PolylineColorAppearance(), asynchronous: false, }); expect(function () { verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); }).toThrowDeveloperError(); }); it("setting per instance attribute throws when value is undefined", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(function () { attributes.color = undefined; }).toThrowDeveloperError(); }); it("can disable picking when asynchronous", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: true, allowPicking: false, appearance: new PolylineColorAppearance(), }); scene.groundPrimitives.add(groundPolylinePrimitive); return pollToPromise(function () { scene.renderForSpecs(); return groundPolylinePrimitive.ready; }).then(function () { var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes( "polyline on terrain" ); expect(function () { attributes.color = undefined; }).toThrowDeveloperError(); }); }); it("getGeometryInstanceAttributes throws without id", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); expect(function () { groundPolylinePrimitive.getGeometryInstanceAttributes(); }).toThrowDeveloperError(); }); it("getGeometryInstanceAttributes returns undefined if id does not exist", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, appearance: new PolylineColorAppearance(), }); expect(function () { groundPolylinePrimitive.getGeometryInstanceAttributes("unknown"); }).toThrowDeveloperError(); }); it("isDestroyed", function () { groundPolylinePrimitive = new GroundPolylinePrimitive(); expect(groundPolylinePrimitive.isDestroyed()).toEqual(false); groundPolylinePrimitive.destroy(); expect(groundPolylinePrimitive.isDestroyed()).toEqual(true); }); it("renders when using asynchronous pipeline", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: true, appearance: new PolylineColorAppearance(), }); scene.groundPrimitives.add(groundPolylinePrimitive); return pollToPromise(function () { scene.renderForSpecs(); return groundPolylinePrimitive.ready; }).then(function () { // verifyGroundPolylinePrimitiveRender adds the primitive, so remove it to avoid being added twice. scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; verifyGroundPolylinePrimitiveRender( lookPosition, groundPolylinePrimitive, polylineColor ); }); }); it("destroy before asynchronous pipeline is complete", function () { if (!GroundPolylinePrimitive.isSupported(scene)) { return; } groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: true, appearance: new PolylineColorAppearance(), }); scene.groundPrimitives.add(groundPolylinePrimitive); scene.renderForSpecs(); groundPolylinePrimitive.destroy(); expect(groundPolylinePrimitive.isDestroyed()).toEqual(true); // The primitive has already been destroyed, so remove it from the scene so it doesn't get destroyed again. scene.groundPrimitives.destroyPrimitives = false; scene.groundPrimitives.removeAll(); scene.groundPrimitives.destroyPrimitives = true; }); it("creating a synchronous primitive throws if initializeTerrainHeights wasn't called", function () { // Make it seem like initializeTerrainHeights was never called var initPromise = ApproximateTerrainHeights._initPromise; var terrainHeights = ApproximateTerrainHeights._terrainHeights; ApproximateTerrainHeights._initPromise = undefined; ApproximateTerrainHeights._terrainHeights = undefined; groundPolylinePrimitive = new GroundPolylinePrimitive({ geometryInstances: groundPolylineInstance, asynchronous: false, }); scene.groundPrimitives.add(groundPolylinePrimitive); if (GroundPolylinePrimitive.isSupported(scene)) { expect(function () { scene.renderForSpecs(); }).toThrowDeveloperError(); } // Set back to initialized state ApproximateTerrainHeights._initPromise = initPromise; ApproximateTerrainHeights._terrainHeights = terrainHeights; }); }, "WebGL" );