浏览代码

Merge pull request #5095 from postman-nz/master

Added optional alphaFilter parameter to CreateGroundFromHeightMap
David Catuhe 7 年之前
父节点
当前提交
a32f384d14
共有 4 个文件被更改,包括 52 次插入19 次删除
  1. 1 0
      dist/preview release/what's new.md
  2. 11 8
      src/Mesh/babylon.mesh.ts
  3. 35 9
      src/Mesh/babylon.mesh.vertexData.ts
  4. 5 2
      src/Mesh/babylon.meshBuilder.ts

+ 1 - 0
dist/preview release/what's new.md

@@ -126,6 +126,7 @@
 - Improved performance of cached nodes but ensuring parent always updates cache. This removes failed isSynchronized test that meant computeWorldMatrix would always have to rebuild. On large scenes this could double framerate. ([Bolloxim](https://github.com/Bolloxim))
 - Added FXAA and MSAA support to the StandardRenderingPipeline ([julien-moreau](https://github.com/julien-moreau))
 - Make teleportCamera public in VR experience helper ([TrevorDev](https://github.com/TrevorDev))
+- Added optional alphaFilter parameter to ```CreateGroundFromHeightMap``` to allow for heightmaps to be created that ignore any transparent data ([Postman-nz](https://github.com/Postman-nz))
 
 
 ### glTF Loader

+ 11 - 8
src/Mesh/babylon.mesh.ts

@@ -3130,12 +3130,14 @@
          * Creates a ground mesh from a height map.    
          * tuto : http://doc.babylonjs.com/babylon101/height_map   
          * Please consider using the same method from the MeshBuilder class instead.    
-         * The parameter `url` sets the URL of the height map image resource.  
-         * The parameters `width` and `height` (positive floats, default 10) set the ground width and height sizes.     
-         * The parameter `subdivisions` (positive integer, default 1) sets the number of subdivision per side.  
-         * The parameter `minHeight` (float, default 0) is the minimum altitude on the ground.     
-         * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.   
-         * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * @param url sets the URL of the height map image resource.  
+         * @param width (positive float, default 10) set the ground width size.  
+         * @param height (positive float, default 10) set the ground height size.  
+         * @param subdivisions (positive integer, default 1) sets the number of subdivision per side.  
+         * @param minHeight (float, default 0) is the minimum altitude on the ground.     
+         * @param maxHeight (float, default 1) is the maximum altitude on the ground.   
+         * @param onReady is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * @param alphaFilter will filter any data where the alpha channel is below this value, defaults 0 (all data visible).
          * This function is passed the newly built mesh : 
          * ```javascript
          * function(mesh) { // do things
@@ -3143,7 +3145,7 @@
          * ```
          * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          */
-        public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void): GroundMesh {
+        public static CreateGroundFromHeightMap(name: string, url: string, width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, scene: Scene, updatable?: boolean, onReady?: (mesh: GroundMesh) => void, alphaFilter?: number): GroundMesh {
             var options = {
                 width: width,
                 height: height,
@@ -3151,7 +3153,8 @@
                 minHeight: minHeight,
                 maxHeight: maxHeight,
                 updatable: updatable,
-                onReady: onReady
+                onReady: onReady,
+                alphaFilter: alphaFilter
             };
 
             return MeshBuilder.CreateGroundFromHeightMap(name, url, options, scene);

+ 35 - 9
src/Mesh/babylon.mesh.vertexData.ts

@@ -1739,15 +1739,17 @@
           * * buffer the array holding the image color data 
           * * bufferWidth the width of image
           * * bufferHeight the height of image
+          * * alphaFilter Remove any data where the alpha channel is below this value, defaults 0 (all data visible)
          * @returns the VertexData of the Ground designed from a heightmap   
          */
-        public static CreateGroundFromHeightMap(options: { width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, colorFilter: Color3, buffer: Uint8Array, bufferWidth: number, bufferHeight: number }): VertexData {
+        public static CreateGroundFromHeightMap(options: { width: number, height: number, subdivisions: number, minHeight: number, maxHeight: number, colorFilter: Color3, buffer: Uint8Array, bufferWidth: number, bufferHeight: number, alphaFilter: number }): VertexData {
             var indices = [];
             var positions = [];
             var normals = [];
             var uvs = [];
             var row, col;
             var filter = options.colorFilter || new Color3(0.3, 0.59, 0.11);
+            var alphaFilter = options.alphaFilter || 0.0;
 
             // Vertices
             for (row = 0; row <= options.subdivisions; row++) {
@@ -1762,10 +1764,17 @@
                     var r = options.buffer[pos] / 255.0;
                     var g = options.buffer[pos + 1] / 255.0;
                     var b = options.buffer[pos + 2] / 255.0;
+                    var a = options.buffer[pos + 3] / 255.0;
 
                     var gradient = r * filter.r + g * filter.g + b * filter.b;
-
-                    position.y = options.minHeight + (options.maxHeight - options.minHeight) * gradient;
+                    
+                    // If our alpha channel is not within our filter then we will assign a 'special' height 
+                    // Then when building the indices, we will ignore any vertex that is using the special height
+                    if(a >= alphaFilter)
+                        position.y = options.minHeight + (options.maxHeight - options.minHeight) * gradient;
+                    else {
+                        position.y = options.minHeight - BABYLON.Epsilon; // We can't have a height below minHeight, normally.
+                    }
 
                     // Add  vertex
                     positions.push(position.x, position.y, position.z);
@@ -1777,13 +1786,30 @@
             // Indices
             for (row = 0; row < options.subdivisions; row++) {
                 for (col = 0; col < options.subdivisions; col++) {
-                    indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + 1 + row * (options.subdivisions + 1));
-                    indices.push(col + row * (options.subdivisions + 1));
+                    // Calculate Indices
+                    var idx1 = (col + 1 + (row + 1) * (options.subdivisions + 1));
+                    var idx2 = (col + 1 + row * (options.subdivisions + 1));
+                    var idx3 = (col + row * (options.subdivisions + 1));
+                    var idx4 = (col + (row + 1) * (options.subdivisions + 1));
+
+                    // Check that all indices are visible (based on our special height)
+                    // Only display the vertex if all Indices are visible
+                    // Positions are stored x,y,z for each vertex, hence the * 3 and + 1 for height
+                    var isVisibleIdx1 = positions[idx1 * 3 + 1] >= options.minHeight;
+                    var isVisibleIdx2 = positions[idx2 * 3 + 1] >= options.minHeight;
+                    var isVisibleIdx3 = positions[idx3 * 3 + 1] >= options.minHeight;
+                    if (isVisibleIdx1 && isVisibleIdx2 && isVisibleIdx3) {
+                        indices.push(idx1);
+                        indices.push(idx2);
+                        indices.push(idx3);
+                    }
 
-                    indices.push(col + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + 1 + (row + 1) * (options.subdivisions + 1));
-                    indices.push(col + row * (options.subdivisions + 1));
+                    var isVisibleIdx4 = positions[idx4 * 3 + 1] >= options.minHeight;
+                    if (isVisibleIdx4 && isVisibleIdx1 && isVisibleIdx3) {
+                        indices.push(idx4);
+                        indices.push(idx1);
+                        indices.push(idx3);
+                    }
                 }
             }
 

+ 5 - 2
src/Mesh/babylon.meshBuilder.ts

@@ -776,6 +776,7 @@
          * * The parameter `maxHeight` (float, default 1) is the maximum altitude on the ground.   
          * * The parameter `colorFilter` (optional Color3, default (0.3, 0.59, 0.11) ) is the filter to apply to the image pixel colors to compute the height.  
          * * The parameter `onReady` is a javascript callback function that will be called  once the mesh is just built (the height map download can last some time).  
+         * * The parameter `alphaFilter` will filter any data where the alpha channel is below this value, defaults 0 (all data visible)
          * * The mesh can be set to updatable with the boolean parameter `updatable` (default false) if its internal geometry is supposed to change once created.  
          * @param name defines the name of the mesh
          * @param url defines the url to the height map
@@ -785,13 +786,14 @@
          * @see http://doc.babylonjs.com/babylon101/height_map   
          * @see http://doc.babylonjs.com/tutorials/Mesh_CreateXXX_Methods_With_Options_Parameter#ground-from-a-height-map
          */
-        public static CreateGroundFromHeightMap(name: string, url: string, options: { width?: number, height?: number, subdivisions?: number, minHeight?: number, maxHeight?: number, colorFilter?: Color3, updatable?: boolean, onReady?: (mesh: GroundMesh) => void }, scene: Scene): GroundMesh {
+        public static CreateGroundFromHeightMap(name: string, url: string, options: { width?: number, height?: number, subdivisions?: number, minHeight?: number, maxHeight?: number, colorFilter?: Color3, alphaFilter?: number, updatable?: boolean, onReady?: (mesh: GroundMesh) => void }, scene: Scene): GroundMesh {
             var width = options.width || 10.0;
             var height = options.height || 10.0;
             var subdivisions = options.subdivisions || 1 | 0;
             var minHeight = options.minHeight || 0.0;
             var maxHeight = options.maxHeight || 1.0;
             var filter = options.colorFilter || new Color3(0.3, 0.59, 0.11);
+            var alphaFilter = options.alphaFilter || 0.0;
             var updatable = options.updatable;
             var onReady = options.onReady;
 
@@ -834,7 +836,8 @@
                     width: width, height: height,
                     subdivisions: subdivisions,
                     minHeight: minHeight, maxHeight: maxHeight, colorFilter: filter,
-                    buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight
+                    buffer: buffer, bufferWidth: bufferWidth, bufferHeight: bufferHeight, 
+                    alphaFilter: alphaFilter
                 });
 
                 vertexData.applyToMesh(ground, updatable);