heightmap.js 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. this.getHeight = function( x, y ) {
  2. // Finding the nearest point in the heightmap works for our current applications,
  3. // so that is what we do currently. Below is a commented-out version that does tri-linear
  4. // interpolation between the nearest four points to find the height
  5. // Convert world (x,y) into fractional array indices
  6. var minWorldX = this.minWorldX;
  7. var fractX = ( x - minWorldX ) / ( this.maxWorldX - minWorldX ) *
  8. this.heightmapWidth;
  9. var minWorldY = this.minWorldY;
  10. var fractY = ( 1 - ( y - minWorldY ) / ( this.maxWorldY - minWorldY ) ) *
  11. this.heightmapHeight;
  12. // Find the (x,y)
  13. var x1 = Math.round( fractX );
  14. var y1 = Math.round( fractY );
  15. // Find the heightmap value
  16. var heightValue = this.getHeightmapValue( x1, y1 );
  17. // Convert that value into a height
  18. // Height range is from 0 to ( 256^3 - 1 ) ... or 16777215
  19. var heightPercent = heightValue / 16777215;
  20. var minWorldZ = this.minWorldZ;
  21. var zRange = this.maxWorldZ - minWorldZ;
  22. return minWorldZ + heightPercent * zRange;
  23. // Here starts the commented-out more accurate (though slower) trilinear interpolation version
  24. // // The following diagram show the values being calculated in this function:
  25. // //
  26. // // a --e-------- b
  27. // // | |
  28. // // | g | In the world y increases up.
  29. // // | | In the heightmap y increases down.
  30. // // | |
  31. // // c --f-------- d
  32. // //
  33. // // g is the point for which the height value has been requested
  34. // // a, b, c, d represent the four closest values in the heightmap
  35. // // We interpolate betweena and b to find e and between c and d to find f
  36. // // Then, we interpolate between e and f to find g
  37. // // (the value at the requested location)
  38. // // Convert world (x,y) into fractional array indices
  39. // var gX = ( x - this.minWorldX ) / ( this.maxWorldX - this.minWorldX ) *
  40. // this.heightmapWidth;
  41. // var gY = ( 1 - ( y - this.minWorldY ) / ( this.maxWorldY - this.minWorldY ) ) *
  42. // this.heightmapHeight;
  43. // // Find the (x,y) for a,b,c,d
  44. // var x1 = Math.floor( gX );
  45. // var x2 = Math.ceil( gX );
  46. // var y1 = Math.floor( gY );
  47. // var y2 = Math.ceil( gY );
  48. // // Find the heightmap values at a,b,c,d
  49. // var a = this.getHeightmapValue( x1, y1 );
  50. // var b = this.getHeightmapValue( x2, y1 );
  51. // var c = this.getHeightmapValue( x1, y2 );
  52. // var d = this.getHeightmapValue( x2, y2 );
  53. // // Interpolate to find e and f
  54. // var e = a * ( gX - x1 ) + b * ( x2 - gX );
  55. // var f = c * ( gX - x1 ) + d * ( x2 - gX );
  56. // // Interpolate between e and f to find g
  57. // var g = e * ( gY - y1 ) + f * ( y2 - gY );
  58. // // Convert that value into a height
  59. // // Height range is from 0 to ( 255 * 256 * 256 ) ... or 16711680
  60. // var gHeightPercent = g / 16711680;
  61. // var zRange = this.maxWorldZ - this.minWorldZ;
  62. // return this.minWorldZ + gHeightPercent * zRange;
  63. }
  64. this.getHeightmapValue = function( x, y ) {
  65. // The heightamp is a flat array that contains four values for each pixel (r,g,b,a)
  66. // Since the image is grayscale, the (r,g,b) values should all be equal.
  67. // Therefore, we pull out the red channel from a pixel and use it as the heightmap
  68. // value
  69. var rIndex = 4 * ( this.heightmapWidth * y + x );
  70. var gIndex = rIndex + 1;
  71. var bIndex = gIndex + 1;
  72. var heightmapData = this.heightmap;
  73. var rValue = heightmapData[ rIndex ];
  74. var gValue = heightmapData[ gIndex ];
  75. var bValue = heightmapData[ bIndex ];
  76. return rValue + gValue * 256 + bValue * 65280;
  77. }
  78. //@ sourceURL=http://vwf.example.com/heightmap.js