Layered Tile providers?

Nevermind, it’s working fine for both. I think it was just downloading slow when I tried earlier, and I just assumed that it was not working. Thanks for the help.

Great, glad to hear it’s working.

Hey guys, In the multiple layers branch, I am getting many webgl errors when I try to have more than one globe in my application. This works fine in main and has worked since we started using Cesium back in May. We have a dialog that contains another Cesium globe to preview and manage map layers and this a really important feature to keep.

Here are the errors.

WebGL: INVALID_OPERATION: bindBuffer: object not from this context index.html:1

WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER bound index.html:1

WebGL: INVALID_OPERATION: bindBuffer: object not from this context index.html:1

WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER bound index.html:1

WebGL: INVALID_OPERATION: bindBuffer: object not from this context index.html:1

WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER bound index.html:1

WebGL: INVALID_OPERATION: bindBuffer: object not from this context index.html:1

WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER bound index.html:1

WebGL: INVALID_OPERATION: bindBuffer: object not from this context index.html:1

WebGL: INVALID_OPERATION: drawElements: no ELEMENT_ARRAY_BUFFER bound index.html:1

WebGL: too many errors, no more errors will be reported to the console for this context.

You can reproduce this in the Skeleton example by placing another canvas in the index.html file. I also just duplicated the skeleton.js file and named it skeleton2.js and changed the canvas id in the file to the second canvas.

Skeleton body { padding: 0; margin: 0; width: 100%; height: 100%; overflow: hidden; } #glCanvas# { display: block;W border: none; width: 100%; height: 50%; }

I googled and read this

https://github.com/mrdoob/three.js/issues/2144

Sounds similar to this problem. Any ideas on how to fix this?

Hi Jonah,

As far as I know, you’re the first person to try using multiple globes in the imagery_layers branch, so I think you found a bug. Most likely the problem is in the code that attempts to save memory by sharing index buffers between patches of terrain. If I’m right, you should be able to change line 140 in TerrainProvider.js from this:

indexBuffer = buffers.indices.indexBuffer = context.createIndexBuffer(indices, BufferUsage.STATIC_DRAW, IndexDatatype.UNSIGNED_SHORT);

To this:

indexBuffer = context.createIndexBuffer(indices, BufferUsage.STATIC_DRAW, IndexDatatype.UNSIGNED_SHORT);

That will stop it from sharing the index buffer. We need a better solution, of course, but hopefully that will get you up and running. Let me know how it goes.

Kevin

That works great Kevin! I really appreciate the quick response with a correct solution.

Kevin,

I recently added a unique ID to the Context to allow caching per-context resources like vertex and index buffers. It’s not in master yet, but will be soon. For an example, see getVertexArray in ViewportQuad.js.

Patrick

Just letting you guys know that I found a problem with the ArcGisMapServerImageryProvider when you add this layer after the globe is initialized, you will see this error:

Uncaught TypeError: Cannot read property ‘north’ of undefined

Which happens on line 188 of the extent class in the intersectWith function

Extent.prototype.intersectWith = function(otherExtent) {

This is happening because the arcgis imagery provider defers setting it’s extent and tiling scheme until after getting the properties from the arcgis server. You can easily reproduce this in the skeleton by moving

var esriStreetsLayer = imageryLayerCollection.addImageryProvider(esriStreetsImageryProvider);

to the end of the class. I fixed it by setting an initial extent and tiling scheme, but there may be a better way. The other imagery providers work fine when you add them later.

While I am asking about imagery providers, I’m also seeing an issue with the single image tile provider with the following image:

I’m getting WebGL: INVALID_OPERATION: generateMipmap: level 0 not power of 2 or not all the same size

Why does Cesium not render this image?

Hi Jonah,

I haven’t had a chance to look at this closely, yet, but I suspect there’s a missing check of the “ready” property of the ImageryProvider somewhere. We’re not supposed to try to use an imagery provider until it advertises itself as ready. I’ll look into it closer, soon - probably tomorrow.

Regarding the power-of-two problem… WebGL unfortunately requires that mipmapped textures have a power-of-two (POT) size, like 128, 256, 512, etc. One easy solution is to not mipmap imagery textures. You can do that by removing the calls to generateMipmap in ImageryLayer (or in ImageryProvider if you’re not quite in sync with the head.) That’s not a great solution, though, because mipmapping is important for both performance and for visual quality. A better solution is to round non-POT (NPOT) textures to the next larger POT size, or perhaps to split a single image into multiple, each of which is a POT size. That will take a bit more work, though, and it may be a little while before Scott Hunter or I get to it. If you or someone else wants to try implementing it in the meantime, though, I can definitely provide some guidance.

Kevin

Thanks for the help Kevin. I think for now I will just convert the image to have a power of two size. Sorry, I don’t have the bandwidth at this point either to help out with that.

Hey again Kevin, what is the status of 2D mode for the imagery_layers branch? I can’t seem to get it working in the skeleton example or my own code. I am using the EllipsoidTerrainProvider and a SingleTileImageryProvider.

Sorry to say, it’s totally and completely broken! It will probably be at least a couple more weeks before Scott and I get around to working on 2D and Columbus View.

Oh ok. At least we have multiple imagery layers and terrain now. Awesome work!

Scott, Kevin, I hope someone can help me with this webworkers issue I am seeing in firefox. This did not seem to be a problem in the cesium development environment, but to get the webworkers running outside of the development environment, I modified this part of TaskProcessor

var uri = require.toUrl(‘Workers/’ + processor._workerName + ‘.js’);

var worker = new Worker(uri);

to

var worker = new Worker(‘path_to_webworker’);

createVerticesFromExtent.js

Because I was getting
TypeError: require.toUrl is not a function

I also modified the workers to import the Cesium.js file instead of using require.

Now I am seeing this in firefox.

postMessage is not a function


}, [vertices.buffer]);


