Entity rotation origin

Hi all,

I'm trying to use the entity api to draw a rotated cone. I am specifying a position and then an orientation that specifies a 90 degree roll to rotate the cone on its side. The problem I'm having is that I'm trying to rotate the cone from its apex, instead of from its center. That is, I want the apex to appear at the position and then to rotate about this point. No matter what I seem to do, I cannot seem to get the entity to rotate in this manner. What am I missing?

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

var position = Cesium.Cartesian3.fromDegrees(-75, 40);
    
var orientation = Cesium.Transforms.headingPitchRollQuaternion(
    position,
    Cesium.Math.toRadians(0.0),
    Cesium.Math.toRadians(0.0),
    Cesium.Math.toRadians(90.0)
    );

var entity = viewer.entities.add(new Cesium.Entity({
    position: position,
    orientation: orientation,
    point: {
        color: Cesium.Color.YELLOW,
        show: true,
        pixelSize: 20
    },
    cylinder: {
        topRadius: 0,
        bottomRadius: 5,
        length: 20,
        material: Cesium.Color.YELLOW.withAlpha(0.5)
    }
}));
                                 
viewer.zoomTo(viewer.entities);

Position and rotation is always about the center, so you need to generate the rotation and then offset the position to account for it. Below is a complete example that does what you want (just paste it into Sandcastle). Since moving an object around like this is probably something people want to do often, I’ll make a note to make it easier to do.

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

var position = Cesium.Cartesian3.fromDegrees(-75, 40);

//Original, non-rotated cone for comparison.

viewer.entities.add(new Cesium.Entity({

position: position,

point: {

color: Cesium.Color.YELLOW,

show: true,

pixelSize: 20

},

cylinder: {

topRadius: 0,

bottomRadius: 5,

length: 20,

material: Cesium.Color.YELLOW.withAlpha(0.5)

}

}));

//Create a rotation

var orientation = Cesium.Transforms.headingPitchRollQuaternion(

position,

Cesium.Math.toRadians(0.0),

Cesium.Math.toRadians(0.0),

Cesium.Math.toRadians(90.0));

//Since the rotate is in the center, we need to offset it

//by the length in the north direction.

var offset = new Cesium.Cartesian3(0, 10, 0);

//Create a transform for the offset.

var enuTransform = Cesium.Transforms.eastNorthUpToFixedFrame(position);

//Transform the offset

Cesium.Matrix4.multiplyByPointAsVector(enuTransform, offset, offset);

//Add the offset to the original position to get the final value.

Cesium.Cartesian3.add(position, offset, position);

viewer.entities.add(new Cesium.Entity({

position: position,

orientation: orientation,

point: {

color: Cesium.Color.YELLOW,

show: true,

pixelSize: 20

},

cylinder: {

topRadius: 0,

bottomRadius: 5,

length: 20,

material: Cesium.Color.YELLOW.withAlpha(0.5)

}

}));

viewer.zoomTo(viewer.entities);

With some slight modifications to Matthew’s example it can be easier to see

line3

var position = Cesium.Cartesian3.fromDegrees(-75, 40,10); //add some altitude so it’s not buried

line30

var offset = new Cesium.Cartesian3(0, 10, 10); //add z offset to make it look like it was rotated around the apex

Even though you can only rotate around center, with offset you can make it look like it was rotated around any point you like. Same with rotations in 2D.

Thanks guys. I actually ended up finding the sensors plugin that did exactly what I wanted, but this is good to know as well. I think it will be likely that I'll need to rotate from a particular origin at some point though, so I'll keep this in mind.

Matt, a simpler way to handle this would be a welcome addition.

Thanks again for your help!

With primitives you can manipulate its position and orientation by simply altering its modelMatrix property. With entities you can manipulate its Cartesian3 position by altering its position property and its Quanternion orientation by altering its orientation property. However, one might already have orientation in the form of 3 orthogonal vectors which is the form that modelMatrix uses. Does one have to convert to Quanternion orientation form for entities? Also, is entity orientation always in terms of the ENU frame of the entity position?

Entity orientation is always in respect to Earth fixed (ECF), if you don’t specify an orientation, it default to ENU at the entity position (so that volumes and shapes have a decent default orientation).

The lack of a modelMatrix is intentional for a number of reasons (ease of use and time-dynamic position/orientation are the two that immediately come to mind). It’s true that losing the model matrix means you can’t apply a certain transformations like you can with a primitive, our goal is to have parity between functionality when it’s needed. So if you have a good use case for something that the Entity API can’t do, just let us know.

Ah, if you init with a specified orientation the orientation is constant in the Earth Fixed Frame. If you don’t then the orientation aligns with the local ENU frame as you drag it around.

I would imagine that the position/orientation combos are converted to a matrix form upon rendering anyways, so I thought it might be trivial to implement a modelMatrix option where one could either declare orientation or a rotation matrix (though I suppose you can also scale with a rotation matrix.) Akin to the relationship between Cartesian and Cartographic: Ultimately at some point Cartographic is going to be converted to Cartesian for processing. Also akin to Degrees and Radians: Ultimately at some point Degrees is converted to Radians for processing.

When I originally asked I was trying to use entities for the 3D compass, but then I settled with primitives since I can alter their modelMatrix. It’s trivial to obtain a rotation matrix for things like the Camera to Sun arrow, but it would take an extra step to convert this to HPR for entities, which I assume is converted to matrix form later on for processing.

How did you achieve this in sensor plugin? Can you share piece of code. Thanks

Hi Matthew,

do you know how to make this work with it other hpr ?

For example:

var orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
Cesium.Math.toRadians(0.0),
Cesium.Math.toRadians(0.0),
Cesium.Math.toRadians(120.0)
);

What offset would I use if I wanted to rotated 30 degrees around the apex for example, or 45 degrees?