TopoLoader.gd 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. extends Node
  2. #var Downloader = preload("res://downloader.gd")
  3. var cache = {}
  4. var topoChunks = {}
  5. var maxheight = 10.783
  6. var minheight = -8.719
  7. signal fileReady
  8. signal chunkCached
  9. class topoChunk:
  10. var chunkPos: Vector2
  11. var filePrefix = "user://topo/"
  12. var formatString = "SLDEM2015_%s_%02d%s_%02d%s_%03d_%03d_FLOAT.IMG"
  13. var samplesPerLine = 23040
  14. var lines = 15360
  15. var offset = 1737.4*1000
  16. var scaleFact = 1
  17. var resolution = 512
  18. var orientation: String = "N"
  19. var latMin = 0
  20. var latMax = 30
  21. var lonMin = 0
  22. var lonMax = 45
  23. var chunkCached = false
  24. var fileReady = false
  25. var file: File
  26. # Called when the node enters the scene tree for the first time.
  27. func open(latMinIN, lonMinIN):
  28. chunkPos = Vector2(latMinIN, lonMinIN)
  29. latMin = (int(latMinIN)/30) * 30
  30. if latMinIN >= 0:
  31. orientation = "N"
  32. latMax = latMin+30
  33. else:
  34. orientation = "S"
  35. latMax = latMin-30
  36. lonMin = (int(lonMinIN)/45) * 45
  37. lonMax = lonMin+45
  38. file = File.new()
  39. print("opening topo: "+getFilepath())
  40. var err = file.open(getFilepath(), File.READ)
  41. if err == 7:
  42. Downloader.download(getFilename(), "topo")
  43. var dl = Downloader.Download.new()
  44. while not dl._file_name == getFilepath():
  45. dl = yield(Messenger, "fileDownloaded")
  46. file.open(getFilepath(), File.READ)
  47. _fileReady()
  48. return true
  49. elif err != 0:
  50. push_error("error opening file err:%s" %err)
  51. return false
  52. else:
  53. fileReady = true
  54. return true
  55. func getFilename():
  56. # example sldem2015_512_00n_30n_000_045_float.img
  57. # "%s/sldem2015_%s_%0*d%s_%0*d%s_%00*d_%00*d_float.img"
  58. var properties
  59. if orientation == "S":
  60. properties = [resolution, abs(latMax), orientation, abs(latMin), orientation, lonMin, lonMax]
  61. else:
  62. properties = [resolution, latMin, orientation, latMax, orientation, lonMin, lonMax]
  63. return formatString % properties
  64. func getFilepath():
  65. return filePrefix+getFilename()
  66. func _fileReady():
  67. fileReady = true
  68. Messenger.emit_signal("fileReady", self)
  69. func close():
  70. file.close()
  71. #queue_free()
  72. func clear():
  73. cache = {}
  74. func cacheChunk(chunkPos: Vector2):
  75. var tc
  76. if topoChunks.has(chunkPos.x) and topoChunks[chunkPos.x].has(chunkPos.y):
  77. tc = cache[chunkPos.y][chunkPos.x]
  78. return tc
  79. tc = topoChunk.new()
  80. tc.open(chunkPos.x, chunkPos.y)
  81. while tc.get_class() != topoChunk.get_class() and not tc.fileReady and tc.chunkPos != chunkPos:
  82. tc = yield(Messenger, "fileReady")
  83. var lat = chunkPos.x
  84. while lat <= chunkPos.x + 1.0:
  85. cache[lat]={}
  86. var line = abs(lat)*tc.resolution*tc.samplesPerLine*4
  87. # the origin of each .img file lies in it's upper left corner
  88. # so we need to read the files from the end on the northern hemisphere
  89. if lat >= 0:
  90. var origin = (chunkPos.x + 1.0)*tc.resolution*tc.samplesPerLine*4
  91. tc.file.seek((origin - line) + chunkPos.y*tc.resolution*4)
  92. else:
  93. tc.file.seek(line + chunkPos.y*tc.resolution*4)
  94. var lon = chunkPos.y
  95. while lon <= chunkPos.y + 1.0:
  96. cache[lat][lon] = tc.file.get_float()
  97. lon += 1.0/float(tc.resolution)
  98. lat += 1.0/float(tc.resolution)
  99. tc.chunkCached = true
  100. if not topoChunks.has(chunkPos.x):
  101. topoChunks[chunkPos.x] = {}
  102. topoChunks[chunkPos.x][chunkPos.y] = tc
  103. tc.file.close()
  104. Messenger.emit_signal("chunkCached", tc)
  105. return tc
  106. func createHeightmap(chunkPos:Vector2):
  107. var minLat:float = chunkPos.x
  108. var minLon:float = chunkPos.y
  109. var maxLat:float = chunkPos.x + 1.0
  110. var maxLon:float = chunkPos.y + 1.0
  111. var idxX = 0
  112. var idxY = 0
  113. var value = 0.0
  114. var heightmap = Image.new()
  115. heightmap.create(len(cache[cache.keys()[0]]), len(cache), false, Image.FORMAT_RF)
  116. heightmap.lock()
  117. for y in cache.keys():
  118. if not minLat:
  119. minLat = y
  120. for x in cache[y].keys():
  121. if not minLon:
  122. minLon = x
  123. value = inverse_lerp(minheight, maxheight, cache[y][x])
  124. heightmap.set_pixel(idxX, idxY, Color(value,0,0))#Color(cache[y][x],0,0))
  125. maxLon = x
  126. idxX += 1
  127. maxLat = y
  128. idxY += 1
  129. idxX = 0
  130. heightmap.unlock()
  131. var heightmapfilepath = "user://heightmap/%s:%s-%s:%s.png"%[minLat, minLon, maxLat, maxLon]
  132. heightmap.save_png(heightmapfilepath)
  133. return heightmap
  134. func read(lat,lon):
  135. if cache.has(lat) and cache[lat].has(lon):
  136. return cache[lat][lon]
  137. else:
  138. print("out of scope!")
  139. #func _validate(lat,lon):
  140. # var condition = true
  141. # if abs(lat) > latMax:
  142. # condition = false
  143. # if abs(lat) < latMin:
  144. # condition = false
  145. # if lon > lonMax:
  146. # condition = false
  147. # if lon < lonMin:
  148. # condition = false
  149. #
  150. # return condition
  151. #if abs(lat) <= latMax and abs(lat) >= latMin and lon <= lonMax and lon >= lonMin:
  152. # return true
  153. #return false
  154. # Called every frame. 'delta' is the elapsed time since the previous frame.
  155. #func _process(delta):
  156. # pass