public static void calculateMountainDistance(int seed, DualMesh mesh, int[] peak_t, Float spacing, Float jaggedness, NativeArray <Float> t_distance) { int randIndex = 0; for (var i = 0; i < t_distance.Length; ++i) { t_distance[i] = -1f; } var queue_t = new List <int>(peak_t); for (var i = 0; i < queue_t.Count; i++) { var current_t = queue_t[i]; for (var j = 0; j < 3; j++) { var s = 3 * current_t + j; var neighbor_t = mesh.s_outer_t(s); if (t_distance[neighbor_t] == -1f) { var rf1 = Rander.randFloat(seed, randIndex++); var rf2 = Rander.randFloat(seed, randIndex++); var increment = spacing * (1 + jaggedness * (rf1 - rf2)); t_distance[neighbor_t] = t_distance[current_t] + increment; queue_t.Add(neighbor_t); } } } }
/********************************************************************** * Plates */ static HashSet <int> pickRandomRegions(DualMesh mesh, int N, int seed) { var randInt = Rander.makeRandInt(seed); var numRegions = mesh.numRegions; var chosen_r = new HashSet <int>(); while (chosen_r.Count < N && chosen_r.Count < numRegions) { chosen_r.Add(randInt(numRegions)); } return(chosen_r); }
private static void assignTriangleCenters(DualMesh mesh, NativeArray <double> r_xyz, NativeArray <double> t_xyz) { var numTriangles = mesh.numTriangles; var _r_xyz = (double *)NativeArrayUnsafeUtility.GetUnsafePtr(r_xyz); var _t_xyz = (double *)NativeArrayUnsafeUtility.GetUnsafePtr(t_xyz); Action <int> action = t => { int a = mesh.s_begin_r(3 * t + 0), b = mesh.s_begin_r(3 * t + 1), c = mesh.s_begin_r(3 * t + 2); CentroidOfTriangle(_r_xyz, a, b, c, _t_xyz, t); }; //for (var t = 0; t < numTriangles; t++) action(t); Parallel.For(0, numTriangles, action); }
public _MapJobs(DualMesh.Graph graph, short[] peaks_index, Float spacing) { mesh = new DualMesh(graph); riverTex = RiverTexture.createDefault(); peaks_t = createPeaks(peaks_index, mesh.numBoundaryRegions); config = new Config() { seed = -1, island = -1, mountain_jagged = -1, wind_angle_deg = -1, }; elevation = new NativeArray <Float>(CANVAS_SIZE * CANVAS_SIZE, Allocator.Persistent); preNoise = new PreNoise(); t_elevation = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); t_mountain_distance = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); r_elevation = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); r_wind_sort = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); wind_order_r = new NativeArray <int>(mesh.numRegions, Allocator.Persistent); r_rainfall = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); r_humidity = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); t_moisture = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); order_t = new NativeArray <int>(mesh.numTriangles + 1, Allocator.Persistent); t_downslope_s = new NativeArray <int>(mesh.numTriangles, Allocator.Persistent); t_flow = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); s_flow = new NativeArray <Float>(mesh.numSides, Allocator.Persistent); rivers_v3 = new NativeArray <Vector3>(mesh.numSides, Allocator.Persistent); rivers_uv = new NativeArray <Vector2>(mesh.numSides, Allocator.Persistent); land_v3 = new NativeArray <Vector3>(mesh.numRegions + mesh.numTriangles, Allocator.Persistent); land_uv = new NativeArray <Vector2>(mesh.numRegions + mesh.numTriangles, Allocator.Persistent); land_i = new NativeArray <int>(mesh.numSolidSides * 3, Allocator.Persistent); }
/* Distance from any point in seeds_r to all other points, but * don't go past any point in stop_r */ static Float[] assignDistanceField(DualMesh mesh, HashSet <int> seeds_r, HashSet <int> stop_r, int seed = 123) { var randInt = Rander.makeRandInt(seed); var numRegions = mesh.numRegions; var r_distance = new Float[numRegions]; for (int i = 0; i < numRegions; ++i) { r_distance[i] = Float.PositiveInfinity; } var queue = new List <int>(); foreach (var r in seeds_r) { queue.Add(r); r_distance[r] = 0; } /* Random search adapted from breadth first search */ for (var queue_out = 0; queue_out < queue.Count; queue_out++) { var pos = queue_out + randInt(queue.Count - queue_out); var current_r = queue[pos]; queue[pos] = queue[queue_out]; var out_r = mesh.r_circulate_r(current_r); foreach (var neighbor_r in out_r) { if (r_distance[neighbor_r] == Float.PositiveInfinity && !stop_r.Contains(neighbor_r)) { r_distance[neighbor_r] = r_distance[current_r] + 1; queue.Add(neighbor_r); } } } return(r_distance); // TODO: possible enhancement: keep track of which seed is closest // to this point, so that we can assign variable mountain/ocean // elevation to each seed instead of them always being +1/-1 }
void generateMesh(int N, int P, Float jitter, int seed) { if (mesh != null) { disposeMesh(); } // 噪音只初始化一次就好 if (simplex == null) { simplex = new SimplexNoise(seed); } DualMesh m; List <double> d; DualMesh.makeSphere(N, jitter, seed, out m, out d); mesh = m; r_xyz = new NativeArray <double>(d.ToArray(), Allocator.Persistent); t_xyz = new NativeArray <double>(mesh.numSides, Allocator.Persistent); assignTriangleCenters(mesh, r_xyz, t_xyz); r_elevation = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); r_moisture = new NativeArray <Float>(mesh.numRegions, Allocator.Persistent); t_elevation = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); t_moisture = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); t_downflow_s = new NativeArray <int>(mesh.numTriangles, Allocator.Persistent); // order_t[0] 保存个数 order_t = new NativeArray <int>(mesh.numTriangles + 1, Allocator.Persistent); t_flow = new NativeArray <Float>(mesh.numTriangles, Allocator.Persistent); // numSides = numTriangles * 3 s_flow = new NativeArray <Float>(mesh.numSides, Allocator.Persistent); r_plate = new NativeArray <int>(mesh.numRegions, Allocator.Persistent); plate_vec = new NativeArray <Vector3>(mesh.numRegions, Allocator.Persistent); Debug.Log($"generateMesh N:{N} P:{P} jitter:{jitter} seed:{seed} region:{mesh.numRegions} tri:{mesh.numTriangles}"); }
public static void makeSphere(int N, double jitter, int seed, out DualMesh mesh, out List <double> d) { var latlong = generateFibonacciSphere(N, jitter, seed); //DebugHelper.SaveArray("generateFibonacciSphere.txt", latlong); var r_xyz = new List <double>(); for (var r = 0; r < latlong.Count / 2; r++) { pushCartesianFromSpherical(r_xyz, latlong[2 * r], latlong[2 * r + 1]); } var r_xy = stereographicProjection(r_xyz); //DebugHelper.SaveArray("stereographicProjection.txt", r_xy); var delaunay = new Delaunator(r_xy.ToArray()); /* TODO: rotate an existing point into this spot instead of creating one */ r_xyz.AddRange(new double[] { 0, 0, 1 }); addSouthPoleToMesh(r_xyz.Count / 3 - 1, delaunay); var dummy_r_vertex = new Float2[N + 1]; dummy_r_vertex[0] = new Float2(0, 0); for (var i = 1; i < N + 1; i++) { dummy_r_vertex[i] = dummy_r_vertex[0]; } mesh = new DualMesh(new Graph() { numBoundaryRegions = 0, numSolidSides = delaunay.triangles.Length, _r_vertex = dummy_r_vertex, _triangles = delaunay.triangles, _halfedges = delaunay.halfedges, }); d = r_xyz; }
static HashSet <int> generatePlates( DualMesh mesh, NativeArray <double> r_xyz, int P, int N, int seed, /** output */ NativeArray <int> r_plate, NativeArray <Vector3> plate_vec ) { //r_plate.fill(-1); for (var i = 0; i < r_plate.Length; ++i) { r_plate[i] = -1; } var plate_r = pickRandomRegions(mesh, Math.Min(P, N), seed); var queue = new List <int>(plate_r); foreach (var r in queue) { r_plate[r] = r; } var randInt = Rander.makeRandInt(seed); /* In Breadth First Search (BFS) the queue will be all elements in * queue[queue_out ... queue.length-1]. Pushing onto the queue * adds an element to the end, increasing queue.length. Popping * from the queue removes an element from the beginning by * increasing queue_out. * * To add variety, use a random search instead of a breadth first * search. The frontier of elements to be expanded is still * queue[queue_out ... queue.length-1], but pick a random element * to pop instead of the earliest one. Do this by swapping * queue[pos] and queue[queue_out]. */ for (var queue_out = 0; queue_out < queue.Count; queue_out++) { var pos = queue_out + randInt(queue.Count - queue_out); var current_r = queue[pos]; queue[pos] = queue[queue_out]; var out_r = mesh.r_circulate_r(current_r); foreach (var neighbor_r in out_r) { if (r_plate[neighbor_r] == -1) { r_plate[neighbor_r] = r_plate[current_r]; queue.Add(neighbor_r); } } } //DebugHelper.SaveArray("plate_r.txt", plate_r); //DebugHelper.SaveArray("queue.txt", queue); Vector3 xyz(int i) { return(new Vector3((float)r_xyz[i + 0], (float)r_xyz[i + 1], (float)r_xyz[i + 2])); } // Assign a random movement vector for each plate foreach (var center_r in plate_r) { var neighbor_r = mesh.r_circulate_r(center_r)[0]; Vector3 p0 = xyz(3 * center_r), p1 = xyz(3 * neighbor_r); plate_vec[center_r] = (p1 - p0).normalized; //Debug.Log($"{center_r}, {neighbor_r} {plate_vec[center_r].x},{plate_vec[center_r].y},{plate_vec[center_r].z}"); } return(plate_r); }