AB4D Forum

Full Version: HeightMapVisual3D and missing points
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hi,

Hopefully someone can help me with this.

I want to display what is essentially a heightmap, but with holes where there is no data.  Is there anyway to delete bits of the mesh?

I am currently using HeightMapVisual3D, but I have to fully populate the values I give to it. If my data contains NaN (for example) it would be great to have no triangles generated.

If not, is there is a nice example of how to create a mesh, or large array of triangles, manually. Just like with HeightMapVisual3D I will need to shade based on height value.  If I need to go this route, are there any performance tips I should be looking at for large meshes (100s thousands of height values)?

Any help greatly appreciated.

cheers,

SLH
Here is the code from HeightMapMesh3D that builds the MeshGeometry3D:

Code:
           _xCount = _heightData.GetUpperBound(0) + 1; // NOTE: This is not length but max element index (so lenght is GetUpperBound() + 1)
           _yCount = _heightData.GetUpperBound(1) + 1;

           double x_step = _size.X / ((double)(_xCount - 1));
           double z_step = _size.Z / ((double)(_yCount - 1));

           Point3DCollection positions = new Point3DCollection(_xCount * _yCount);
           PointCollection textureCoordinates = new PointCollection(_xCount * _yCount);
           Int32Collection triangleIndices = new Int32Collection((_xCount - 1) * (_yCount - 1) * 6);


           double x_pos = _centerPosition.X - (_size.X / 2.0);
           double yScale = _size.Y;
           double yOffset = _centerPosition.Y; // if one value is 0, then it is positioned at the _centerPosition.Y (positive values are above center; negative values below center)

           for (int x = 0; x < _xCount; x++)
           {
               double z_pos = _centerPosition.Z - (_size.Z / 2.0);

               for (int y = 0; y < _yCount; y++)
               {
                   positions.Add(new Point3D(x_pos, _heightData[x,y] * yScale + yOffset, z_pos));
                   z_pos += z_step;
               }

               x_pos += x_step;
           }


           double xCount1 = (double)(_xCount - 1);
           double yCount1 = (double)(_yCount - 1);

           for (int x = 0; x < _xCount; x++)
           {
               double xTexture = ((double)x) / xCount1;

               for (int y = 0; y < _yCount; y++)
               {
                   textureCoordinates.Add(new Point(xTexture, (double)y / yCount1));
               }
           }

           for (int x = 0; x < _xCount - 1; x++)
           {
               for (int y = 0; y < _yCount - 1; y++)
               {
                   if ((x + y) % 2 == 1)
                   {
                       triangleIndices.Add(y + (x * _yCount));
                       triangleIndices.Add((y + 1) + x * _yCount);
                       triangleIndices.Add((y) + ((x + 1) * _yCount));
                       
                       triangleIndices.Add(y + ((x + 1) * _yCount));
                       triangleIndices.Add((y + 1) + ((x) * _yCount));
                       triangleIndices.Add((y + 1) + ((x + 1) * _yCount));
                   }
                   else
                   {
                       triangleIndices.Add(y + (x * _yCount));
                       triangleIndices.Add((y + 1) + x * _yCount);
                       triangleIndices.Add((y + 1) + ((x + 1) * _yCount));
                       
                       triangleIndices.Add(y + (x * _yCount));
                       triangleIndices.Add((y + 1) + ((x + 1) * _yCount));
                       triangleIndices.Add(y + ((x + 1) * _yCount));
                   }
               }
           }


           _geometry = new MeshGeometry3D();
           _geometry.Positions = positions;
           _geometry.TextureCoordinates = textureCoordinates;
           _geometry.TriangleIndices = triangleIndices;

As you see the last pair of for loops build the triangles (2 for each quad of the grid).

In your case you would need to update the code in those 2 for loops to check the positions that form the quad. If all 4 positions are valid, the use the existing code. If all 4 are NaN, just skip the quad. If you have 3 valid positions, then you can define only that triangle.

If you would also like to define the edge to somehow "complete" the height map when it "touches" the NaN area, you may try to do something like this:

- Update all "edge positions" y values from Nan to double.MinValue (in positions collection) (or something similar but different from NaN) - edge positions are positions that are neighbors to a valid position (when checking 4 positions inside a for loop). Then form the triangles as with the MinValue positions would be valid. You will also need to adjust checking for valid values - MinValue should be considered as NaN - so you would not expand the edge - in case you have 2 MinValues and 2 NaN you should not create any triangle. Then after the 2 for loops add another for loop that will go through all positions and set double.MinValue to a value that you would like to have as a min value - for example 0.



I cannot say if WPF 3D will be able to render your height map with sufficient performance. You should try it. If this will not work well, then just add DXEngine to the scene and the DirectX 11 rendering engine should render it smoothly as butter.
Excellent!

That worked first time and solved my problem.

Thank you very much for your clear and detailed response.