Menu

Get height of a specific position on heightfield

Help
Daniel
2017-03-12
2017-03-12
  • Daniel

    Daniel - 2017-03-12

    Hi everyone!

    I need to get the height of a certain spot on a heightfield, can someone explain how I can do that?
    Thanks in advance!

    /Daniel

     
  • Pavel Vassiliev

    Pavel Vassiliev - 2017-03-13

    Daniel,
    See for example demos in svn branch/examples/autofleet/nightfighter
    and there in the end of Cadencer1Progress you could find
    with DummyCube1.Position do
    if Y < TerrainRenderer1.InterpolatedHeight(AsVector) then
    Y := TerrainRenderer1.InterpolatedHeight(AsVector) + FCamHeight;

    PW

     
  • Daniel

    Daniel - 2017-03-13

    Hi Pavel!
    Thank you for the answer.
    Yes, I have used Interpolated height for TerrainRenderer, but the function does not seem to exist for a heightfield.
    How can I do the same thing for a Heightfield object?

     
  • Jerome.D (BeanzMaster)

    Hi how do you generate your heightfield ?

     
  • Daniel

    Daniel - 2017-03-13

    Hi Jerome!
    I use a TGLHeightField and in a cadencer I have:

    MyHeightField.OnGetHeight := formula1;

    Then the formula is something like:

    procedure TForm1.formula1(const x, y: Single; var z: Single;
     var color: TVector4f; var texPoint: TTexPoint);
     begin
    
     z := vectornorm(x,y);
     z := some sin() equations...
    

    Similar to Pavels solution, I want an object to not fall through the HeightField.

    All the best,
    Daniel

     
  • Pavel Vassiliev

    Pavel Vassiliev - 2017-03-13

    Daniel,
    Hm, use search opt in your RAD, there are many demos for Delphi in the trunk and look also at AlitaOnHightField example in branch\games folder where

    procedure TForm1.HeightField1GetHeight(const X, Y: Single; var z: Single;
    var Color: TVector4f; var TexPoint: TTexPoint);
    var
    val: Integer;
    xi, yi: Integer;
    begin
    xi := Round(X * (Image1.Picture.Width - 1));
    // translate heightfield coordinate to Image1 pixel number
    yi := Round((1 - Y) * (Image1.Picture.Height - 1));
    val := (Image1.Picture.Bitmap.Canvas.Pixels[xi, yi]) AND $000000FF;
    // use brightness of heightmap pixel to calculate height of point x,y
    z := val * 0.05; // return the height of the landscape in z at position x,y
    end;
    Pavel

     
  • Daniel

    Daniel - 2017-03-13

    Thanks Pavel!
    It seems I don't even have to draw the image to get what I want.
    This seems to work, unless I missed something:

    v := HeightField.absoluteToLocal(HeightTester.AbsolutePosition);
    
    HeightFieldGetHeight(v[0], v[1], SingleZ, HV, tp);
    
     HeightTester.Position.Y := SingleZ * HeightField.Scale.Z;
    
     
  • Jerome.D (BeanzMaster)

    Daniel, i take a look in the TGLHeightfield class is not possible to do what you want, because Height is calculate and redering dynamically in real time. So the value are not stored. So the only way is to make lookup table (like a bitmap or a simple array like said Pavel). you can fill it in the HeightFieldGetHeight event, after you'll can retrieve the right value from the x,y pos

    eg :

    procedure TForm1.formula1(const x, y: Single; var z: Single;
    var color: TVector4f; var texPoint: TTexPoint);
    begin

    z := vectornorm(x,y);
    z := some sin() equations...
    MyArray[x,y]:=z;

    procedure GLCadencer.OnProgress
    begin
    if CurrentPosZ<MyArray[CurrentPosX, CurrentPosY] then .....

    Or something like that

    Cheers

     

    Last edit: Jerome.D (BeanzMaster) 2017-03-13
  • Daniel

    Daniel - 2017-03-15

    Thanks for the answer Jerome!
    I'll try it out!

    Cheers

     
  • Eric Hardinge

    Eric Hardinge - 2017-03-15

    Hi Daniel,
    Here is an application that I wrote to help my granson to understand 3D math.
    There are some aspects that I need to improve but not just now.
    Eric Hardinge

     
  • Eric Hardinge

    Eric Hardinge - 2017-03-15

    Here are some example files used by Plot3D

     
  • Pavel Vassiliev

    Pavel Vassiliev - 2017-03-16

    Hi, Eric
    Fine, I've tested and added your Plot2D and Plot3D in ..branches\examples\mathapps
    Pavel

     
  • Jerome.D (BeanzMaster)

    Hi, Eric, Pavel I'm tried to convert Plot3D under Lazarus but some missing maths functions. Have you
    code for : ArcCsc, ArcSec, ArcCot, Csch, SecH, CotH, ArcCsch, ArcSecH, ArcCotH.
    For ArcCot,ArcSec and ArcCsc i just negate value of the Csc, Sec and Cotangent functions from FPC Math unit, but not sure is right.

     
    • Pavel Vassiliev

      Pavel Vassiliev - 2017-03-17

      Jerome,
      Here the maths functions that not included in GLVectorGeometry unit from System.Math:

      const
      FuzzFactor = 1000;
      Infinity = 1.0 / 0.0; // not for comparison, only assignments
      ExtendedResolution = 1E-19 * FuzzFactor;

      function IsZero(const A: Extended; Epsilon: Extended): Boolean;
      begin
      if Epsilon = 0 then
      Epsilon := ExtendedResolution;
      Result := Abs(A) <= Epsilon;
      end;

      procedure FClearExcept;
      begin
      end;

      procedure FCheckExcept;
      begin
      end;

      // next only for single case
      //ArcCsc,
      function ArcCsc(const X: Single): Single;
      begin
      FClearExcept;
      if IsZero(X) then
      Result := Infinity
      else
      Result := ArcSin(1 / X);
      FCheckExcept;
      end;

      //ArcSec,
      function ArcSec(const X: Single): Single;
      begin
      FClearExcept;
      if IsZero(X) then
      Result := Infinity
      else
      Result := ArcCos(1 / X);
      FCheckExcept;
      end;

      //ArcCot
      function ArcCot(const X: Single): Single;
      begin
      FClearExcept;
      if IsZero(X) then
      Result := PI / 2
      else
      Result := ArcTan(1 / X);
      FCheckExcept;
      end;

      //Csch
      function CscH(const X: Single): Single;
      begin
      FClearExcept;
      Result := 1 / SinH(X);
      FCheckExcept;
      end;

      //SecH
      function SecH(const X: Single): Single;
      begin
      FClearExcept;
      Result := 1 / CosH(X);
      FCheckExcept;
      end;

      //CotH
      function CotH(const X: Extended): Extended;
      begin
      FClearExcept;
      Result := 1 / TanH(X);
      FCheckExcept;
      end;

      //ArcCsch,
      function ArcCscH(const X: Single): Single;
      begin
      FClearExcept;
      if IsZero(X) then
      Result := Infinity
      else
      if X < 0 then
      Result := Ln((1 - Sqrt(1 + X * X)) / X)
      else
      Result := Ln((1 + Sqrt(1 + X * X)) / X);
      FCheckExcept;
      end;

      //ArcSecH
      function ArcSecH(const X: Single): Single;
      begin
      FClearExcept;
      if IsZero(X) then
      Result := Infinity
      else if SameValue(X, 1) then
      Result := 0
      else
      Result := Ln((Sqrt(1 - X * X) + 1) / X);
      FCheckExcept;
      end;

      //ArcCotH
      function ArcCotH(const X: Single): Single;
      begin
      FClearExcept;
      if SameValue(X, 1) then
      Result := Infinity // 1.0 / 0.0
      else if SameValue(X, -1) then
      Result := NegInfinity // -1.0 / 0.0
      else
      Result := 0.5 * Ln((X + 1) / (X - 1));
      FCheckExcept;
      end;

      And it's needs to say that if we have nevertheless using System.Math unit in uses clause of GLVectorGeometry then there are many obsolete dublicated routines yet.
      PW

       
  • Pavel Vassiliev

    Pavel Vassiliev - 2017-03-17

    Eric,
    Your Plot3D math is an excellent app for z=f(x,y) on hightfiled and it may be remains only to develop the next advanced Plot4D for g=f(x,y,z) on 3D grid. But I've found that it's creating a folder C:\Plot 3D that might be not advisable for Win 10. So it's more safety to compile the project to your Plot3d\bin directory and then if necessary to write Innosetup's installler to send exe to C:Program Files.
    PW

     
  • Eric Hardinge

    Eric Hardinge - 2017-03-17

    Hi Pavel,
    That is one of the problems of old age, I turned 80 last week;
    "You cant teach old dogs new tricks"
    However I will take your advise and modify the installer etc.
    I have also wanted to develop the 4 D version but it all takes time, and I cant spend long periods of time sitting as my body becomes stiff and painful.
    I do have a parametric 2D application and a 3D parametric plotter might be good.
    Eric Hardinge

     
  • Pavel Vassiliev

    Pavel Vassiliev - 2017-03-17

    Dear Eric,
    Ok, I'm understand you so I wish you health and success.
    Pavel Vassiliev

     

    Last edit: Pavel Vassiliev 2017-03-17
  • Jerome.D (BeanzMaster)

    Hi, thanks Pavel i'll add those functions in GLVectorGeometry.Pas of the Lazarus Branch.
    And like siad Pavel, to take care of you is the most important Eric. Thanks great job a lot of little tricks in your code.

    Cheers

     
  • Jerome.D (BeanzMaster)

    Hi just found related C code to do it with Bilinear interpolation
    see (in french)
    https://jeux.developpez.com/tutoriels/theorie-des-collisions/sols-monde-3d/#LIII-D-4

    bool Collision(AABB3D box,Image Im) 
    { 
       float x = box.x + box.w/2; 
       float y = box.y + box.h/2; 
       float z = box.z + box.d; 
       int ix = (int)(x); 
       int iy = (int)(y); 
       float dx = x - ix; 
       float dy = y - iy; 
       float hauteursol = ((1-dx)*GetPixel(Image,ix,iy) + dx*GetPixel(Image,ix+1,iy)) * (1-dy) 
                         +((1-dx)*GetPixel(Image,ix,iy+1) + dx*GetPixel(Image,ix+1,iy+1)) * dy; 
       if (hauteursol>z) 
          return true; 
       else 
          return false; 
    }
    

    esaly to convert ;)

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.