Advertisement
Guest User

Untitled

a guest
Dec 15th, 2019
195
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 5.76 KB | None | 0 0
  1. import godot;
  2. import godot.core;
  3. import godot.object;
  4. import godot.node.all;
  5. import godot.progressbar;
  6. import godot.arraymesh;
  7. import godot.multimesh;
  8. import godot.mesh;
  9. import godot.meshdatatool;
  10. import godot.input;
  11. import godot.inputevent.all;
  12. import godot.resourceloader;
  13. import godot.packedscene;
  14. import godot.visualscriptyield;
  15.  
  16. import std.random;
  17. import std.math;
  18. import array = std.container.array;
  19.  
  20. import std.stdio;
  21.  
  22. mixin GodotNativeLibrary!(
  23.     "planetgenerator",
  24.     Planetgenerator
  25. );
  26.  
  27. class Planetgenerator : GodotScript!WorldEnvironment
  28. {
  29.     alias owner this;
  30.  
  31.     typeof(Random(unpredictableSeed)) rnd;
  32.  
  33.     @OnReady!(gs!"container/progress") ProgressBar progress;
  34.     @OnReady!(gs!"planet/Planet") MeshInstance planet;
  35.     MeshInstance mesh_original;
  36.    
  37.     @Method _ready()
  38.     {
  39.         rnd = Random(unpredictableSeed);
  40.         mesh_original = MeshInstance._new();
  41.         mesh_original.mesh = planet.mesh;
  42.         Input.setMouseMode(Input.MouseMode.mouseModeHidden);
  43.         makePlanet();
  44.     }
  45.    
  46.     @Method _input(InputEvent event)
  47.     {
  48.         if(event.isActionPressed(gs!"ui_accept"))
  49.         {
  50.             if(!progress.visible)
  51.                 makePlanet();
  52.         }
  53.     }
  54.  
  55.     @Method makePlanet()
  56.     {
  57.         Ref!MeshDataTool surf = MeshDataTool._new();
  58.         surf.createFromSurface(mesh_original.mesh.as!ArrayMesh, 0L);
  59.  
  60.         // the tree (pos, normal) pairs
  61.         array.Array!PosNormal tree_pairs;
  62.  
  63.         // show the progress bar
  64.         progress.show();
  65.  
  66.         enum max_iterations = 145;
  67.         //writeln("surf.getVertexCount ", surf.getVertexCount);
  68.         foreach(j; 0..max_iterations)
  69.         {
  70.             // wait a frame to prevent freezing the game
  71.             //yield(get_tree(), "idle_frame")
  72.             //auto vsy = VisualScriptYield._new();
  73.            
  74.             // show progress in the progress bar
  75.             progress.maxValue = max_iterations;
  76.             progress.value = j;
  77.  
  78.             immutable dir = Vector3(
  79.                 uniform!"[]"(-1.0f, 1.0f, rnd),
  80.                 uniform!"[]"(-1.0f, 1.0f, rnd),
  81.                 uniform!"[]"(-1.0f, 1.0f, rnd)
  82.                 ).normalized();
  83.  
  84.             // push/pull all vertices (this is the slow part)
  85.             foreach(i; 0..surf.getVertexCount)
  86.             {
  87.                 Vector3 v = surf.getVertex(i);
  88.                 Vector3 norm = surf.getVertexNormal(i);
  89.                
  90.                 float dot = norm.normalized().dot(dir);
  91.                 enum sharpness = 50;  // how sharp the edges are
  92.                 dot = exp(dot*sharpness) / (exp(dot*sharpness) + 1.0) - 0.5; // sigmoid function
  93.                
  94.                 v += dot * norm * 0.01;
  95.                
  96.                 surf.setVertex(i, v);
  97.             }
  98.         }
  99.  
  100.         enum min_dist = 0.9; // deep sea
  101.         enum max_dist = 1.1; // mountains
  102.         enum vegetation_dist = 1.03; // ideal height for vegetation to grow
  103.         enum beach_dist = 1.0; // beach level
  104.  
  105.         // finally set uv.x according to distance to center, which colors the terrain depending on elevation
  106.    
  107.         foreach(i; 0..surf.getVertexCount)
  108.         {
  109.             auto v = surf.getVertex(i);
  110.             auto dist = v.length;
  111.             auto dist_normalized = (dist-min_dist) / (max_dist-min_dist); // bring dist to 0..1 range
  112.            
  113.             auto uv = Vector2(dist_normalized, 0.0);
  114.             surf.setVertexUv(i, uv);
  115.         }
  116.  
  117.         // also recalculate face normals (TODO smooth 'em!)
  118.    
  119.         foreach(i; 0..surf.getFaceCount)
  120.         {  
  121.             long v1i = surf.getFaceVertex(i, 0);
  122.             long v2i = surf.getFaceVertex(i, 1);
  123.             long v3i = surf.getFaceVertex(i, 2);
  124.            
  125.             Vector3 v1 = surf.getVertex(v1i);
  126.             Vector3 v2 = surf.getVertex(v2i);
  127.             Vector3 v3 = surf.getVertex(v3i);
  128.            
  129.             // calculate normal for this face
  130.             Vector3 norm = -(v2 - v1).normalized().cross((v3 - v1).normalized()).normalized();
  131.            
  132.             surf.setVertexNormal(v1i, norm);
  133.             surf.setVertexNormal(v2i, norm);
  134.             surf.setVertexNormal(v3i, norm);
  135.         }
  136.  
  137.         // place trees
  138.    
  139.         foreach(i; 0..surf.getVertexCount)
  140.         {
  141.             Vector3 v = surf.getVertex(i);
  142.             auto dist = v.length();
  143.            
  144.             Vector3 norm = surf.getVertexNormal(i);
  145.            
  146.             // place tree with chance depending on difference between ideal height and current vertex height
  147.             auto chance = 1.0 / (1.0 + pow(fabs(dist - vegetation_dist) * 10.0, 2.0) * 10000.0);
  148.             bool is_underwater = dist <= beach_dist;
  149.  
  150.             if (!is_underwater && uniform!"[]"(0.0f, 1.0f, rnd) < chance)
  151.                 tree_pairs.insertBack(PosNormal(v, norm));
  152.         }
  153.  
  154.         // commit the mesh
  155.         Ref!ArrayMesh mmesh = ArrayMesh._new();
  156.         surf.commitToSurface(mmesh);
  157.         getNode(gs!"planet/Planet").as!MeshInstance.mesh = mmesh;
  158.  
  159.         // --------  place trees in the scene -------------
  160.        
  161.         // get the tree mesh from tree.dae and intialize the multimesh, used for quickly drawing lots of trees
  162.         //auto tree = ResourcePreloader().getResource(gs!"res://tree.dae").as!PackedScene.instance();
  163.         Ref!PackedScene tree = ResourceLoader.load(gs!"res://tree.dae").as!PackedScene;
  164.         MeshInstance tree_mesh = tree.instance.getNode(gs!"tree").as!MeshInstance;
  165.         Ref!MultiMesh multimesh = getNode(gs!"planet/trees").as!MultiMeshInstance.multimesh;
  166.         multimesh.mesh = tree_mesh.mesh;
  167.         multimesh.instanceCount = tree_pairs.length;
  168.  
  169.         {
  170.             size_t i = 0;
  171.             foreach (immutable ref tree_pair; tree_pairs)
  172.             {      
  173.                 Vector3 pos = getNode(gs!"planet").as!Spatial.toGlobal(tree_pair.pos);
  174.                
  175.                 // orient the tree to the face normal and randomly rotate it along the normal
  176.                 Vector3 y = tree_pair.normal;
  177.                 Vector3 x = tree_pair.normal.cross(Vector3(0.0, 1.0, 0.0)).normalized(); // NOTE this will go wrong if the normal is exactly (0, 1, 0)
  178.                 Vector3 z = x.cross(y).normalized();
  179.                 Basis basis = Basis(x, y, z).rotated(y, uniform!"[]"(0.0f, 2.0f*PI, rnd))
  180.                     .scaled(Vector3(1.0, 1.0, 1.0) * uniform!"[]"(0.01f, 0.03f, rnd) / 2.0); // scale the tree randomly
  181.                
  182.                 // set the transform of the multimesh at this index
  183.                 multimesh.setInstanceTransform(i, Transform(basis, pos));
  184.                 ++i;
  185.             }
  186.         }
  187.  
  188.         // hide the progress bar
  189.         progress.hide();
  190.     }
  191.    
  192.     @Method _process(float delta)
  193.     {
  194.         // rotate cam
  195.         getNode(gs!"cam_root").as!Spatial.rotateY(delta / 3.0);
  196.     }
  197. }
  198.  
  199. struct PosNormal
  200. {
  201.     Vector3 pos;
  202.     Vector3 normal;
  203. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement