City builder navigation?

I am using a TCastleWalkNavigation with gravity on because I want it to be aware of the ground. I then have it wired to the mouse wheel to change preferred height and pressing middle button to engage mouselook. It works great. But when I move (using WASD), unless I am at ground level, I don’t want it to adjust my height based on the terrain. Even if I am far above the terrain, moving over a hill moves me up and down. Only if I were to intersect that hill do I want it to move me up to keep me above the terrain.

If I turn off gravity I seem unable to control the height of the navigation using either preferredheight or height. Maybe I am missing something?

I want my navigation height to be ‘absolute’ instead of AGL (Above Ground Level) until it reaches a minimum AGL where it has to adjust based on terrain. Is there a way to easily accomplish this?

(Happy New Year!)

I accomplished what I wanted by changing the main camera’s translation directly. However that is at the expense of the smooth transition that the TCastleWalkNavigation provided.

Hi! Happy New Year – sorry for delay :slight_smile:

What you describe shall be possible using TCastleWalkNavigation with Gravity=false but CheckCollisions=true (this is default for CheckCollisions). We will then not adjust the camera position to be always at PreferredHeight above the ground, instead the PreferredHeight will be deliberately ignored, and we will only adjust the position to not collide with the mesh. The navigation Radius will control the necessary minimal distance between the camera position and any other geometry.

Let me know if it doesn’t seem to work, you can also post a testcase to reproduce the problem then.

P.S. TCastleWalkNavigation doesn’t have a property called literally Height from what I can tell. Neither does TCastleTransform nor TCastleCamera.

When I had CheckCollisions=true and Gravity=false it seemed to ignore PreferredHeight changes. So now I am adjusting the camera translation.y directly.

That is true and deliberate. That is, when Gravity is false, then PreferredHeight is ignored. (docs: Castle Game Engine: CastleCameras: Class TCastleWalkNavigation ).

The PreferredHeight means that we try to keep the given height above the ground (not more, not less – except when crouching or using head bobbing). So “honoring PreferredHeight” is synonymous with “gravity works”, at least with our current meaning of “what gravity should do in a navigation component”.

To achieve what you describe,

  1. You can set an initial camera position above the ground, at the Y you want. This is the way to control camera height in this case.

    (Optional) If you want this initial position to be at specific height above the ground, then calculate it once, using e.g.

var
  YAboveEverything: Single;
  CameraPositionAboveEverything: TVector3;
  GoodInitialCameraPosition: TVector3;
  AboveHeight: Single; 
  AboveGround: PTriangle;
const
  GoodInitialHeightAbove = 100;
begin
  YAboveEverything := Items.BoundingBox.Max.Y + 1;
  CameraPositionAboveEverything := Vector3(.., , YAboveEverything, ...);
  if MyViewport.Items.WorldHeight(CameraPositionAboveEverything, AboveHeight, AboveGround) then
  begin
    GoodInitialCameraPosition := CameraPositionAboveEverything; // copy XZ
    GoodInitialCameraPosition.Y := YAboveEverything - AboveHeight + GoodInitialHeightAbove;
  end else
  begin
    // .. CameraPositionAboveEverything wasn't above ground -- choose some sensible action
  end;
end;
  1. Moreover, you should check the current camera Translation.Y each frame (e.g. in Update) using similar code as above. If it is higher than GoodInitialCameraPosition.Y, and the distance to ground is > GoodInitialHeightAbove, then you should set camera Y back to GoodInitialCameraPosition.Y.

With these 2 mods, using TCastleWalkNavigation with CheckCollisions=true and Gravity=false should work as you need.

I’m not sure, but maybe this is already what you do :slight_smile: Since you mentioned

So now I am adjusting the camera translation.y directly.

But earlier you mentioned

I accomplished what I wanted by changing the main camera’s translation directly. However that is at the expense of the smooth transition that the TCastleWalkNavigation provided.

To be clear, my approach above means you only readjust the position of the camera. (each frame, if it’s too high; and at start, if you want). You still use and benefit from other TCastleWalkNavigation features.

1 Like