javascript3dcesiumjs

Cone rotation around apex with Cesium.js


I am trying to rotate a cone from its apex, rather than its centre, so that the apex remains in the same position.

I've found the example below from the following link: https://groups.google.com/forum/#!topic/cesium-dev/f9ZiSWPMgus

But it only shows how to rotate the cone by 90 degrees, if you choose a different value for roll, like 45 or 30 degrees, it gets skewed, and the apex ends up in the wrong place.

I know its something to do with the offset, but can't make any progress from there. Is there some way to calculate the correct offset for any value of roll?

I'd also like to extend the length of the cone when its rotated, so that when its rotated 30 degrees for example, the bottom of the cone will still reach the ground in that direction, while the apex still remains in its original place, I don't know how feasible that is though.

Here's a glitch of the code sample below: https://glitch.com/edit/#!/cesium-cone-rotation

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

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

//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: 45,
        length: 180,
        material: Cesium.Color.YELLOW.withAlpha(0.5)
    }
}));

var heading = Cesium.Math.toRadians(0.0);
var pitch = Cesium.Math.toRadians(0.0);
var roll = Cesium.Math.toRadians(90.0);
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);

//Create a rotation
var orientation = Cesium.Transforms.headingPitchRollQuaternion(position, hpr);

// offset the rotation so it's rotating from the apex of the cone, instead of the centre
var offset = new Cesium.Cartesian3(0, 90, 90);

//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: 45,
        length: 180,
        material: Cesium.Color.YELLOW.withAlpha(0.5)
    }
}));

viewer.zoomTo(viewer.entities);

Solution

  • A little late to the party but I made a sandcastle with an example of rotating a cone around its apex. I also put it into a function to allow quick and easy replication. The purple cone represents the cone in its initial transform.

    Hopefully this helps someone.

    https://sandcastle.cesium.com/#c=hVbbcts2EP2VHb2YahhSrtPLyLKnruxMZpr04jh90gtErkSMQYADgJYdR//eBUFSIC2nHFsSwLO7B+csCGZKGgsPHHeo4QIk7mCJhtdl8m8zF51kzXCppGVcoj6Znq/kSm5qmVmuJFg0NnoWzHJb50gpzt7FIJTcduO3p6e/xFAg3xaWhjP6HUMVg44hU0LV+qItuKSRTm5vrpMdt8WVqAoWzZKfppQO5dYWF6ez2X4Kz648QJrCNW6IEVTK8IaK2oAtEEymER2GIFmzvAG7ZHbu7tw8srIS2N/zOVv8iP44pLsdxvQLJJYN+oOf4BJKtKiNp+3BPeWLTu0l06QkZ/Is2WhVXuOWFmGivlTcE+209D6EQhTIci63pC63GYnMZA5aCQEbpRtlqDgeSLTwA4dPzBaJVbc0zaSJCvj2DWauTE/b5X0VX73AN8Vfg+seHlCqRk34wXP82xW+pWzReI2uRFhywx8xf69ZiXeaqtDKS3OgcJhLkBn7p9K2+FLdqfd9VNRZE8h7VVXiCRhYF+1scG2voFQP2Mha8QflPOXSunk3JZnWagdIDrRdOdQ+TBUKpPnju6YB7g6AKNDj0CYRbST6e+v3RvrjdNp03SdHyhPK1U4Ccx3UEzgxwB65GQjuq45Z+DZ8KX+lhwbbhuLxHH4lty0mXFFfNlB5qcq162LHtcvbtHCg1aFy5tH5a5XLWlhOtkVDinGYLQ47rQ2Mpn59r6U71l/xiM14POzxIaGzYb+3k9FRElu03f1xwVHS0COlOUo7arV/akbPJElzA498eHQkW2sSUaCG3hi0QYFm/NICwoaejykf7+pp2BEaiSVtvOHecSOq5s+shNZG+xVNwvI8enYod3W7eN6yi9O0m4o7TCDMPBz0gOxJcJmjnkOf111+x8XBM360xbvLqso97GozdzvVbU52jwa4DZbUXWtlLfnQws883g/D9LBmZhBXOh85E/P2MO3J75tfe98J7l+jrbVsC6/kfiW9nLIu183Z/yud6nRQRILM5O6kPqevRXuffr950x6+/siviObPM0i7BD8A3099sSZ7l19j/rkqUH/XM0kbag6ryS3mYDzavQTAWrDsHlRtyQlcTZo1Hbz9/tnpXzzc68hs2gSiELwyiue9oZoE5vNXWvF0lpANh89pq+1B8v97cfH4lv2cHj01DueayFGe3z9eLf/w5tHn3u+HtvNJQi++N/tF5JebEQXnSCv6V0WniopGFrj0aTqEZBQ0iScLY58EXnYN9RsvKzovodYiSpLUIr0LkRImXdfZPdokM8Y3G8AiDUMXOX8Anl+sJqNXydUEMsGMoTubWojP/CtZfLlICf8iVKjmJPrrAbVgTw5WnF5+9JNJkixSGh6PtEqJNdNBZo/4Dw