import { BoundingSphere } from "../../Source/Cesium.js"; import { Cartesian3 } from "../../Source/Cesium.js"; import { Clock } from "../../Source/Cesium.js"; import { ClockStep } from "../../Source/Cesium.js"; import { defaultValue } from "../../Source/Cesium.js"; import { defined } from "../../Source/Cesium.js"; import { HeadingPitchRange } from "../../Source/Cesium.js"; import { HeadingPitchRoll } from "../../Source/Cesium.js"; import { JulianDate } from "../../Source/Cesium.js"; import { Matrix4 } from "../../Source/Cesium.js"; import { Resource } from "../../Source/Cesium.js"; import { TimeIntervalCollection } from "../../Source/Cesium.js"; import { Transforms } from "../../Source/Cesium.js"; import { Cesium3DTileStyle } from "../../Source/Cesium.js"; import { ClippingPlane } from "../../Source/Cesium.js"; import { ClippingPlaneCollection } from "../../Source/Cesium.js"; import { DracoLoader } from "../../Source/Cesium.js"; import { PointCloudEyeDomeLighting } from "../../Source/Cesium.js"; import { ShadowMode } from "../../Source/Cesium.js"; import { TimeDynamicPointCloud } from "../../Source/Cesium.js"; import createCanvas from "../createCanvas.js"; import createScene from "../createScene.js"; import pollToPromise from "../pollToPromise.js"; import { when } from "../../Source/Cesium.js"; describe( "Scene/TimeDynamicPointCloud", function () { var scene; var center = new Cartesian3( 1215012.8828876738, -4736313.051199594, 4081605.22126042 ); var clock = new Clock({ clockStep: ClockStep.TICK_DEPENDENT, shouldAnimate: true, }); var dates = [ JulianDate.fromIso8601("2018-07-19T15:18:00Z"), JulianDate.fromIso8601("2018-07-19T15:18:00.5Z"), JulianDate.fromIso8601("2018-07-19T15:18:01Z"), JulianDate.fromIso8601("2018-07-19T15:18:01.5Z"), JulianDate.fromIso8601("2018-07-19T15:18:02Z"), JulianDate.fromIso8601("2018-07-19T15:18:02.5Z"), ]; var transforms = [ Matrix4.fromColumnMajorArray([ 0.968635634376879, 0.24848542777253735, 0, 0, -0.15986460794399626, 0.6231776137472074, 0.7655670897127491, 0, 0.190232265775849, -0.7415555636019701, 0.6433560687121489, 0, 1215012.8828876738, -4736313.051199594, 4081605.22126042, 1, ]), Matrix4.fromColumnMajorArray([ 0.968634888916237, 0.24848833367832227, 0, 0, -0.1598664774761181, 0.6231771341505793, 0.7655670897127493, 0, 0.19023449044168372, -0.7415549929018358, 0.6433560687121489, 0, 1215027.0918213597, -4736309.406139632, 4081605.22126042, 1, ]), Matrix4.fromColumnMajorArray([ 0.9686341434468771, 0.24849123958187078, 0, 0, -0.1598683470068011, 0.6231766545483426, 0.7655670897127493, 0, 0.19023671510580634, -0.7415544221950274, 0.6433560687121489, 0, 1215041.3007441103, -4736305.761037043, 4081605.22126042, 1, ]), Matrix4.fromColumnMajorArray([ 0.9686333979687994, 0.24849414548318288, 0, 0, -0.15987021653604533, 0.6231761749404972, 0.7655670897127491, 0, 0.19023893976821685, -0.7415538514815451, 0.6433560687121489, 0, 1215055.5096559257, -4736302.115891827, 4081605.22126042, 1, ]), Matrix4.fromColumnMajorArray([ 0.9686326524820043, 0.2484970513822586, 0, 0, -0.15987208606385075, 0.6231756953270434, 0.7655670897127492, 0, 0.19024116442891523, -0.7415532807613887, 0.6433560687121489, 0, 1215069.7185568055, -4736298.470703985, 4081605.22126042, 1, ]), ]; function createIntervals(useTransforms, useDraco) { var folderName; if (useTransforms) { folderName = "Data/Cesium3DTiles/PointCloud/PointCloudTimeDynamicWithTransform/"; } else if (useDraco) { folderName = "Data/Cesium3DTiles/PointCloud/PointCloudTimeDynamicDraco/"; } else { folderName = "Data/Cesium3DTiles/PointCloud/PointCloudTimeDynamic/"; } var uris = []; for (var i = 0; i < 5; ++i) { uris.push(folderName + i + ".pnts"); } function dataCallback(interval, index) { return { uri: uris[index], transform: useTransforms ? transforms[index] : undefined, }; } return TimeIntervalCollection.fromJulianDateArray({ julianDates: dates, dataCallback: dataCallback, }); } function createTimeDynamicPointCloud(options) { options = defaultValue(options, {}); var useTransforms = defaultValue(options.useTransforms, false); var useDraco = defaultValue(options.useDraco, false); options.intervals = createIntervals(useTransforms, useDraco); options.clock = clock; if (!defined(options.style)) { options.style = new Cesium3DTileStyle({ color: 'color("red")', pointSize: 10, }); } return scene.primitives.add(new TimeDynamicPointCloud(options)); } function zoomTo(center) { scene.camera.lookAt(center, new HeadingPitchRange(0.0, -1.57, 5.0)); } function loadFrame(pointCloud, index) { index = defaultValue(index, 0); goToFrame(index); return pollToPromise(function () { scene.renderForSpecs(); var frame = pointCloud._frames[index]; var ready = defined(frame) && frame.ready; if (ready) { scene.renderForSpecs(); } return ready; }); } function getLoadFrameFunction(pointCloud, index) { return function () { return loadFrame(pointCloud, index); }; } function loadFrames(pointCloud, indexes) { var length = indexes.length; var promise = getLoadFrameFunction(pointCloud, indexes[0])(); for (var i = 1; i < length; ++i) { promise = promise.then(getLoadFrameFunction(pointCloud, indexes[i])); } return promise.then(function () { goToFrame(indexes[0]); }); } function loadAllFrames(pointCloud) { return loadFrames(pointCloud, [0, 1, 2, 3, 4]); } function goToFrame(index) { clock.currentTime = dates[index]; clock.multiplier = 0.0; } function initializeScene() { scene.morphTo3D(0.0); zoomTo(center); goToFrame(0); } beforeAll(function () { scene = createScene(); }); afterAll(function () { scene.destroyForSpecs(); }); beforeEach(function () { initializeScene(); }); afterEach(function () { scene.primitives.removeAll(); }); it("throws if options.clock is undefined", function () { var intervals = createIntervals(); expect(function () { return new TimeDynamicPointCloud({ intervals: intervals, }); }).toThrowDeveloperError(); }); it("throws if options.intervals is undefined", function () { expect(function () { return new TimeDynamicPointCloud({ clock: clock, }); }).toThrowDeveloperError(); }); it("renders in 3D", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { scene.morphTo3D(0.0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); scene.camera.moveRight(10.0); expect(scene).toRender([0, 0, 0, 255]); }); }); it("renders in 2D", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { scene.morphTo2D(0.0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); scene.camera.moveRight(10.0); expect(scene).toRender([0, 0, 0, 255]); }); }); it("renders in CV", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { scene.morphToColumbusView(0.0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); scene.camera.moveRight(10.0); expect(scene).toRender([0, 0, 0, 255]); }); }); it("gets bounding sphere of the rendered frame", function () { var pointCloud = createTimeDynamicPointCloud({ useTransforms: true, }); expect(pointCloud.boundingSphere).toBeUndefined(); // Undefined until a frame is rendered return loadAllFrames(pointCloud).then(function () { var boundingSphereFrame0 = pointCloud.boundingSphere; expect(boundingSphereFrame0).toBeDefined(); goToFrame(1); scene.renderForSpecs(); var boundingSphereFrame1 = pointCloud.boundingSphere; expect(boundingSphereFrame1).toBeDefined(); expect( BoundingSphere.equals(boundingSphereFrame0, boundingSphereFrame1) ).toBe(false); }); }); it("resolves ready promise", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { return pointCloud.readyPromise.then(function (pointCloud) { expect(pointCloud.boundingSphere).toBeDefined(); }); }); }); it("sets show", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { expect(scene).toRender([255, 0, 0, 255]); pointCloud.show = false; expect(scene).toRender([0, 0, 0, 255]); }); }); it("sets model matrix", function () { var translation = new Cartesian3(10000, 2000, 100); var modelMatrix = Matrix4.fromTranslation(translation); var newCenter = Cartesian3.add(center, translation, new Cartesian3()); var pointCloud = createTimeDynamicPointCloud({ modelMatrix: modelMatrix, }); return loadFrame(pointCloud).then(function () { expect(scene).toRender([0, 0, 0, 255]); // Out of view zoomTo(newCenter); expect(scene).toRender([255, 0, 0, 255]); pointCloud.modelMatrix = Matrix4.IDENTITY; expect(scene).toRender([0, 0, 0, 255]); // Out of view zoomTo(center); expect(scene).toRender([255, 0, 0, 255]); }); }); it("sets shadows", function () { var pointCloud = createTimeDynamicPointCloud({ shadows: ShadowMode.DISABLED, }); return loadFrame(pointCloud).then(function () { scene.renderForSpecs(); expect(scene.frameState.commandList[0].castShadows).toBe(false); expect(scene.frameState.commandList[0].receiveShadows).toBe(false); pointCloud.shadows = ShadowMode.ENABLED; scene.renderForSpecs(); expect(scene.frameState.commandList[0].castShadows).toBe(true); expect(scene.frameState.commandList[0].receiveShadows).toBe(true); }); }); it("honors maximumMemoryUsage by unloading all frames not currently being loaded or rendered", function () { var pointCloud = createTimeDynamicPointCloud(); return loadAllFrames(pointCloud).then(function () { var singleFrameMemoryUsage = 33000; var frames = pointCloud._frames; var framesLength = frames.length; expect(pointCloud.totalMemoryUsageInBytes).toBe( singleFrameMemoryUsage * framesLength ); pointCloud.maximumMemoryUsage = 0; // Expect all frames except the current frame to be undefined scene.renderForSpecs(); expect(pointCloud.totalMemoryUsageInBytes).toBe(singleFrameMemoryUsage); expect(frames[0].ready).toBe(true); for (var i = 1; i < length; ++i) { expect(frames[i]).toBeUndefined(); } // The loading frame and last rendered frame are not unloaded goToFrame(1); scene.renderForSpecs(); expect(pointCloud.totalMemoryUsageInBytes).toBe(singleFrameMemoryUsage); expect(frames[0].ready).toBe(true); expect(frames[1].ready).toBe(false); // The loaded frame is the only one loaded return loadFrame(pointCloud, 1).then(function () { expect(pointCloud.totalMemoryUsageInBytes).toBe( singleFrameMemoryUsage ); expect(frames[0]).toBeUndefined(); expect(frames[1].ready).toBe(true); }); }); }); it("enables attenuation and eye dome lighting", function () { var oldScene = scene; scene = createScene({ canvas: createCanvas(100, 100), }); initializeScene(); var pointCloud = createTimeDynamicPointCloud({ shading: { attenuation: true, eyeDomeLighting: false, }, style: new Cesium3DTileStyle(), }); return loadFrame(pointCloud).then(function () { var attenuationPixelCount; expect(scene).toRenderPixelCountAndCall(function (pixelCount) { attenuationPixelCount = pixelCount; }); // Disable attenuation and expect less pixels to be drawn pointCloud.shading.attenuation = false; expect(scene).toRenderPixelCountAndCall(function (pixelCount) { expect(pixelCount).toBeLessThan(attenuationPixelCount); }); scene.destroyForSpecs(); scene = oldScene; }); }); it("enabled eye dome lighting", function () { if (!PointCloudEyeDomeLighting.isSupported(scene.frameState.context)) { return; } var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { expect(scene.frameState.commandList.length).toBe(1); pointCloud.shading.attenuation = true; pointCloud.shading.eyeDomeLighting = true; scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBe(3); // Added 2 EDL commands }); }); it("sets style", function () { var pointCloud = createTimeDynamicPointCloud({ style: new Cesium3DTileStyle({ color: 'color("blue")', pointSize: 10, }), }); return loadAllFrames(pointCloud).then(function () { expect(scene).toRender([0, 0, 255, 255]); pointCloud.style = new Cesium3DTileStyle({ color: 'color("lime")', pointSize: 10, }); expect(scene).toRender([0, 255, 0, 255]); goToFrame(1); // Also check that the style is updated for the next frame expect(scene).toRender([0, 255, 0, 255]); }); }); it("make style dirty", function () { var pointCloud = createTimeDynamicPointCloud({ style: new Cesium3DTileStyle({ color: 'color("blue")', pointSize: 10, }), }); return loadAllFrames(pointCloud).then(function () { expect(scene).toRender([0, 0, 255, 255]); pointCloud.style.color = 'color("lime")'; pointCloud.makeStyleDirty(); expect(scene).toRender([0, 255, 0, 255]); goToFrame(1); // Also check that the style is updated for the next frame expect(scene).toRender([0, 255, 0, 255]); }); }); it("sets clipping planes", function () { var modelMatrix = new Transforms.headingPitchRollToFixedFrame( center, new HeadingPitchRoll(0, 0, 0) ); var clippingPlanesX = new ClippingPlaneCollection({ modelMatrix: modelMatrix, planes: [new ClippingPlane(Cartesian3.UNIT_X, 0.0)], }); var clippingPlanesY = new ClippingPlaneCollection({ modelMatrix: modelMatrix, planes: [new ClippingPlane(Cartesian3.UNIT_Y, 0.0)], }); var pointCloud = createTimeDynamicPointCloud({ clippingPlanes: clippingPlanesX, }); return loadAllFrames(pointCloud).then(function () { // Go to unclipped area (right half) scene.camera.moveRight(0.1); goToFrame(0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); // Go to clipped area (left half) scene.camera.moveLeft(0.2); goToFrame(0); expect(scene).toRender([0, 0, 0, 255]); goToFrame(1); expect(scene).toRender([0, 0, 0, 255]); // Same area no longer clipped. Responds to clipping planes updates. pointCloud.clippingPlanes.enabled = false; goToFrame(0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); // Sets a new clipping plane that uses a different axis // Go to unclipped area (bottom left) pointCloud.clippingPlanes = clippingPlanesY; scene.camera.moveRight(0.2); scene.camera.moveUp(0.1); goToFrame(0); expect(scene).toRender([255, 0, 0, 255]); goToFrame(1); expect(scene).toRender([255, 0, 0, 255]); // Go to clipped area (bottom right) scene.camera.moveDown(0.2); goToFrame(0); expect(scene).toRender([0, 0, 0, 255]); goToFrame(1); expect(scene).toRender([0, 0, 0, 255]); }); }); it("works with frame transforms", function () { var pointCloud = createTimeDynamicPointCloud({ useTransforms: true, }); return loadAllFrames(pointCloud).then(function () { goToFrame(0); expect(scene).toRender([255, 0, 0, 255]); // The transform shifted the point cloud to the right goToFrame(1); expect(scene).toRender([0, 0, 0, 255]); scene.camera.moveRight(10.0); expect(scene).toRender([255, 0, 0, 255]); }); }); it("does not render during morph", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBeGreaterThan(0); scene.morphToColumbusView(1.0); scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBe(0); }); }); it("renders frames using Draco compression", function () { var pointCloud = createTimeDynamicPointCloud({ useDraco: true, }); return loadFrame(pointCloud).then(function () { expect(scene).toRender([255, 0, 0, 255]); }); }); it("picks", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { pointCloud.show = false; expect(scene).toPickPrimitive(undefined); pointCloud.show = true; expect(scene).toPickPrimitive(pointCloud); }); }); it("does not render if current time is out of range", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { // Before clock.currentTime = JulianDate.addSeconds( dates[0], -10.0, new JulianDate() ); scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBe(0); // During clock.currentTime = dates[0]; scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBe(1); // After clock.currentTime = JulianDate.addSeconds( dates[5], 10.0, new JulianDate() ); scene.renderForSpecs(); expect(scene.frameState.commandList.length).toBe(0); }); }); it("prefetches different frame when clock multiplier changes", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(pointCloud, "_getAverageLoadTime").and.returnValue(0.5); return loadFrame(pointCloud).then(function () { expect(pointCloud._frames[1]).toBeUndefined(); clock.multiplier = 1.0; scene.renderForSpecs(); expect(pointCloud._frames[1]).toBeDefined(); clock.multiplier = 4.0; scene.renderForSpecs(); expect(pointCloud._frames[2]).toBeUndefined(); expect(pointCloud._frames[3]).toBeUndefined(); expect(pointCloud._frames[4]).toBeDefined(); }); }); it("renders last rendered frame while new frame loads", function () { var pointCloud = createTimeDynamicPointCloud(); return loadFrame(pointCloud).then(function () { var commandList = scene.frameState.commandList; var firstFrameCommand = commandList[0]; goToFrame(4); return pollToPromise(function () { scene.renderForSpecs(); var frame = pointCloud._frames[4]; var ready = defined(frame) && frame.ready; if (!ready) { expect(commandList[0]).toBe(firstFrameCommand); } return ready; }).then(function () { scene.renderForSpecs(); expect(commandList[0]).toBeDefined(); expect(commandList[0]).not.toBe(firstFrameCommand); }); }); }); it("skips frames based on average load time and clock multiplier", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(pointCloud, "_getAverageLoadTime").and.returnValue(2.0); scene.renderForSpecs(); // at 0.0 seconds - loads frame 0 clock.multiplier = 0.6; scene.renderForSpecs(); // at 0.0 seconds - preloads frame 2 at 1.2 seconds clock.tick(); scene.renderForSpecs(); // at 0.6 seconds clock.tick(); scene.renderForSpecs(); // at 1.2 seconds - preloads frame 4 at 2.4 seconds clock.tick(); scene.renderForSpecs(); // at 1.8 seconds clock.tick(); scene.renderForSpecs(); // at 2.4 seconds var frames = pointCloud._frames; expect(frames[0]).toBeDefined(); expect(frames[1]).toBeUndefined(); expect(frames[2]).toBeDefined(); expect(frames[3]).toBeUndefined(); expect(frames[4]).toBeDefined(); }); it("does not skip frames if clock multiplier is sufficiently slow", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(pointCloud, "_getAverageLoadTime").and.returnValue(0.5); scene.renderForSpecs(); // at 0.0 seconds - loads frame 0 clock.multiplier = 0.6; scene.renderForSpecs(); // at 0.0 seconds - preloads frame 1 clock.tick(); scene.renderForSpecs(); // at 0.6 seconds - preloads frame 2 clock.tick(); scene.renderForSpecs(); // at 1.2 seconds - preloads frame 3 clock.tick(); scene.renderForSpecs(); // at 1.8 seconds - preloads frame 4 clock.tick(); scene.renderForSpecs(); // at 2.4 seconds var frames = pointCloud._frames; expect(frames[0]).toBeDefined(); expect(frames[1]).toBeDefined(); expect(frames[2]).toBeDefined(); expect(frames[3]).toBeDefined(); expect(frames[4]).toBeDefined(); }); it("renders loaded frames between the previous frame and next frame", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(pointCloud, "_getAverageLoadTime").and.returnValue(3.4); var frames = pointCloud._frames; return loadFrames(pointCloud, [0, 2]).then(function () { clock.multiplier = 0.6; scene.renderForSpecs(); // at 0.0 seconds - preloads frame 4 at 2.04 seconds - renders frame 0 expect(pointCloud._lastRenderedFrame).toBe(frames[0]); clock.tick(); scene.renderForSpecs(); // at 0.6 seconds - renders frame 0 expect(pointCloud._lastRenderedFrame).toBe(frames[0]); clock.tick(); scene.renderForSpecs(); // at 1.2 seconds - renders frame 2 which has already been loaded expect(pointCloud._lastRenderedFrame).toBe(frames[2]); clock.tick(); scene.renderForSpecs(); // at 1.8 seconds - renders frame 2 expect(pointCloud._lastRenderedFrame).toBe(frames[2]); }); }); it("works with negative clock multiplier", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(pointCloud, "_getAverageLoadTime").and.returnValue(2.0); goToFrame(4); scene.renderForSpecs(); // at 2.0 seconds - loads frame 4 clock.multiplier = -0.6; scene.renderForSpecs(); // at 2.0 seconds - preloads frame 1 at 0.8 seconds clock.tick(); scene.renderForSpecs(); // at 1.4 seconds clock.tick(); scene.renderForSpecs(); // at 0.8 seconds - nothing left to preload clock.tick(); scene.renderForSpecs(); // at 0.2 seconds clock.tick(); scene.renderForSpecs(); // at -0.4 seconds var frames = pointCloud._frames; expect(frames[0]).toBeUndefined(); expect(frames[1]).toBeDefined(); expect(frames[2]).toBeUndefined(); expect(frames[3]).toBeUndefined(); expect(frames[4]).toBeDefined(); }); it("frames not loaded in sequential updates do not impact average load time", function () { var pointCloud = createTimeDynamicPointCloud(); expect(pointCloud._runningAverage).toBe(0.0); return loadFrame(pointCloud).then(function () { expect(pointCloud._frames[0].sequential).toBe(true); expect(pointCloud._runningLength).toBe(1); expect(pointCloud._runningAverage).toBeGreaterThan(0.0); goToFrame(2); // Start loading frame 2, but don't finish loading it now scene.renderForSpecs(); return loadFrame(pointCloud, 1).then(function () { var twoFrameAverage = pointCloud._runningAverage; expect(pointCloud._frames[1].sequential).toBe(true); expect(pointCloud._runningLength).toBe(2); expect(pointCloud._runningAverage).toBeGreaterThan(0.0); return loadFrame(pointCloud, 2).then(function () { expect(pointCloud._frames[2].sequential).toBe(false); expect(pointCloud._runningLength).toBe(2); // No update expect(pointCloud._runningAverage).toBe(twoFrameAverage); // No update }); }); }); }); it("frame failed event is raised from request failure", function () { var pointCloud = createTimeDynamicPointCloud(); spyOn(Resource._Implementations, "loadWithXhr").and.callFake(function ( request, responseType, method, data, headers, deferred, overrideMimeType ) { deferred.reject("404"); }); var spyUpdate = jasmine.createSpy("listener"); pointCloud.frameFailed.addEventListener(spyUpdate); var i; for (i = 0; i < 5; ++i) { goToFrame(i); scene.renderForSpecs(); } for (i = 0; i < 5; ++i) { var arg = spyUpdate.calls.argsFor(i)[0]; expect(arg).toBeDefined(); expect(arg.uri).toContain(i + ".pnts"); expect(arg.message).toBe("404"); } }); it("failed frame event is raised from Draco failure", function () { var pointCloud = createTimeDynamicPointCloud({ useDraco: true, }); return loadFrame(pointCloud).then(function () { var decoder = DracoLoader._getDecoderTaskProcessor(); spyOn(decoder, "scheduleTask").and.returnValue( when.reject({ message: "my error" }) ); var spyUpdate = jasmine.createSpy("listener"); pointCloud.frameFailed.addEventListener(spyUpdate); goToFrame(1); scene.renderForSpecs(); var failedPromise; var frameFailed = false; return pollToPromise(function () { var contents = pointCloud._frames[1].pointCloud; if (defined(contents) && !defined(failedPromise)) { failedPromise = contents.readyPromise.otherwise(function () { frameFailed = true; }); } scene.renderForSpecs(); return frameFailed; }).then(function () { var arg = spyUpdate.calls.argsFor(0)[0]; expect(arg).toBeDefined(); expect(arg.uri).toContain("1.pnts"); expect(arg.message).toBe("my error"); }); }); }); it("raises frame changed event", function () { var pointCloud = createTimeDynamicPointCloud(); var spyFrameChanged = jasmine.createSpy("listener"); pointCloud.frameChanged.addEventListener(spyFrameChanged); return loadAllFrames(pointCloud).then(function () { expect(spyFrameChanged.calls.count()).toBe(5); // Go to random frame goToFrame(2); scene.renderForSpecs(); expect(spyFrameChanged.calls.count()).toBe(6); // Go out of range. No event raised. clock.currentTime = JulianDate.addSeconds( dates[0], -10.0, new JulianDate() ); scene.renderForSpecs(); expect(spyFrameChanged.calls.count()).toBe(6); goToFrame(0); scene.renderForSpecs(); expect(spyFrameChanged.calls.count()).toBe(7); expect(spyFrameChanged.calls.argsFor(0)[0]).toBe(pointCloud); }); }); it("destroys", function () { var pointCloud = createTimeDynamicPointCloud(); return loadAllFrames(pointCloud).then(function () { expect(pointCloud.isDestroyed()).toEqual(false); scene.primitives.remove(pointCloud); expect(pointCloud.isDestroyed()).toEqual(true); expect(pointCloud.totalMemoryUsageInBytes).toBe(0); }); }); }, "WebGL" );