-2

I've written my own 3D Game Engine in the past few years and wanted to actually use it for a game.

I stumbled accros the following problem:

I have multiple planes in my game but lets talk about one single plane. Naturally, planes are not able to dive into the ground and fly under the terrain. Therefor, I need to implement something that detects the collision between a plane/jet and my ground.

The informations given are the following:

  1. Grid of terrain [2- dimensional array; stores height at according x,z coordinate]
  2. Hitbox of my plane (it moves with my plane, so the bounds etc. are all already calculated and given)

So about the hitboxes: I though about which method to use. The best one in terms of performance seems to be simple spheres with different radius.

About the ground: Graphically, the ground is subdivided into triangles: enter image description here

So what I need now is the optimal type of hitbox (sphere, AABB,...) and the according most efficient calculations.

My attempt was to get every surrounding triangle and calculate the distance from that one to each center of my hitbox spheres. If the distance is less than the radius, it has successfully detected a collision. But when I have up to 10/20 spheres in my plane and like 100 triangles to check, it will take to much time.

Another attempt was to get the vertical distance to the ground from each hitbox sphere. This one needs way less calculations but fails when getting near steep surfaces.

I would be very happy if someone could help me implementing an efficient version of plane/terrain collision detection :)

genpfault
  • 51,148
  • 11
  • 85
  • 139
Luecx
  • 160
  • 1
  • 12
  • for rendered planes you can do this in shader. I assume terrain is rendered before objects so once you are attempting to render plane fragment below surface (test the pre stored depth texture from previous pass) you know a collision occur so you can output plane ID to some 1D texture output or whatever. This way is pixel perfect and can even provide location of the hit. – Spektre Sep 15 '17 at 07:57
  • Well to increase the speed of my shaders I calculated the height of each vertex beforehand. So there is no "depth texture". I might also change the vertex positions after reading it from my height map. – Luecx Sep 15 '17 at 08:33
  • Wait. Nvm, you were talking about the depth texture. How do I read that one? – Luecx Sep 15 '17 at 09:54
  • @Luecx I rewriten my comment into answer so it is more clear – Spektre Sep 16 '17 at 07:44

1 Answers1

0
  1. render terrain

    May be you could try liner depth buffer to improve accuracy.

  2. read depth texture

    you can use glReadPixels with GL_DEPTH_COMPONENT and GL_FLOAT. That will copy depth buffer into CPU side memory. So now you can do also collision on CPU side or any computation related to ground in view...

  3. use the depth buffer as texture

    so copy it back GPU with glTexImage2D. I know this is slow (but most likely much faster then your current computation of collision. In case you are not using Intel HD Graphics You can instead #2,#3 use FBO for depth which will render depth buffer directly to texture. But on Intel this does not work reliably (or at all).

  4. now render your objects (off screen) with GLSL

    inside fragment shader just compare rendered position with depth (attached as texture). If bellow output the collision somewhere. If done in compute shaders than you can store results in some texture. Or you could use some attachment or FBO for this.

    In case you can not use FBO you could render to "screen" with specifically color encoded collisions. Then read it with glReadPixels and scan for it to handle what ever collision logic you have on CPU side...

    Do not write to Depth buffer in this pass !!! And also do not use CULL_FACE because that could miss some collision of the back side of your object.

  5. now render the objects normally

    in case you do not render in #4 or you encode collision to screen buffer you need to overwrite/render the stuff. Otherwise this step is not needed. But rendering after collision detection is good because in case of collision you most likely change the object position/orientation/mesh and already rendered object could be hindering the altered one.

[Notes]

Copying image between CPU and GPU is slow so use FBO and render to texture if you can instead.

If you are not familiar with multiple pass rendering see some QAs for inspiration:

This works only in view ... but you can do just collision rendering pass (per object). Render with camera set to view from top to down (birdseye) and covering only area around your object... Also you do not need too big resolution for this so it should be relatively fast ... So you can divide your screen to square areas (using glViewport) testing more objects in single frame to lover the sync time slowdowns as much as possible (use less glReadPixel calls). Also you do not need any vertex colors or textures for this.

Spektre
  • 49,595
  • 11
  • 110
  • 380