Have you guys come across this problem before or know anything about it?

Thanks!

OK, I tried it out and was able to get it working. I did find a few problems along the way.

  1. the version of main.js that I committed earlier to fix the problem with “window” in the worker was still not quite right, I pushed a new commit. Your fix from earlier in the thread, which I assume you are still using locally, is fine though.

  2. You’re right about the missing require.toUrl. The AMD loader that we use for the all-in-one Cesium file doesn’t have that feature, which I didn’t realize. I’ll put in a real fix eventually, but for now, using the direct URI to the worker file is fine. You could also do something like:

var uri = ‘…/…/Build/’ + processor._workerName + ‘.js’;

where ‘…/…/Build/’ can be replaced with the path to your directory that contains Cesium, and then the worker files will be pulled out of that same directory. I think in the long run that’s what I’ll do for the all-in-one built version, assuming I can find a way for Cesium to dynamically figure out the path to itself, so it can look for the worker scripts in that same directory.

  1. I hand-edited a version of createVerticesFromExtent.js to sit right next to the combined Cesium.js. This works for me in both Chrome and FF15, with a modified version of the Skeleton that uses the combined file, and removes the requirejs code from the top:

/global importScripts/

importScripts(’./Cesium.js’);

(function () {

“use strict”;

/global self/

var ExtentTessellator = Cesium.ExtentTessellator;

var postMessage = self.webkitPostMessage || self.postMessage;

self.onmessage = function(event) {

var data = event.data;

var id = data.id;

var parameters = data.parameters;

var vertices = new Float32Array(parameters.width * parameters.height * 5);

parameters.vertices = vertices;

parameters.generateTextureCoordinates = true;

parameters.interleaveTextureCoordinates = true;

ExtentTessellator.computeVertices(parameters);

postMessage({

id : id,

result : {

vertices : vertices

}

}, [vertices.buffer]);

};

})();

Thanks Scott! It looks like the secret sauce was wrapping the code into a function and calling it that way.

(function () {

})();

This worked in chrome just fine without needing to be inside of a function. Thanks again for looking into that and sorry if my question was confusing because I wrote it in a hurry.

Hey Kevin, Scott,

I am trying to get the WebMapServiceImageryProvider.js working again in the latest imagery_layers branch. I added the two new functions that it was missing by comparing it to the ArcGisMapServerImageryProvider.js.

WebMapServiceImageryProvider.prototype.getTileDiscardPolicy = function() {

return this._tileDiscardPolicy;

};

and

WebMapServiceImageryProvider.prototype.getAvailableHostnames = function(x, y, level) {

return this._imageUrlHostnames;

};

But I am currently seeing a webgl error in the ShaderProgram.js.

[GL] Fragment shader compile log: ERROR: 0:1: ‘’ : array size must be a positive integer ERROR: 0:1: ‘’ : array size must be a positive integer ERROR: 0:2: ‘’ : array size must be a positive integer ERROR: 0:2: ‘’ : array size must be a positive integer ERROR: 0:3: ‘’ : array size must be a positive integer ERROR: 0:3: ‘’ : array size must be a positive integer ERROR: 0:4: ‘’ : array size must be a positive integer ERROR: 0:4: ‘’ : array size must be a positive integer

Are you guys seeing this too? I can’t tell what I am missing. I have attached the modified WebMapServiceImageryProvider.js.

Hey Kevin, Scott,

I am trying to get the WebMapServiceImageryProvider.js working again in the latest imagery_layers branch. I added the two new functions that it was missing by comparing it to the ArcGisMapServerImageryProvider.js.

WebMapServiceImageryProvider.prototype.getTileDiscardPolicy = function() {

return this._tileDiscardPolicy;

};

and

WebMapServiceImageryProvider.prototype.getAvailableHostnames = function(x, y, level) {

return this._imageUrlHostnames;

};

