Skip to content

Instantly share code, notes, and snippets.

@averrin
Last active July 27, 2018 17:04
Show Gist options
  • Save averrin/226339e05f03a1a3682c4af376cceb56 to your computer and use it in GitHub Desktop.
Save averrin/226339e05f03a1a3682c4af376cceb56 to your computer and use it in GitHub Desktop.
main
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using UnityEngine;
using Zenject;
public class Main : MonoBehaviour
{
public bool StartWorld = true;
public World CurrentWorld;
[Header("Dependencies")]
public LPWAsset.LowPolyWaterScript water;
[Header("Size")]
public int DrawPerShot = 100;
public int MapWidth = 1000;
public int MapHeight = 1000;
public float WaterOffset = 5;
static IntPtr nativeLibraryPtr;
private int _jsonSize;
delegate int createMap(int size, int w, int h);
delegate string getRegion(StringBuilder sb, int length);
public float LandHeightMod = 50f;
public float MountainHeightMod = 50f;
private float _seaLevel = -999;
private bool _finalized = false;
[Inject]
private RegionsManager regionsManager;
[Inject]
private Camera mainCamera;
private void Update()
{
if (CurrentWorld != null && !_finalized)
{
if (regionsManager.MegaClusters.Count == 0 && CurrentWorld.megaClusters.Count != 0)
{
regionsManager.SetClusters(CurrentWorld);
}
CreateRegions();
}
foreach (var region in regionsManager.regions)
{
var distanceToCamera = Vector3.Distance(mainCamera.transform.position, region.verts[0]);
region.SetDistance(distanceToCamera);
}
}
void FinalizeWorld() {
Debug.Log("Finalize world");
regionsManager.Clusters.ForEach((mc) => mc.Combine());
_finalized = true;
}
void Awake()
{
if (!StartWorld) return;
if (nativeLibraryPtr != IntPtr.Zero) return;
nativeLibraryPtr = Native.LoadLibrary("generator");
if (nativeLibraryPtr == IntPtr.Zero)
{
Debug.LogError("Failed to load native library");
}
var th = new Thread(CreateMap);
th.Start();
}
void CreateMap() {
int seed = Math.Abs((int)System.DateTime.Now.Ticks);
_jsonSize = Native.Invoke<int, createMap>(nativeLibraryPtr, seed, MapWidth, MapHeight);
Debug.Log(_jsonSize);
StringBuilder sb = new StringBuilder(_jsonSize);
Native.Invoke<string, getRegion>(nativeLibraryPtr, sb, sb.Capacity);
CurrentWorld = JsonUtility.FromJson<World>(sb.ToString());
}
void CreateRegions()
{
int n = 0;
foreach (var region in CurrentWorld.regions) {
if (n >= DrawPerShot) {
break;
}
if (region.onScene) {
continue;
}
n++;
region.onScene = true;
regionsManager.Create(region).Paint();
}
if (CurrentWorld.regions.Count > 0 && CurrentWorld.regions.TrueForAll((r) => r.onScene))
{
FinalizeWorld();
var pos = water.transform.position;
water.transform.position = new Vector3(pos.x, regionsManager.GetSeaLevel() + WaterOffset, pos.z);
}
}
void OnApplicationQuit()
{
if (nativeLibraryPtr == IntPtr.Zero) return;
Debug.Log(Native.FreeLibrary(nativeLibraryPtr)
? "Native library successfully unloaded."
: "Native library could not be unloaded.");
}
}
using System.Collections.Generic;
using UnityEngine;
using Zenject;
public class RegionsManager {
[Inject]
public List<IRegionMesh> prefabs;
[Inject]
private Cluster _clusterPrefab;
[Inject(Id = "RegionsRoot")]
private Transform root;
public List<RegionMesh> regions = new List<RegionMesh> { };
public List<GameObject> MegaClusters = new List<GameObject> { };
public List<Cluster> Clusters = new List<Cluster> { };
public void SetClusters(World world) {
foreach (var c in world.clusters)
{
var cObject = GameObject.Instantiate(_clusterPrefab);
cObject.transform.parent = root;
cObject.name = c.biom;
Clusters.Add(cObject);
}
foreach (var mc in world.megaClusters)
{
Debug.Log(mc.name);
var mcObject = new GameObject();
mcObject.transform.parent = root;
mcObject.name = mc.name;
MegaClusters.Add(mcObject);
foreach (var c in mc.clusters)
{
Clusters[c].transform.parent = mcObject.transform;
}
}
var u = new GameObject();
u.transform.parent = root;
u.name = "Unknown";
MegaClusters.Add(u);
foreach (var c in Clusters)
{
if (c.transform.parent == root)
{
c.transform.parent = u.transform;
}
}
}
public RegionMesh GetPrefab(string biom) {
return prefabs.Find((IRegionMesh prefab) => prefab.getBioms().Contains(biom)) as RegionMesh;
}
public float GetSeaLevel() {
if (regions == null || regions.Count == 0) {
return 10;
}
var sea = regions.FindAll((RegionMesh region) => !region.region.isLand);
float h = -999;
foreach (var region in sea)
{
foreach (var point in region.region.points)
{
if (point.height > h) {
h = point.height;
}
}
}
return h;
}
public RegionMesh Create(Region region) {
var prefab = GetPrefab(region.biom);
if (prefab == null) {
Debug.Log(region.biom);
prefab = prefabs[0] as RegionMesh;
}
var regionMesh = GameObject.Instantiate(prefab);
regionMesh.transform.SetParent(Clusters[region.cluster].transform, true);
regionMesh.gameObject.layer = 9;
regionMesh.region = region;
regionMesh.name = string.Format("{0} [{1}, {2}]", region.biom, region.site.x, region.site.y);
regions.Add(regionMesh);
return regionMesh;
}
}
using System;
using System.Collections.Generic;
[Serializable]
public class Point
{
public float x;
public float y;
public float height;
}
[Serializable]
public class Region
{
public List<Point> points;
public Point site;
public string biom;
public bool isLand;
public bool onScene = false;
public int megaCluster;
public int cluster;
}
[Serializable]
public class RegionCluster
{
public string name;
public int id;
public List<int> clusters;
public int regions;
public string biom;
}
[Serializable]
public class World
{
public List<Region> regions;
public List<RegionCluster> megaClusters;
public List<RegionCluster> clusters;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment