uber / h3

Hexagonal hierarchical geospatial indexing system
https://h3geo.org
Apache License 2.0
4.92k stars 468 forks source link

API for UBER H3 to (OpenGL) verteces, triangles, normals. #694

Open SkybuckFlying opened 2 years ago

SkybuckFlying commented 2 years ago

It would be helpfull if there was a UBER H3 api which would return arrays containing enough information to visualize the UBER H3 world via for example OpenGL.

One of these APIs could look like:

H3Error getTriangularWorld( int Resolution, VectorStruct VectorArray, Triangle TriangleArray, Vector *NormalArray );

The purposes of this API would be to connect (lines) triangles between all hexagon centers. The initial idea was to connect lines, but lines don't visualize well in OpenGL, no backface culling for lines. So a better idea is to visualize the lines by drawing triangles instead, computing normals for triangles is possible and by setting them when the 3 vectors are added to OpenGL for the triangle, OpenGL will know how to backface cull these triangles, which is handy to not show the back of the earth/world.

Where VectorArray is a dynamic array of VectorStruct { float x,y,z; };

Where TriangleArray is a dynamic array of TriangleStruct { int64 vi1, vi2, vi3; // vector index. }

Where NormalArray is a dynamic array of VectorStruct

VectorArray should be filled with all coordinates of the centers of all hexagons at the specified resolution.

TriangleArray should be filled with all indices of the triangles which describe the hexagon. The order of the indices should be such that when computing the plane normal (using formula below) it's pointing outwards.

NormalVector := CalcPlaneNormal ( VectorArray[ TriangleArray[ Index ].vi1 ], VectorArray[ TriangleArray[ Index ].vi2 ], VectorArray[ TriangleArray[ Index ].vi3 ]
);

TAffineVector = VectorStruct;

function CalcPlaneNormal(const p1, p2, p3: TAffineVector): TAffineVector; var V1, V2: TAffineVector; begin VectorSubtract(p2, p1, V1); VectorSubtract(p3, p1, V2); VectorCrossProduct(V1, V2, result); NormalizeVector(result); end;

procedure VectorSubtract(const V1, V2: TAffineVector; var result: TAffineVector); begin result.X := V1.X - V2.X; result.Y := V1.Y - V2.Y; result.Z := V1.Z - V2.Z; end;

procedure VectorCrossProduct(const V1, V2: TAffineVector; var vr: TAffineVector); overload; begin vr.V[X] := V1.V[Y] V2.V[Z] - V1.V[Z] V2.V[Y]; vr.V[Y] := V1.V[Z] V2.V[X] - V1.V[X] V2.V[Z]; vr.V[Z] := V1.V[X] V2.V[Y] - V1.V[Y] V2.V[X]; end;

procedure NormalizeVector(var V: TAffineVector); var invLen: Single; vn: Single; begin vn := VectorNorm(V); if vn > 0 then begin invLen := RSqrt(vn); V.X := V.X invLen; V.Y := V.Y invLen; V.Z := V.Z * invLen; end; end;

function VectorNorm(const V: TAffineVector): Single; begin result := V.X V.X + V.Y V.Y + V.Z * V.Z; end;

function RSqrt(V: Single): Single; begin result := 1 / Sqrt(V); end;

SkybuckFlying commented 2 years ago

For now I am mostly interested in winding order of the triangles, any triangle, be it from hexagon itself or from connecting centers.

Normals do not seem to play a roll in winding order and back face culling. However maybe normals could also be used to darken verteces or lines that face away from camera/eye, etc.