But I am currently seeing a webgl error in the ShaderProgram.js.

[GL] Fragment shader compile log: ERROR: 0:1: ‘’ : array size must be a positive integer ERROR: 0:1: ‘’ : array size must be a positive integer ERROR: 0:2: ‘’ : array size must be a positive integer ERROR: 0:2: ‘’ : array size must be a positive integer ERROR: 0:3: ‘’ : array size must be a positive integer ERROR: 0:3: ‘’ : array size must be a positive integer ERROR: 0:4: ‘’ : array size must be a positive integer ERROR: 0:4: ‘’ : array size must be a positive integer

Are you guys seeing this too? I can’t tell what I am missing. I have attached the modified WebMapServiceImageryProvider.js.

Thanks Scott! It looks like the secret sauce was wrapping the code into a function and calling it that way.

(function () {

})();

This worked in chrome just fine without needing to be inside of a function. Thanks again for looking into that and sorry if my question was confusing because I wrote it in a hurry.

OK, I tried it out and was able to get it working. I did find a few problems along the way.

  1. the version of main.js that I committed earlier to fix the problem with “window” in the worker was still not quite right, I pushed a new commit. Your fix from earlier in the thread, which I assume you are still using locally, is fine though.
  1. You’re right about the missing require.toUrl. The AMD loader that we use for the all-in-one Cesium file doesn’t have that feature, which I didn’t realize. I’ll put in a real fix eventually, but for now, using the direct URI to the worker file is fine. You could also do something like:

var uri = ‘…/…/Build/’ + processor._workerName + ‘.js’;

where ‘…/…/Build/’ can be replaced with the path to your directory that contains Cesium, and then the worker files will be pulled out of that same directory. I think in the long run that’s what I’ll do for the all-in-one built version, assuming I can find a way for Cesium to dynamically figure out the path to itself, so it can look for the worker scripts in that same directory.

  1. I hand-edited a version of createVerticesFromExtent.js to sit right next to the combined Cesium.js. This works for me in both Chrome and FF15, with a modified version of the Skeleton that uses the combined file, and removes the requirejs code from the top:

/global importScripts/

importScripts(’./Cesium.js’);

(function () {

“use strict”;

/global self/

var ExtentTessellator = Cesium.ExtentTessellator;

var postMessage = self.webkitPostMessage || self.postMessage;

self.onmessage = function(event) {

var data = event.data;

var id = data.id;

var parameters = data.parameters;

var vertices = new Float32Array(parameters.width * parameters.height * 5);

parameters.vertices = vertices;

parameters.generateTextureCoordinates = true;

parameters.interleaveTextureCoordinates = true;

ExtentTessellator.computeVertices(parameters);

postMessage({

id : id,

result : {

vertices : vertices

}

}, [vertices.buffer]);

};

})();

Scott, Kevin, I hope someone can help me with this webworkers issue I am seeing in firefox. This did not seem to be a problem in the cesium development environment, but to get the webworkers running outside of the development environment, I modified this part of TaskProcessor

var uri = require.toUrl(‘Workers/’ + processor._workerName + ‘.js’);

var worker = new Worker(uri);

to

var worker = new Worker(‘path_to_webworker’);

createVerticesFromExtent.js

Because I was getting
TypeError: require.toUrl is not a function

I also modified the workers to import the Cesium.js file instead of using require.

Now I am seeing this in firefox.

postMessage is not a function

}, [vertices.buffer]);

Have you guys come across this problem before or know anything about it?

Thanks!

WebMapServiceImageryProvider.js (7.6 KB)

Hi Jonah,

Sorry for the delay getting back to you on this.

Does your WMS layer cover the entire world? If not, do you have a base layer underneath it that does? There’s currently a bug that causes WebGL errors like that if you have a terrain tile with zero imagery tiles overlapping it. I’m still having other problems with the WMS imagery provider, though. Once I get it working I’ll commit my new .js file to the imagery_layers branch and let you know.

Kevin

Jonah,

I just committed a bunch of fixes. At this point, if you uncomment the WebMapServiceImageryProvider construction code in the skeleton, it succesfully maps some imagery hosted with a default install of GeoServer 2.1.4, as long as your install the CORS Filter so that the imagery is accessible via CORS. It works with or without a global base layer underneath. Let me know if you still see problems.

Kevin

Thanks for the update Kevin. For now, I just put a band aid on it by setting the ellipsoid tile provider when there is a wms layer. I had to reset the terrain provider by accessing a couple of private variables in the central body: _terrain and _surface. I also had to comment out this if statement in Event.js. For some reason there can only be one event listener right now I guess.

// if (index !== -1) {

// throw new DeveloperError(‘listener is already subscribed.’);

// }

Swapping out terrain providers seems to work just fine though with those modifications. Have you thought about making this a public interface method to change the tile provider? I will try out your fixes soon.