Add geometryInstance to Primitive

I am trying to draw about 30k rectangles and am getting very poor performance using entities (~10-15fps). As such, I have tried to use a Primitive with geometry instances.

The problem is, this is dynamically loaded. So, I can't create all instances at the start and add them to a primitive.

I have attempted to use the following to create the primitive:

var rectsPrimitive = new Cesium.Primitive({
            geometryInstances: ,
            appearance: new Cesium.PerInstanceColorAppearance(),
            releaseGeometryInstances: false
        });

And then this to add geometry instances:
var instance = new Cesium.GeometryInstance({
                geometry: new Cesium.RectangleGeometry({
                    rectangle: Cesium.Rectangle.fromDegrees(lng - 0.0001, lat - 0.0001,
                                                            lng + 0.0001, lat + 0.0001),
                    vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
                }),
                attributes: {
                    color: new Cesium.ColorGeometryInstanceAttribute.fromColor(color.withAlpha(0.5)),
                }
            });
            
            rectsPrimitive.geometryInstances.push(instance);

I get no errors, but nothing seems to get added on the map. If I print rectsPrimitive it seems to have the correct number of geometryInstances.

What am I missing?

Hello,

It looks like you aren’t adding the primitive to the scene. Add the following line of code:

viewer.scene.primitives.add(rectsPrimitive);

``

Best,

Hannah

Sorry, I am already adding it to the scene. I see any of the geometry instances that I added to the primitive before I added the primitive to the scene, but I can't seem to add any more instances to the same primitive.

Hmm, okay. I’m not seeing that problem. Here’s the sandcastle example I created to test it:

var viewer = new Cesium.Viewer(‘cesiumContainer’);

var rectsPrimitive = new Cesium.Primitive({

geometryInstances: ,

appearance: new Cesium.PerInstanceColorAppearance(),

releaseGeometryInstances: false

});

var lng = -100;

var lat = 40;

var d = 0.0001;

var instance = new Cesium.GeometryInstance({

geometry: new Cesium.RectangleGeometry({

rectangle: Cesium.Rectangle.fromDegrees(lng - d, lat - d,

lng + d, lat + d),

vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT

}),

attributes: {

color: new Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))

}

});

rectsPrimitive.geometryInstances.push(instance);

viewer.scene.primitives.add(rectsPrimitive);

var instance2 = new Cesium.GeometryInstance({

geometry: new Cesium.RectangleGeometry({

rectangle: Cesium.Rectangle.fromDegrees(lng + d, lat + d,

lng + 2d, lat + 2d),

vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT

}),

attributes: {

color: new Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW.withAlpha(0.5))

}

});

rectsPrimitive.geometryInstances.push(instance2);

viewer.camera.viewRectangle(Cesium.Rectangle.fromDegrees(lng - d, lat - d, lng + 2d, lat + 2d));

``

I see both rectangles added.
Can you alter that example or create a different example that replicates your issue?

Thanks,

Hannah

It seems like my reply didn't go through, or it was just emailed to you directly. This is what i said:

Thank you very much for your responses.

It seems to do it if you try to add it later (for example, via an interval or timeout).

The following sandcastle code should create a growing line of rects, but it does nothing. The console output shows that things are being correctly referenced in the interval.

var viewer = new Cesium.Viewer('cesiumContainer');

var rectsPrimitive = new Cesium.Primitive({
    geometryInstances: ,
    appearance: new Cesium.PerInstanceColorAppearance(),
    releaseGeometryInstances: false
});

var lng = -100;
var lat = 40;
var d = 0.0001;
var instance = new Cesium.GeometryInstance({
    geometry: new Cesium.RectangleGeometry({
        rectangle: Cesium.Rectangle.fromDegrees(lng - d, lat - d,
                                                            lng + d, lat + d),
        vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
    }),
    attributes: {
        color: new Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED.withAlpha(0.5))
    }
});

rectsPrimitive.geometryInstances.push(instance);

viewer.scene.primitives.add(rectsPrimitive);

var i = 2;

rectsPrimitive.geometryInstances.push(new Cesium.GeometryInstance({
        geometry: new Cesium.RectangleGeometry({
        rectangle: Cesium.Rectangle.fromDegrees(lng + (d*i), lat + d,
                                                lng + (d*(i+1)), lat + (d*2)),
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        }),
        attributes: {
            color: new Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.YELLOW.withAlpha(0.5))
        }
    }));

viewer.camera.viewRectangle(Cesium.Rectangle.fromDegrees(lng - d, lat - d, lng + 2*d, lat + 2*d));

setInterval(function(){
    console.log('interval ' + i);
    console.log(rectsPrimitive);
    rectsPrimitive.geometryInstances.push(new Cesium.GeometryInstance({
        geometry: new Cesium.RectangleGeometry({
        rectangle: Cesium.Rectangle.fromDegrees(lng + (d*i), lat + d,
                                                lng + (d*(i+1)), lat + (d*2)),
            vertexFormat: Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        }),
        attributes: {
            color: new Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREEN.withAlpha(0.5))
        }
    }));
    i ++;
}, 3000);

Adding geometry instances to a primitive after it is created has no effect. On the first render, the geometries are computed and batched (possibly on a web worker) . When it is finished, the data is passed to the GPU. That is why the releaseGeometryInstance option defaults to true. It frees all of the CPU memory containing the instance data after it is passed to the GPU. Entities are built on top of Primitives, but adding and removing geometries will cause re-computation of attributes and batching.

Going back to your original email, you mentioned “I am trying to draw about 30k rectangles and am getting very poor performance using entities (~10-15fps)”

Can you explain in more detail exactly what you are trying to do. Are these dynamic/moving rectangles or are they static? If they are static then you should see way better performance then what you claim. There shouldn’t be a reason for you to use the Primitive API for this.