]> marstr Code Repo - marstr/orthographic.git/commitdiff
Perlin-noise based renderer fully functional. perlin.py adjusted to produce fully...
authorMarcus Str. <marcus@marstr.online>
Sat, 1 Feb 2025 15:39:15 +0000 (16:39 +0100)
committerMarcus Str. <marcus@marstr.online>
Sat, 1 Feb 2025 15:39:41 +0000 (16:39 +0100)
defines.py
layergen.py
og.py
orthographic.py
perlin.py
photogen.py
xp_scenery.py

index 733a5059b8e9b2e825f6a40448c738e43c61894a..6494065857a1a033834741264606df140bc3edd4 100644 (file)
@@ -71,7 +71,7 @@ mstr_xp_genscenery = True
 \r
 # Generate normal maps for X-Plane scenery?\r
 # Strong recommendation: yes\r
-mstr_xp_scn_normalmaps = True\r
+mstr_xp_scn_normalmaps = False\r
 \r
 # Paths to required X-Plane scenery tools\r
 #mstr_xp_meshtool = "/home/marcus/Developer/Projects/orthographic/bin/MeshTool"\r
@@ -195,11 +195,11 @@ mstr_ortho_layers = [
     ("building", "commercial", "building", "commercial"),\r
     ("building", "warehouse", "building", "warehouse"),\r
     ("building", "yes", "building", "common"),\r
+    #("waterway", "river", 3),\r
     ("water", "lake", "natural", "water"),\r
     ("water", "pond", "natural", "water"),\r
     ("water", "river", "natural", "water"),\r
     ("natural", "water", "natural", "water"),\r
-    ("waterway", "river", 3),\r
     ("place", "sea", "natural", "sea"),\r
     ("place", "ocean", "natural", "sea")\r
 ]\r
