How to make a primitive 2d object ?

I followed the wiki page of "Geometry and Appearances part 2" ( to create a 3D object thanks to geometry and primitive functions. That works perfectly in 3D view but I can't display the same object in 2d and Colombus view.

I tried to use GeometryPipeline.projectTo2D to create 2D attributes but I failed. Without more documentation for GeometryPipeline, it's difficult to guess its behavior.

How can I make a primitive which will be displayed in 3D, 2D and Colombus view?

Can you share the code for the new geometry? It should work in 2D and Columbus view just as well as 3D like all the geometries that are part of Cesium.


Hello thanks for your interest. My code:

function Maquette(){
      var positions = new Float64Array(4 * 3);
      var A={x:0,y:3.5,z:0};
      var B={x:1.500,y:-1.000,z:0};
      var D={x:-1.500,y:-1.000,z:0};
      var E={x:0,y:-1.000,z:1.500};

      positions[0] = A.x;
    positions[1] = A.y;
    positions[2] = A.z;

    positions[3] = B.x;
    positions[4] = B.y;
    positions[5] = B.z;

    positions[6] = D.x;
    positions[7] = D.y;
    positions[8] = D.z;

    positions[9] = E.x;
    positions[10] = E.y;
    positions[11] = E.z;

    var indices = new Uint16Array(4 * 3);

    // back triangle AEB
    indices[0] = 0;
    indices[1] = 3;
    indices[2] = 1;

    // left triangle EAD
    indices[3] = 3;
    indices[4] = 0;
    indices[5] = 2;

    // right triangle EDB
    indices[6] = 3;
    indices[7] = 2;
    indices[8] = 1;

    // bottom triangle BAD
    indices[9] = 1;
    indices[10] = 0;
    indices[11] = 3;
        var attributes = new Cesium.GeometryAttributes({
            position : new Cesium.GeometryAttribute({
                componentDatatype : Cesium.ComponentDatatype.DOUBLE,
                componentsPerAttribute : 3,
                values : positions

        var geometryPleine = Cesium.GeometryPipeline.computeNormal(new Cesium.Geometry({
            attributes: attributes,
            indices: indices,
            primitiveType: Cesium.PrimitiveType.TRIANGLES,
            boundingSphere: Cesium.BoundingSphere.fromVertices(positions)

        return geometryPleine;

  function MonAvion(){
    this.position=new Cesium.Cartographic.fromDegrees(45, 45,10000);

    var modelMatrix = this.getModelMatrix();

    var instancePleine = new Cesium.GeometryInstance({
        geometry : Maquette(),
        attributes : {
            color : new Cesium.ColorGeometryInstanceAttribute(0,0.6,0,0.4)

    this.primitivePleine=new Cesium.Primitive({
        geometryInstances : instancePleine,
        appearance : new Cesium.PerInstanceColorAppearance({
            translucent : true




    var quatRoute=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z,this.route);
    var quatInclinaison=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Y,this.inclinaison);
    var quatPente=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_X,this.pente);

    var quaternion=Cesium.Quaternion.multiply(Cesium.Quaternion.multiply(quatRoute,quatPente),quatInclinaison);
    var myTransformMatrix=Cesium.Matrix4.fromTranslationQuaternionRotationScale(
        new Cesium.Cartesian3(0, 0, 0),
        new Cesium.Cartesian3(300, 300, 300)
    return Cesium.Matrix4.multiply(Cesium.Transforms.eastNorthUpToFixedFrame(ellipsoid.cartographicToCartesian(this.position)),myTransformMatrix);

    options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
    this.position=Cesium.defaultValue(options.position, this.position);
    this.route=Cesium.defaultValue(options.route, this.route);
    this.inclinaison=Cesium.defaultValue(options.inclinaison, this.inclinaison);
    this.pente=Cesium.defaultValue(options.pente, this.pente);

  var avion=new MonAvion();

The problem is that you are using positions near the origin which are undefined when projected to 2D. Try setting an initial model matrix when creating the geometry instance. Then when the model matrix is changed set it to

Matrix4.multiply(newModelMatrix, Matrix4.inverseTransformation(initialModelMatrix))

You should also note that an east-north-up model matrix may not be what you want in 2D and Columbus view. What you probably want is

Matrix4.fromRotationTranslation(Matrix3.IDENTITY, projectedPosition);



Hello, I use your advice to make a bigger geometry (scale 300 times) and I tried to use a new modelMatrix in 2D and Colombus modes.
But to define the new model matrix, I need to understand which referential is used in 2D and Colombus modes.
In 3D mode the referential is well known and "Cesium.Transforms.eastNorthUpToFixedFrame(ellipsoid.cartographicToCartesian(this.position)" is a good tool to create a transfer matrix.
Do you have a hint for 2D and Colombus view?
Thanks for your attention.

Should I search in UniformState? I just need to know in which coordinate system I'll project the geometry.

Did you try the model matrix from my previous post? The “newModelMatrix” , in 2D and Columbus View, should be something like:

var projectedPosition = scene.scene2D.projection.project(cartographicPosition);

projectedPosition = Cartesian3.fromElements(projectedPosition.z, projectedPosition.x, projectedPosition.y);

Matrix4.fromRotationTranslation(Matrix3.IDENTITY, projectedPosition);

The swizzle is necessary to change the position to the new coordinate system.




I tried and that don’t work.

My code:

var resultat;
var cartesianPosition=ellipsoid.cartographicToCartesian(this.position);

    var quatRoute=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z,this.route);// blue
    var quatInclinaison=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Y,this.inclinaison);//green
    var quatPente=Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_X,this.pente);//red

    var quaternion=Cesium.Quaternion.multiply(Cesium.Quaternion.multiply(quatRoute,quatPente),quatInclinaison);
    var myTransformMatrix=Cesium.Matrix4.fromTranslationQuaternionRotationScale(
        new Cesium.Cartesian3(0, 0, 0),

        new Cesium.Cartesian3(0.1,0.1, 0.1)


        var projectedPosition = scene.scene2D.projection.project(this.position);
        //projectedPosition =cartesianPosition;
        projectedPosition = Cesium.Cartesian3.fromElements(projectedPosition.z, projectedPosition.x, projectedPosition.y);

    return resultat;

I change update function in order to display a DebugModelMatrixPrimitive :

options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
this.position=Cesium.defaultValue(options.position, this.position);
this.route=Cesium.defaultValue(options.route, this.route);

    this.inclinaison=Cesium.defaultValue(options.inclinaison, this.inclinaison);
    this.pente=Cesium.defaultValue(options.pente, this.pente);

    var modelMatrix=this.getModelMatrix();


    this.primitiveDebug=new Cesium.DebugModelMatrixPrimitive({modelMatrix:modelMatrix });



The position is 45° north, 70° west, 300 meters above ground (USA).

When I try your snippet code I have the result in attached file scene2DProjection.png

When I uncomment the line //projectedPosition =cartesianPosition; I have the result in attached file cartesianPosition.png

In 2D, the coordinate system is ECEF ( ?

any idea to create a modelMatrix in 2D or Colombus views?

Hello in "Moving dome" topic (!topic/cesium-dev/ZCzBQsDALD0 ), there is a hint to update a primitive in 2D :
1) remove the selected primitive from the composite primitive of scene
2) create an instance with a model matrix (same in 3D, 2D and colombus views)
3) create a new primitive with the instance of point 2) and add it to composite primitive of scene

I think this solution is very expensive ( removing and adding in compositePrimitive) and go against the recommended use of primitives and instances.
Moreover, I think there is a issue in primitive.modelMatrix function when the scene is in 2D or colombus view.

Creating a model matrix for use with Geometry and Appearances is difficult and scene mode dependent. I plan on refactoring the Geometry and appearance code so that setting the model matrix in 3D will work across scene modes similar to the work I started in the cameraTransform branch, but, in the mean time, the last post is a good workaround.