3D Compass

Never become disoriented again by using a 3D compass! Your typical 1D compass only shows the north vector while a 3D compass shows the East, North, and Up vectors!

BTW this is using DebugModelMatrixPrimitive which I saw on the Camera SandCastle app. Anyone know of a built-in 3D arrow? I wish to use arrows to point to the Moon and Sun putting the base of those rays/arrows on the base of the 3DCompass. Then at a glance you can know their altitude and azimuth.

nice! I wonder if we could take the math and logic behind it and translate it to a pretty compass that will behave well in all views? 2d, 3d, columbus…etc. I’ve been playing with the compass in the Bhuvan app:


But it’s not behaving well for me across all views and camera tilts :confused:

  • V

The compass on that site seems to be working fine, in which situations does it not behave?

The math/logic behind the 3D compass is actually very simple. First obtain the ENU matrix at the camera position. Then offset the position portion of the matrix some distance in front of the camera. Then set the modelMatrix property of the model to that resulting matrix. The model used is built into Cesium, the same one used on the camera Sandcastle app. A nice looking model designed just for this purpose would be great. One where it’s obvious if the arrows coming out of the compass are pointing toward or away from you. Also one that works well for those whom are color blind as north and east are green and red on that model.

In the video the compass was 1km in front of the camera with a 1km width. I’ve since changed it to 2 meters in front of the camera with 0.2 meters width. I also now scale the compass width with the camera’s FOV so it keeps the same apparent size.

While the middle of the screen works fine, I tried moving it toward the edge of the screen to be out of the way. However due to perspective when you face the same direction as a compass hand you can still see the compass hand, unlike when the compass is in the middle of the screen. But of course the same phenomenon occurs when using a real life compass in real life, I mean how many hold a compass up in their air so the north hand is co-linear with their eye’s forward vector like they are aiming with a rifle scope.

What I could do to counteract this is if I move the compass down the screen rotate it (pitch it down) so when I look due north I can no longer see the north hand of the compass. However this might confuse people whom expect the perspective phenomenon like they do with a real life compass. Another idea would be to draw it orthogonal, but draw everything else with perspective, but that might look weird.

Sorry I forgot you referred to other projections. Well the ENU frame in CV and 2D is the same for everywhere: East is (1,0,0) North is (0,1,0) Up is (0,0,1).

Yes, that’s what I’m trying to work with. My application requires odd tilts and maneuvering:


And when I put the compass into my application and test it…it doesn’t respond well to camera tilts. I probably just need to adjust some things.

  • V

Is the compass a 2D widget, or 3D like a primitive or entity? Are you calculating heading first then adjusting the compass from that?

I changed the 3D Compass to 3 independent cylinder primitives (morphed into cones), so if you only want 1 or 2 you can easily turn off the others. I also added Sun and Moon arrows, so even if they are below the horizon the arrows will let you know where they are.

What I’d like to be able to do is color the bottom circle face of a cylinder a different color than its sides. I can then shift each arrow back a bit exposing it’s base. Then you could then easily determine if the arrow is facing toward you or away from you. Is this already possible? If not, any chance of this feature being added?

Video with Moon and Sun arrows

I was working off the code from this fork:


  • V

I’ve searched for things like heading and compass from that fork with no results.That fork hasn’t been updated in 2 years though.

Are the heading values wrong, or is the graphic orientation not matching the heading value? Getting heading is very simple to obtain regardless of the camera orientation. Once you convert the camera.direction to the local ENU transform you can find heading with


For vertical orientations you could substitute camera.direction with camera.up (this makes sense if roll is always zero.)

BTW the HPR text on my Moon Sun video is wrong, I was testing some other functions at the time. However the arrow directions are correct.

One cool thing about the Moon Sun arrows is that at a glance you know what type of Moon:

-face in opposite directions = Full Moon

-face in the same direction = New Moon

-face 90deg from eachother = Half Moon

Full Moon always rises soon after the Sun sets. There is never a night time with a New Moon. At a glance you can obtain a lot of information. I plan to add labels to the end of the Moon Sun arrows with exact altitude/azimuth info.

If you right click on the compass at http://bhuvan.nrsc.gov.in/globe/3d.php then inspect element then expand till you find this within an svg tag:


It shows rotate going through 0 to 360. Math.atan2 will split 0 to 180 CW and 0 to -180 CCW. I’m not sure if SVG accepts negative values but to convert you can do: if(heading<0){heading = 360-heading;}

I mean if(heading<0){heading = 360+heading;}

Hyper, you could also you a gltf file for each axis, which would then allow users to easily change the graphics of the compass. Not to sound like a broken record, but this is yet another feature that I’m not people would be interested in if you want to make a plug-in or commit your code back to Cesium. Ultimately I could see it turning into a standard Viewer widget that could be turned on/off easily.

Oh ya, that would be very beneficial. At the moment it’s difficult to see exactly what direction the arrows are facing. You can’t notice it with these symmetric arrow models, but I do set up their modelMatrix a certain way so that they have zero roll. If I had fancy arrow models you could glean more information from them knowing that they have zero roll and how they look from your perspective. If anyone knows of any good arrow models please let me know, particularly ones that look different geometrically from different angles and have different colors on the various sides. Currently it’s part of my 3Dmouse plugin, but it can easily be separated into its own plugin.

Granted it’s obtrusive in the middle of the screen, but one advantage is that you know the camera direction matches an arrow direction when you can no longer see the sides of the arrow. I make use of this when flying back to Earth after flying to the Sun: I make sure the blue arrow faces directly toward me. On my Feb 26 post I did write about a way to retain this even if the compass is off to the edge of the screen.

I would think a polished implementation would be small and in the corner of the screen, maybe enlarging if you mouse of it. Of course for the average user, there’s always a chance that a simple 2D compass would actually be more beneficial from a usability standpoint.

I agree that a smaller version at the edge would be best. With good arrow models even a small size would be sufficient. It wouldn’t even have to consist of arrows, as long as it was obvious which part of the model points north,east, and up from any HPR angle combination. Perhaps some would have an airplane model as the compass model!

A good 2D alternative might be a combination of the standard north-east compass plane along side a 2D pitch indicator (simply a ray that points up at pitch 90, point sideways at pitch 0, points down at pitch -90, as well as everything in between.) Well assuming the user want’s to know the camera pitch. There could be a 2D ray for roll indication as well similar to the NE compass. Instead of the 2 rays I suppose one could use an airplane attitude indicator for pitch&roll I suppose, but those don’t work well with high pitch values.

Perhaps all this fancy stuff could be off by default, but chosen with a pull down menu like the one used to select an imagery source.

I made a video demonstrating the concept of ‘perspective correction’.

The top and bottom compass positions are both 20deg pitched away from the center compass. The rotation matrix of the top compass is identical to the compass in the middle. The bottom compass rotation matrix is rotated down 20deg pitch relative to the middle compass rotation matrix.

-The top and middle compasses actually point in the same direction but ‘appear’ to point to different directions. (similar to a compass in real life that isn’t located on your eye’s forward vector)

-The bottom and middle compasses appear to point in the same direction while in fact they are rotated 20 degrees from eachother. (the bottom is ‘perspective corrected’)

I plan to let the user put the compass anywhere on the screen, and also give them the option to use perspective correction or not depending on their preference.