@@ -244,11 +244,12 @@ mstr_mask_blur = [
     ("natural", "water", 1),\r
     ("natural", "bay", 7),\r
     ("natural", "beach", 7),\r
+    ("natural", "sand", 3),\r
     ("water", "lake", 3),\r
     ("water", "pond", 3),\r
     ("water", "river", 3),\r
     ("leisure", "swimming_pool", 3),\r
-    ("waterway", "river", 3),\r
+    #("waterway", "river", 3),\r
     ("waterway", "stream", 2),\r
     ("amenity", "parking", 1),\r
     ("amenity", "school", 1),\r
index 59f3a3b61f0be0b75cc1491750a4ac8b5104a309..f78a7fb26e628e94bdd34a1a6b229de7dde587e4 100644 (file)
@@ -361,8 +361,8 @@ class mstr_layergen:
                 for x in range(0, layer.width):\r
                     xp = prln_x + int(x/prln_pix_step)\r
                     yp = prln_y + int(y/prln_pix_step)\r
-                    if xp == perlin_map.width:  xp = perlin_map.width - 1\r
-                    if yp == perlin_map.height: yp = perlin_map.height - 1\r
+                    if xp >= perlin_map.width:  xp = perlin_map.width - 1\r
+                    if yp >= perlin_map.height: yp = perlin_map.height - 1\r
                     pc = perlin_pix[xp,yp]\r
                     df = randrange(0, 6)\r
                     lc = (pc[0]+df, pc[1]+df, pc[2]+df, 255)\r
@@ -666,7 +666,6 @@ class mstr_layergen:
             #layer_comp.save( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )\r
             mstr_msg("layergen", "Layer image finalized and saved.")\r
 \r
-\r
             # Return image\r
             return layer_comp\r
 \r
@@ -801,8 +800,6 @@ class mstr_layergen:
                     if mp[3] == 255 and tp[3] == 255:\r
                         tree_pix[x,y] = (0,0,0,0)\r
 \r
-\r
-\r
             if mstr_shadow_enabled == True:\r
                 tree_pix = trees.load()\r
                 shadow_pix = tree_shadow.load()\r
@@ -842,7 +839,6 @@ class mstr_layergen:
             return bld_comp\r
 \r
 \r
-\r
     # Find the next "by-ten" numbers for the current latitude and longitude\r
     def find_earthnavdata_number(self):\r
         earthnavdata = []\r
diff --git a/og.py b/og.py
index ce483ba8183071070b8b5b4c42e49de933c6d336..3ff99af9c0f9d8c0b52b2507d5c0a61ca89a3e26 100644 (file)
--- a/og.py
+++ b/og.py
@@ -19,25 +19,26 @@ from defines import *
 \r
 \r
 # Print a welcome message\r
-print(r' ')\r
-print(r'   ____       __  __                                 __    _     ')\r
-print(r'  / __ \_____/ /_/ /_  ____  ____ __________ _____  / /_  (_)____')\r
-print(r' / / / / ___/ __/ __ \/ __ \/ __ `/ ___/ __ `/ __ \/ __ \/ / ___/')\r
-print(r'/ /_/ / /  / /_/ / / / /_/ / /_/ / /  / /_/ / /_/ / / / / / /__  ')\r
-print(r'\____/_/   \__/_/ /_/\____/\__, /_/   \__,_/ .___/_/ /_/_/\___/  ')\r
-print(r'                          /____/          /_/                    ')\r
-print(r' ----------------------------------------------------------------')\r
-print(r'   A ground texture generator, using photo realistic resources,')\r
-print(r'                    for flight simulators.')\r
-print(r' ----------------------------------------------------------------')\r
-print(r'               Developed by and (c) Marcus Str.')\r
-print(r'          Website: https://marstr.online/orthographic')\r
-print(r' Code repo:  https://marstr.online/code/gitweb.cgi?p=orthographic')\r
-print(r' ----------------------------------------------------------------')\r
-print(r' If you paid for this software, you have been scammed. The source')\r
-print(r'           code and always available free of charge.')\r
-print(r' ----------------------------------------------------------------')\r
-print(r' ')\r
+def _welcome():\r
+    print(r' ')\r
+    print(r'   ____       __  __                                 __    _     ')\r
+    print(r'  / __ \_____/ /_/ /_  ____  ____ __________ _____  / /_  (_)____')\r
+    print(r' / / / / ___/ __/ __ \/ __ \/ __ `/ ___/ __ `/ __ \/ __ \/ / ___/')\r
+    print(r'/ /_/ / /  / /_/ / / / /_/ / /_/ / /  / /_/ / /_/ / / / / / /__  ')\r
+    print(r'\____/_/   \__/_/ /_/\____/\__, /_/   \__,_/ .___/_/ /_/_/\___/  ')\r
+    print(r'                          /____/          /_/                    ')\r
+    print(r' ----------------------------------------------------------------')\r
+    print(r'   A ground texture generator, using photo realistic resources,')\r
+    print(r'                    for flight simulators.')\r
+    print(r' ----------------------------------------------------------------')\r
+    print(r'               Developed by and (c) Marcus Str.')\r
+    print(r'          Website: https://marstr.online/orthographic')\r
+    print(r'    Code repo:  http://marstr.online:3000/marstr/orthographic')\r
+    print(r' ----------------------------------------------------------------')\r
+    print(r' If you paid for this software, you have been scammed. The source')\r
+    print(r'           code and always available free of charge.')\r
+    print(r' ----------------------------------------------------------------')\r
+    print(r' ')\r
 \r
 \r
 # Evaluate CLI arguments and process tile.\r
@@ -61,20 +62,17 @@ if __name__ == '__main__':
         # Create the class and init values\r
         og = mstr_orthographic(lat, lng, mstr_datafolder, os.getcwd(), prep)\r
 \r
-        # Prepare a tile\r
-        if sys.argv[3] == "prepare":\r
-            og._prepareTile()\r
-\r
         # Generate orthos\r
         if sys.argv[3] != "prepare" and sys.argv[3] != "xpscenery":\r
+            _welcome()\r
             og._generateOrthos_mt(int(sys.argv[3]))\r
 \r
         # Build the terrain mesh and assign ground textures\r
         if sys.argv[3] == "xpscenery":\r
+            _welcome()\r
             og.generate_xp_scenery()\r
 \r
 \r
-\r
     if cli == False and pbf == False:\r
         mstr_msg("_main", "Please provide Latitude and Longitude. Exiting.")\r
         print ("")\r
index f2dda2cc9ba5339ab2793309fb7619f6ff226284..33736c4a8b4f008ea0e79be2fc82f03c560bf1cf 100644 (file)
@@ -241,15 +241,16 @@ class mstr_orthographic:
         # Step 2\r
         # Create folders and generate all perlin noise maps\r
         self._createFolders()\r
-        """\r
+        #"""\r
         for l in mstr_ortho_layers:\r
             if l[0] != "highway" and l[0] != "building":\r
-                mstr_important_msg("orthographic", "Generating Perlin map for " + l[0] + ":" + l[1])\r
-                prln = mstr_perlin(l[0], l[1], mlat, mlng, 16)\r
-                pmap = prln._generatePerlinMap()\r
                 fn = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/perlin/" + l[0] + "_" + l[1] + ".png"\r
-                pmap.save(fn)\r
-        """\r
+                if os.path.isfile(fn) == False:\r
+                    mstr_important_msg("orthographic", "Generating Perlin map for " + l[0] + ":" + l[1])\r
+                    prln = mstr_perlin(l[0], l[1], mlat, mlng, 16)\r
+                    pmap = prln._generatePerlinMap()\r
+                    pmap.save(fn)\r
+        #"""\r
 \r
         # For completion layers\r
         numbers = list(range(1, 16))\r
@@ -285,9 +286,15 @@ class mstr_orthographic:
         mlng = 1\r
         while bb_lat < self._lat + 1:\r
             bb_lat = bb_lat + self._vstep\r
+            if bb_lat >= self._lat + 1:\r
+                bb_lat = bb_lat - self._zoomlevel\r
+                break\r
             mlat = mlat+1\r
         while bb_lng < self._long + 1:\r
             bb_lng = bb_lng + self._zoomlevel\r
+            if bb_lng >= self._long + 1:\r
+                bb_lng = bb_lng - self._zoomlevel\r
+                break\r
             mlng = mlng+1\r
         mstr_msg("orthographic", "Max lat tile: " + str(mlat) + " - max lng tile: " + str(mlng))\r
         maxlatlng = [ mlat, mlng ]\r
@@ -631,7 +638,7 @@ class mstr_orthographic:
     # - the finished orthos\r
     # - a current LIDAR scan of the terrain\r
     def generate_xp_scenery(self):\r
-        mstr_msg("orthographic", "[X-Plane] Generation of scenery started")\r
+        mstr_important_msg("orthographic", "[X-Plane] Generation of scenery started")\r
 \r
         # This call appears quite often... surely this can be done better\r
         mlat = 1\r
@@ -654,8 +661,8 @@ class mstr_orthographic:
         mstr_msg("orthographic", "[X-Plane] Scenery object instantiated")\r
 \r
         # Download LIDAR scan from our endpoint\r
-        xpscn.acquire_elevation_data()\r
-        mstr_msg("orthographic", "[X-Plane] Elevation data acquired")\r
+        #xpscn.acquire_elevation_data()\r
+        #mstr_msg("orthographic", "[X-Plane] Elevation data acquired")\r
 \r
         # Generate the .ter files\r
         xpscn.build_ter_files()\r
index 799a953eb5047434f9ec3ee2752a48beed3858a5..b462c310e509817798346ef06265357384747f49 100644 (file)
--- a/perlin.py
+++ b/perlin.py
@@ -15,6 +15,8 @@ from PIL import Image # Depends on the Pillow lib
 from random import randrange
 import random
 import numpy as np
+import glob
+from defines import *
 from perlin_numpy import (
     generate_perlin_noise_2d, generate_fractal_noise_2d
 )
@@ -32,113 +34,70 @@ class mstr_perlin:
         if zl == 16: self._mapscale = 80
         if zl == 18: self._mapscale = 20
 
-        # Define some base colors
-        # tag, value, base color, perlin noise color palette
-        self._bc = [
-            # Amenity
-            ["amenity", "parking",              (31,32,34,255), [ (31,32,34), (74,74,73), (56,55,55), (34,40,44) ]],
-            ["amenity", "school",               (26,26,26,255), [ (26,26,26), (78,78,78), (28,29,25), (86,74,64) ]],
-            # Barrier
-            ["barrier", "hedge",                (27,37,25,255), [ (27,37,25),  (8,14,13), (15,20,23), (40,40,38) ]],
-            # Boundary
-            ["boundary", "administrative",      (50,49,46,255), [ (50,49,46), (32,38,34),  (9,14,18), (82,80,76) ]],
-            # Landuse
-            ["landuse", "cemetery",             (22,22,20,255), [ (22,22,20), (44,43,40), (31,33,29), (39,37,34) ]],
-            ["landuse", "construction",         (65,51,32,255), [ (65,51,32), (77,73,67), (45,49,43), (74,63,48) ]],
-            ["landuse", "farmland",             (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["landuse", "farmyard",             (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["landuse", "forest",               (0,30,10,255),  [  (0,30,10), (18,23,16), (15,23,24), (24,29,27) ]],
-            ["landuse", "grass",                (23,24,22,255), [ (23,24,22), (40,27,35), (32,34,30), (54,53,51) ]],
-            ["landuse", "greenfield",           (23,24,22,255), [ (23,24,22), (40,27,35), (32,34,30), (54,53,51) ]],
-            ["landuse", "meadow",               (28,29,27,255), [ (28,29,27), (36,42,40), (45,44,41), (21,22,20) ]],
-            ["landuse", "military",             (23,24,22,255), [ (23,24,22), (40,27,35), (32,34,30), (54,53,51) ]],
-            ["landuse", "orchard",              (27,38,27,255), [ (27,38,27), (19,22,16), (40,42,33), (40,50,45) ]],
-            ["landuse", "recreation_ground",    (27,38,27,255), [ (27,38,27), (19,22,16), (40,42,33), (40,50,45) ]],
-            ["landuse", "residential",          (50,49,46,255), [ (50,49,46), (32,38,34),  (9,14,18), (82,80,76) ]],
-            ["landuse", "residential-boundary", (50,49,46,255), [ (50,49,46), (32,38,34),  (9,14,18), (82,80,76) ]],
-            ["landuse", "vineyard",             (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            # Leisure
-            ["leisure", "dog_park",             (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["leisure", "garden",               (39,39,32,255), [ (39,39,32), (38,47,43), (35,41,31), (21,25,18) ]],
-            ["leisure", "golf_course",          (29,39,28,255), [ (29,39,28), (86,81,76), (60,55,45), (13,18,14) ]],
-            ["leisure", "green",                (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["leisure", "nature_reserve",       (0,30,10,255),  [  (0,30,10), (18,23,16), (15,23,24), (24,29,27) ]],
-            ["leisure", "park",                 (23,24,22,255), [ (23,24,22), (40,27,35), (32,34,30), (54,53,51) ]],
-            ["leisure", "pitch",                (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["leisure", "playground",           (65,51,32,255), [ (65,51,32), (77,73,67), (45,49,43), (74,63,48) ]],
-            ["leisure", "sports_centre",        (66,60,49,255), [ (66,60,49), (23,32,27), (14,18,20), (45,43,39) ]],
-            ["leisure", "swimming_pool",        (9,13,18,255),  [  (9,13,18),  (9,15,21), (11,12,12), (22,28,31) ]],
-            # Natural
-            ["natural", "bare_rock",            (47,54,56,255), [ (47,54,56), (79,75,71), (84,51,43), (26,33,45) ]],
-            ["natural", "beach",                (79,76,69,255), [ (79,76,69), (82,83,80), (71,61,48), (69,68,66) ]],
-            ["natural", "desert",               (79,64,42,255), [ (79,64,42), (79,47,24), (37,41,27), (51,39,23) ]],
-            ["natural", "grassland",            (23,24,22,255), [ (23,24,22), (40,27,35), (32,34,30), (54,53,51) ]],
-            ["natural", "heath",                (26,28,23,255), [ (26,28,23), (45,44,42), (30,34,29), (45,45,42) ]],
-            ["natural", "sand",                 (79,76,69,255), [ (79,76,69), (82,83,80), (71,61,48), (69,68,66) ]],
-            ["natural", "scree",                (38,36,33,255), [ (38,36,33), (81,80,76), (43,42,31), (37,34,27) ]],
-            ["natural", "scrub",                (41,39,35,255), [ (41,39,35), (44,38,34), (30,32,39), (20,27,22) ]],
-            ["natural", "water",                (9,13,18,255),  [  (9,13,18),  (9,15,21), (11,12,12), (22,28,31) ]],
-            ["natural", "wetland",              (32,34,33,255), [ (32,34,33),  (5, 8, 8), (35,36,35), (17,19,17) ]],
-            ["natural", "wood",                 (0,30,10,255),  [  (0,30,10), (18,23,16), (15,23,24), (24,29,27) ]],
-            # Water
-            ["water", "lake",                   (9,13,18,255),  [  (9,13,18),  (9,15,21), (11,12,12), (22,28,31) ]],
-            ["water", "pond",                   (9,13,18,255),  [  (9,13,18),  (9,15,21), (11,12,12), (22,28,31) ]],
-            ["water", "river",                  (9,13,18,255),  [  (9,13,18),  (9,15,21), (11,12,12), (22,28,31) ]]
-        ]
 
+    def _generateColorIndex(self):
+        idx = []
+
+        colorsrc = glob.glob(mstr_datafolder + "textures/" + self._tag + "/" + self._value + "/*.png")
+        if len(colorsrc) >= 4:
+            picknum = list(range(0, len(colorsrc)))
+            picksel = random.sample(picknum, 4)
+
+            for p in range(0, 4):
+                ptc = Image.open(colorsrc[picksel[p]])
+                ptc = ptc.resize((1,1), resample=Image.Resampling.BILINEAR)
+                clr = ptc.getpixel((0,0))
+                res = (clr[0], clr[1], clr[2])
+                idx.append(res)
 
-    # Find base color depending on tag/value
-    def _findBaseColor(self):
-        idx = -1
-        for b in range(len(self._bc)):
-            if self._bc[b][0] == self._tag and self._bc[b][1] == self._value:
-                idx = b
-                break
         return idx
 
 
     # Generates a Perlin map depending on what we need
     def _generatePerlinMap(self):
-        idx = self._findBaseColor()
-
+        #idx = self._findBaseColor()
+        clr = self._generateColorIndex()
         bw = self._mlng * self._mapscale
         bh = self._mlat * self._mapscale
-        wh = 2048
-        base = Image.new("RGBA", (bw,bh), self._bc[idx][2])
+        base = Image.new("RGBA", (bw,bh))
 
-        for c in range(len(self._bc[idx][3])):
-            np.random.seed(randrange(10000000, 100000000))
-            noise1 = generate_fractal_noise_2d((wh,wh), (16,16), 5)
-            np.random.seed(randrange(10000000, 100000000))
-            noise2 = generate_fractal_noise_2d((wh,wh), (8,8), 4)
-
-            im1 = Image.new("RGBA", (wh,wh))
-            im2 = Image.new("RGBA", (wh,wh))
+        if len(clr) == 4:
+            wh = 2048
+            base = Image.new("RGBA", (bw,bh), clr[0])
             
-            for y in range(0, wh):
-                for x in range(0, wh):
-                    n = (noise1[y][x] + 1) / 2
-                    v = (
-                        self._bc[idx][3][c][0],
-                        self._bc[idx][3][c][1],
-                        self._bc[idx][3][c][2],
-                        int(n*255)
-                        )
-                    im1.putpixel((x,y), v)
-                    
-            for y in range(0, wh):
-                for x in range(0, wh):
-                    n = (noise2[y][x] + 1) / 2
-                    v = (
-                        self._bc[idx][3][c][0],
-                        self._bc[idx][3][c][1],
-                        self._bc[idx][3][c][2],
-                        int(n*255)
-                        )
-                    im2.putpixel((x,y), v)
-                    
-            im = Image.blend(im1,im2, alpha=0.5)
-            base.alpha_composite(im)
+            for c in range(len(clr)):
+                np.random.seed(randrange(10000000, 100000000))
+                noise1 = generate_fractal_noise_2d((wh,wh), (64,64), 5)
+                np.random.seed(randrange(10000000, 100000000))
+                noise2 = generate_fractal_noise_2d((wh,wh), (32,32), 4)
+
+                im1 = Image.new("RGBA", (wh,wh))
+                im2 = Image.new("RGBA", (wh,wh))
+                
+                for y in range(0, wh):
+                    for x in range(0, wh):
+                        n = (noise1[y][x] + 1) / 2
+                        v = (
+                            clr[c][0],
+                            clr[c][1],
+                            clr[c][2],
+                            int(n*255)
+                            )
+                        im1.putpixel((x,y), v)
+                        
+                for y in range(0, wh):
+                    for x in range(0, wh):
+                        n = (noise2[y][x] + 1) / 2
+                        v = (
+                            clr[c][0],
+                            clr[c][1],
+                            clr[c][2],
+                            int(n*255)
+                            )
+                        im2.putpixel((x,y), v)
+                        
+                im = Image.blend(im1,im2, alpha=0.675)
+                base.alpha_composite(im)
 
         # Provide the perlin map
         return base
\ No newline at end of file
index d503e5b0bb4957ea086fa5dd0b5ed68843154520..6fb969840bf03601151bec555ba700cc9faaa318 100644 (file)
@@ -210,8 +210,6 @@ class mstr_photogen:
         #self._tile = ImageEnhance.Contrast(self._tile).enhance(0.1)\r
 \r
         # This we can save accordingly.\r
-        self._tile.show()\r
-        exit()\r
         self._tile.save(mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(self._ty) + "_" + str(self._tx) + ".png")\r
 \r
         # Now we convert this into a DDS\r
@@ -489,13 +487,13 @@ class mstr_photogen:
         # First the residential/forest dilemma\r
         residential = -1\r
         forest = -1\r
+        reserve = -1\r
 \r
         curlyr = 0\r
         for lyr in self._lyrnames:\r
-            if lyr[0] == "landuse" and lyr[1] == "residential":\r
-                residential=curlyr\r
-            if lyr[0] == "landuse" and lyr[1] == "forest":\r
-                forest = curlyr\r
+            if lyr[0] == "landuse" and lyr[1] == "residential": residential=curlyr\r
+            if lyr[0] == "landuse" and lyr[1] == "forest": forest = curlyr\r
+            if lyr[0] == "leisure" and lyr[1] == "nature_reserve": reserve = curlyr\r
             curlyr = curlyr+1\r
 \r
         # Make sure we hit the correct layers with correct content!\r
@@ -515,9 +513,80 @@ class mstr_photogen:
 \r
             layers[forest].alpha_composite(rsd_adj)\r
 \r
-        return layers\r
 \r
+        if residential != -1 and reserve != -1:\r
+            rsd_pix = layers[residential].load()\r
+            frs_pix = layers[reserve].load()\r
+            rsd_adj = Image.new("RGBA", (self._imgsize, self._imgsize))\r
+            adj_pix = rsd_adj.load()\r
 \r
+            for y in range(0, self._tile.height):\r
+                for x in range(0, self._tile.width):\r
+                    fp = frs_pix[x,y]\r
+                    rp = rsd_pix[x,y]\r
+                    if rp[3] > 0 and fp[3] > 0:\r
+                        adj_pix[x,y] = (rp[0], rp[1], rp[2], rp[3])\r
+\r
+            layers[reserve].alpha_composite(rsd_adj)\r
+\r
+        # At ZL16 there seems to be an issue with water bodies, especially rivers (natural:water).\r
+        # Let's see if we can correct that\r
+\r
+        # natural:water\r
+        ntrl_water = False\r
+        ntrl_idx = 0\r
+        for lyr in self._lyrnames:\r
+            if lyr[0] == "natural" and lyr[1] == "water":\r
+                ntrl_water = True\r
+                break\r
+            ntrl_idx = ntrl_idx + 1\r
+\r
+        if ntrl_water == True:\r
+            \r
+            # We'll go through all layers and "shavve off" excess.\r
+            # This way we can hopefully correct incorrect line and polygon renders.\r
+            for l in range(0, len(layers)):\r
+                if l < ntrl_idx: # <- We don't want to load the target layer itself\r
+                    lyrpix = layers[l].load()\r
+                    wtr_pix = layers[ntrl_idx].load()\r
+                    for y in range(0, self._tile.height):\r
+                        for x in range(0, self._tile.width):\r
+                            lp = lyrpix[x,y]\r
+                            wp = wtr_pix[x,y]\r
+                            if lp[3] > 0:\r
+                                a = 255 - lp[3]\r
+                                if a < wp[3]:\r
+                                    c = (wp[0], wp[1], wp[2], a)\r
+                                    wtr_pix[x,y] = c\r
+\r
+        # water:river\r
+        river_water = False\r
+        river_idx = 0\r
+        for lyr in self._lyrnames:\r
+            if lyr[0] == "water" and lyr[1] == "river":\r
+                river_water = True\r
+                break\r
+            river_idx = river_idx + 1\r
+\r
+        if river_water == True:\r
+            \r
+            # We'll go through all layers and "shavve off" excess.\r
+            # This way we can hopefully correct incorrect line and polygon renders.\r
+            for l in range(0, len(layers)):\r
+                if l < river_idx and l != ntrl_idx: # <- We don't want to load the target layer itself\r
+                    lyrpix = layers[l].load()\r
+                    wtr_pix = layers[river_idx].load()\r
+                    for y in range(0, self._tile.height):\r
+                        for x in range(0, self._tile.width):\r
+                            lp = lyrpix[x,y]\r
+                            wp = wtr_pix[x,y]\r
+                            if lp[3] > 0:\r
+                                a = 255 - lp[3]\r
+                                if a < wp[3]:\r
+                                    c = (wp[0], wp[1], wp[2], a)\r
+                                    wtr_pix[x,y] = c\r
+\r
+        return layers\r
 \r
 \r
     # This checks the final image for empty patches. Should one be\r
index 0ba44d4495fb840135a56e9c07c860c898b78c48..5660e5fb6a243d886be31d40efbc3b1fbe81ee88 100644 (file)
@@ -92,8 +92,13 @@ class mstr_xp_scenery:
         end = self.find_earthnavdata_number()
         llf = self.xplane_latlng_folder(end)
         meshtxt = mstr_datafolder + "_cache/mesh_"+self._latlngfld+".txt"
-        cmd = mstr_xp_dsftool + " --text2dsf " + meshtxt + " '" + mstr_datafolder + "z_orthographic/Earth nav data/" + llf + "/" + self._latlngfld + ".dsf'"
+        meshtxt = meshtxt.replace("/", "\\")
+        cmdpath = mstr_datafolder + "_cache/" + self._latlngfld + ".dsf"
+        #cmdpath = mstr_datafolder + "z_orthographic/Earth nav data/" + llf + "/" + self._latlngfld + ".dsf"
+        cmdpath = cmdpath.replace("/", "\\")
+        cmd = mstr_xp_dsftool + " --text2dsf " + meshtxt + " " + cmdpath
         os.system(cmd)
+        os.replace(cmdpath, mstr_datafolder + "z_orthographic/Earth nav data/" + llf + "/" + self._latlngfld + ".dsf")
 
 
     # Find exact with of longitude
@@ -165,14 +170,14 @@ class mstr_xp_scenery:
         cur_lat = self._lat
         cur_lng = self._lng
         xp_folder = self.xplane_latlng_folder([self._lat, self._lng])
-        for lat in range(1, self._mlat+1):
-            for lng in range(1, self._mlng+1):
+        for lat in range(1, self._mlat):
+            for lng in range(1, self._mlng):
 
                 wdt = self.find_width_of_longitude(cur_lat)
-                dmt = wdt * mstr_zl_18
+                dmt = wdt * mstr_zl_16
 
                 cnt_x = cur_lat + (self._vstep/2)
-                cnt_y = cur_lng + (mstr_zl_18/2)
+                cnt_y = cur_lng + (mstr_zl_16/2)
 
                 terstr = ""
                 terstr = terstr + "A\r\n"
@@ -181,15 +186,15 @@ class mstr_xp_scenery:
                 terstr = terstr + "\r\n"
                 terstr = terstr + "LOAD_CENTER " + str(cnt_x) + " " + str(cnt_y) + " " + str(dmt) + " 2048\r\n"
                 terstr = terstr + "BASE_TEX_NOWRAP ../../orthos/" + self._latlngfld + "/" + str(lat)+"_"+str(lng)+".dds\r\n"
-                if mstr_xp_scn_normalmaps:
-                    terstr = terstr + "NORMAL_TEX 1.0 ../../normals/" + self._latlngfld + "/" + str(lat)+"_"+str(lng)+".png\r\n"
+                #if mstr_xp_scn_normalmaps:
+                #    terstr = terstr + "NORMAL_TEX 1.0 ../../normals/" + self._latlngfld + "/" + str(lat)+"_"+str(lng)+".png\r\n"
 
                 terfln = mstr_datafolder + "z_orthographic/terrain/" + self._latlngfld + "/" + str(lat)+"_"+str(lng)+".ter"
 
                 with open(terfln, 'w') as textfile:
                     textfile.write(terstr)
                 
-                cur_lng = round(cur_lng + mstr_zl_18, 6)
+                cur_lng = round(cur_lng + mstr_zl_16, 6)
 
             cur_lng = self._lng
             cur_lat = round(cur_lat + self._vstep, 6)
@@ -200,7 +205,7 @@ class mstr_xp_scenery:
     # This generates the entire terrain mesh
     def generate_terrain_mesh(self):
         # Get the DEM model file name, and acquire important info about the data
-        meshfn = mstr_datafolder + "_cache/" + self.build_dem_filename()
+        meshfn = mstr_datafolder + "z_orthographic/data/" + self._latlngfld + "/" + self.build_dem_filename()
         siz = os.path.getsize(meshfn)
         dim = int(math.sqrt(siz/2))
         assert dim*dim*2 == siz, 'Invalid file size'
@@ -245,8 +250,8 @@ class mstr_xp_scenery:
         dsf_str = ""
 
         # Orthos
-        for lat in range(1, self._mlat+1):
-            for lng in range(1, self._mlng+1):
+        for lat in range(1, self._mlat):
+            for lng in range(1, self._mlng):
                 # Write the line only if an ortho exists of course.
                 ddsf = mstr_datafolder + "z_orthographic/orthos/" + self._latlngfld + "/" + str(lat) + "_" + str(lng) + ".dds"
                 if os.path.isfile(ddsf):
@@ -261,8 +266,8 @@ class mstr_xp_scenery:
         # Current patch
         curpatch = 0
 
-        for lat in range(1, self._mlat+1):
-            for lng in range(1, self._mlng+1):
+        for lat in range(1, self._mlat):
+            for lng in range(1, self._mlng):
 
                 # Create the patch only if the matching ortho exists.
                 # This way we make sure that we hit the same order as the .ter files.
@@ -273,7 +278,7 @@ class mstr_xp_scenery:
 
                     # Base coords for this ortho
                     base_lat = self._lat + ((lat-1) * self._vstep)
-                    base_lng = self._lng + ((lng-1) * mstr_zl_18)
+                    base_lng = self._lng + ((lng-1) * mstr_zl_16)
 
                     # Begin a new patch
                     mstr_msg("xp_scenery", "[X-Plane] Processing ortho patch " + str(curpatch))
@@ -281,9 +286,10 @@ class mstr_xp_scenery:
                         textfile.write("BEGIN_PATCH " + str(curpatch) + " 0.000000 -1.000000 1 7\r\n")
 
                     # Step for each ortho vertex
-                    odiv = 4
+                    #odiv = 4
+                    odiv = 16
                     latstep = self._vstep/odiv
-                    lngstep = mstr_zl_18 /odiv
+                    lngstep = mstr_zl_16 /odiv
                     uv_step = 1 / odiv
 
                     # Generate the ortho tile
@@ -300,10 +306,14 @@ class mstr_xp_scenery:
                                 lng_l = base_lng
                             if y == 0:
                                 lat_b = base_lat
-                            if y == 3:
+                            if y == 15:
+                            #if y == 3:
                                 lat_t = base_lat + self._vstep
-                            if x == 3:
-                                lng_r = base_lng + mstr_zl_18
+                            if x == 15:
+                                lng_r = base_lng + mstr_zl_16
+                            #if x == 3:
+                                #lng_r = base_lng + mstr_zl_18
+                                
 
                             # Corrections, just in case
                             if lat_b > self._lat + 1: lat_b = self._lat+1