private void UpdateHoleTexture() { // Hole information could be loaded from a texture. Here, we procedurally create a pattern of // holes. // The hole buffer is array with 1 where there is no hole and 0 where there is a hole. // (This is similar to an alpha mask: 1 = opaque, 0 = transparent.) int numberOfSamples = _terrainObject.TerrainNode.Terrain.Tiles.First().HeightTexture.Width; float[] holes = new float[numberOfSamples * numberOfSamples]; // Fill hole buffer with 1. for (int i = 0; i < holes.Length; i++) { holes[i] = 1; } if (_holeSize > 0) { // Add some 0 elements to create holes. int counterY = _holeSize; for (int y = 0; y < numberOfSamples - 1; y++) { int counterX = _holeSize; for (int x = 0; x < numberOfSamples - 1; x++) { holes[y * numberOfSamples + x] = 0; counterX--; if (counterX <= 0) { counterX = _holeSize; x += _holeSize * 2; } } counterY--; if (counterY <= 0) { counterY = _holeSize; y += _holeSize * 2; } } } // Copy hole buffer to a texture. TerrainHelper.CreateHoleTexture( GraphicsService.GraphicsDevice, holes, numberOfSamples, numberOfSamples, false, ref _holeTexture); foreach (var tile in _terrainObject.TerrainNode.Terrain.Tiles) { // Assign the hole texture to all terrain tiles. (Normally, each tile would have a // different hole texture or no hole texture at all.) tile.HoleTexture = _holeTexture; // We also have to add the holes to the collision detection height fields. // Get rigid body that represents this tile. var rigidBody = Simulation.RigidBodies.First(body => body.UserData == tile); var heightField = (HeightField)rigidBody.Shape; // Update the height values of the collision detection height field. float[] heights = TerrainHelper.GetTextureLevelSingle(tile.HeightTexture, 0); for (int z = 0; z < numberOfSamples; z++) { for (int x = 0; x < numberOfSamples; x++) { if ((!(holes[z * numberOfSamples + x] > 0.5f))) { // The HeightField class treats NaN as holes. heights[z * numberOfSamples + x] = float.NaN; } } } heightField.SetSamples(heights, numberOfSamples, numberOfSamples); heightField.Invalidate(); } _terrainObject.TerrainNode.Terrain.Invalidate(); }