Question by
EuanHollidge · Mar 17, 2017 at 11:01 PM ·
c#positionproceduralpositioning
Spawn Procedural Planet at parent's position
To be honest I'm not sure what the hell is going on. I'm trying to have it so that my code spawns a procedural planet (using voxel chunks) at the 0, 0, 0 of the parent. This isn't happening. Here's the code
World
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using SimpleThreadPool;
using System;
public class chunkSystem
{
public byte[,,] chunkMap;
public Vector2 pos;
}
public class World : MonoBehaviour
{
public Biome[] biomes;
public static World cWorld;
public List<Chunk> chunkMap = new List<Chunk>();
public int numChunk = -1;
public int chunkWidth = 20, chunkHeight = 20, seed = 0;
public float viewRange = 30;
public int planetSides = 10;
public Chunk chunkPrefab;
public GameObject player;
public GameObject planetCore;
public GameObject Ocean;
public Vector3 pos;
public ThreadPool tp = new ThreadPool(4);
public bool reCalculateMesh = false;
int worldBound = 3;
public bool refresh = false;
bool startUp = true;
//Sides
#region
GameObject sideTop;
GameObject sideFront;
GameObject sideBack;
GameObject sideLeft;
GameObject sideRight;
GameObject sideBottom;
bool allSides = false;
bool st = false;
bool sf = false;
bool sb = false;
bool sl = false;
bool sr = false;
bool sb2 = false;
bool st2 = false;
bool sf2 = false;
bool sbb = false;
bool sl2 = false;
bool sr2 = false;
bool sb3 = false;
bool loadedPlanet = false;
bool loadedf = false;
bool loadedr = false;
bool loadedl = false;
bool loadedb = false;
bool loadedt = false;
#endregion
void Start()
{
worldBound *= chunkWidth;
cWorld = this;
if (seed == 0)
{
seed = UnityEngine.Random.Range(0, int.MaxValue);
}
//World
gameObject.AddComponent<SideCounter>();
//Planet Core
Instantiate(planetCore, this.transform);
planetCore.transform.position = transform.position -new Vector3(-20, 85, -20);
planetCore.name = "Planet Core";
planetCore.transform.localScale = new Vector3(30, 30, 30);
//Ocean
Instantiate(Ocean, this.transform);
Ocean.transform.position = transform.position + new Vector3(14, -87.7f, 12.2f);
Ocean.name = "Ocean";
Ocean.transform.localScale = new Vector3(120, 120, 120);
#region
sideTop = new GameObject();
sideTop.name = "Side Top";
sideTop.transform.SetParent(this.transform);
sideTop.transform.position = transform.position;
sideTop.AddComponent<SideCounter>();
sideBottom = new GameObject();
sideBottom.name = "Side Bottom";
sideBottom.transform.SetParent(this.transform);
sideBottom.transform.position = transform.position + new Vector3(0, 0, (chunkWidth * 14) + 2 / (chunkWidth * 7));
sideBottom.AddComponent<SideCounter>();
sideBack = new GameObject();
sideBack.transform.position = transform.position + new Vector3(0, 0, -(chunkWidth * 7) - 2 / (chunkWidth * 7));
sideBack.transform.SetParent(this.transform);
sideBack.name = "Side Back";
sideBack.AddComponent<SideCounter>();
sideFront = new GameObject();
sideFront.name = "Side Front";
sideFront.transform.SetParent(this.transform);
sideFront.transform.position = transform.position + new Vector3(0, 0, (chunkWidth * 7) + 2 / (chunkWidth * 7));
sideFront.AddComponent<SideCounter>();
sideRight = new GameObject();
sideRight.name = "Side Right";
sideRight.transform.SetParent(this.transform);
sideRight.transform.position = transform.position + new Vector3((chunkWidth * 7) + 2 / (chunkWidth * 7), 0, 0);
sideRight.AddComponent<SideCounter>();
sideLeft = new GameObject();
sideLeft.name = "Side Left";
sideLeft.transform.SetParent(this.transform);
sideLeft.transform.position = transform.position + new Vector3(-(chunkWidth * 7) - 2 / (chunkWidth * 7), 0, 0);
sideLeft.AddComponent<SideCounter>();
#endregion
}
// Update is called once per frame
void Update()
{
calculateGeneratedSides();
checkSideFlipped();
loadChunks();
if(startUp == true)
{
startUp = false;
}
if (refresh == true)
{
refresh = false;
reCalculateMesh = true;
Debug.Log(chunkMap.Count);
}
if (reCalculateMesh == true)
{
for (int a = 0; a < this.transform.childCount; a++)
{
if (this.transform.GetChild(a).name != "Planet Core")
{
for (int i = 0; i < this.transform.GetChild(a).transform.childCount; i++)
{
if (this.transform.GetChild(a).transform.GetChild(i).GetComponent<Chunk>() != null)
{
this.transform.GetChild(a).transform.GetChild(i).GetComponent<Chunk>().createVisualMesh2();
}
}
}
}
reCalculateMesh = false;
}
}
private void loadChunks()
{
if (loadedPlanet == false)
{
//Top
spawnChunk(sideTop, 0);
//Front
spawnChunk(sideFront, 0);
//Right
spawnChunk(sideRight, 0);
//Left
spawnChunk(sideLeft, 0);
//Back
spawnChunk(sideBack, 0);
//Bottom
spawnChunk(sideBottom, 90);
loadedPlanet = true;
}
}
private void checkSideFlipped()
{
if (sf == true && sf2 == false)
{
sideFront.transform.Rotate(new Vector3(90, 0, 0));
sideFront.transform.position -= new Vector3(0, worldBound, worldBound);
sf2 = true;
}
if (sb == true && sbb == false)
{
sideBack.transform.Rotate(new Vector3(-90, 0, 0));
sideBack.transform.position += new Vector3(0, -worldBound - chunkWidth, worldBound + chunkWidth);
sbb = true;
}
if (sl == true && sl2 == false)
{
sideLeft.transform.Rotate(new Vector3(0, 0, 90));
sideLeft.transform.position += new Vector3(worldBound + chunkWidth, -worldBound - chunkWidth, 0);
sl2 = true;
}
if (sr == true && sr2 == false)
{
sideRight.transform.Rotate(new Vector3(0, 0, -90));
sideRight.transform.position -= new Vector3(worldBound, worldBound, 0);
sr2 = true;
}
if (sb2 == true && sb3 == false)
{
sideBottom.transform.Rotate(180, 0, 0);
sideBottom.transform.position -= new Vector3(0, (worldBound * 2) + chunkWidth, 2 * ((worldBound * 2) + chunkWidth) - chunkWidth);
sb3 = true;
}
}
private void calculateGeneratedSides()
{
if (allSides == false)
{
int chunksPerSide = (((worldBound / chunkWidth) * 2) + 1) * (((worldBound / chunkWidth) * 2) + 1);
if (st == false)
{
if (sideTop.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideTop.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
st = true;
}
}
}
if (sf == false)
{
if (sideFront.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideFront.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
sf = true;
}
}
}
if (sb == false)
{
if (sideBack.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideBack.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
sb = true;
}
}
}
if (sl == false)
{
if (sideLeft.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideLeft.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
sl = true;
}
}
}
if (sr == false)
{
if (sideRight.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideRight.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
sr = true;
}
}
}
if (sb2 == false)
{
if (sideBottom.transform.childCount == chunksPerSide)
{
int a = 0;
for (int i = 0; i < chunksPerSide; i++)
{
if (sideBottom.transform.GetChild(i).GetComponent<Chunk>().generated)
{
a++;
}
}
if (a == chunksPerSide - 1)
{
sb2 = true;
}
}
}
if (sb2 == true && st == true && sb == true && sl == true && sr == true && sf == true)
{
allSides = true;
}
}
}
void chunkRemover()
{
for (int a = 0; a < Chunk.chunks.Count; a++)
{
if (Chunk.chunks[a].keepChunk == false)
{
Vector3 chunkPos = Chunk.chunks[a].transform.position;
Vector3 var = chunkPos - player.transform.position;
var.y = 0;
if (var.magnitude < viewRange + chunkWidth) { continue; };
Destroy(Chunk.chunks[a]);
}
}
}
void removeChunk(Chunk chunk)
{
chunk.gameObject.transform.position = moveChunk(chunk.gameObject.transform.position, true);
chunk.gameObject.transform.localScale = scaleChunk(chunk.gameObject.transform.localScale, true);
}
void reinstateChunk(Chunk chunk)
{
chunk.gameObject.transform.position = moveChunk(chunk.gameObject.transform.position, false);
chunk.gameObject.transform.localScale = scaleChunk(chunk.gameObject.transform.localScale, false);
}
Vector3 moveChunk(Vector3 chunk, bool upOrDown)
{
Vector3 finalPos = new Vector3();
if (upOrDown == true)
{
finalPos.x = chunk.x / chunkWidth;
finalPos.y = chunk.y * -3000;
finalPos.z = chunk.z / chunkWidth;
}
else
{
finalPos.x = chunk.x * chunkWidth;
finalPos.y = chunk.y / -3000;
finalPos.z = chunk.z * chunkWidth;
}
return finalPos;
}
Vector3 scaleChunk(Vector3 chunk, bool shrink)
{
Vector3 finalScale = new Vector3();
if (shrink == true)
{
finalScale.x /= chunkWidth;
finalScale.y /= chunkHeight;
finalScale.z /= chunkWidth;
}
else
{
finalScale.x *= chunkWidth;
finalScale.y *= chunkHeight;
finalScale.z *= chunkWidth;
}
return finalScale;
}
void enableDisableChunk(GameObject chunk, bool enableDisable)
{
}
void spawnChunk(GameObject side, int rot)
{
int a = 1;
for (float x = side.transform.localPosition.x - (chunkWidth * worldBound); x < side.transform.localPosition.x + (chunkWidth * worldBound); x += chunkWidth)
{
for (float z = side.transform.localPosition.z - (chunkWidth * worldBound); z < side.transform.localPosition.z + (chunkWidth * worldBound); z += chunkWidth)
{
Vector3 pos = new Vector3(x, 0, z);
if (pos.x <= worldBound && pos.z <= worldBound && pos.x >= -worldBound && pos.z >= -worldBound)
{
Chunk chunk = Chunk.findChunk(pos);
if (chunk != null) { continue; }
chunk = (Chunk)Instantiate(chunkPrefab, side.transform.localPosition + pos, Quaternion.identity);
int onSide = checkIfOnSide(a, 48);
#region
if (onSide == 1)
{
chunk.onEdge1 = true;
}
else if (onSide == 2)
{
chunk.onEdge2 = true;
}
else if (onSide == 3)
{
chunk.onEdge3 = true;
}
else if (onSide == 4)
{
chunk.onEdge4 = true;
}
else if (onSide == 5)
{
chunk.onEdge1 = true;
chunk.onEdge2 = true;
}
else if (onSide == 6)
{
chunk.onEdge1 = true;
chunk.onEdge4 = true;
}
else if (onSide == 7)
{
chunk.onEdge3 = true;
chunk.onEdge2 = true;
}
else if (onSide == 8)
{
chunk.onEdge4 = true;
chunk.onEdge3 = true;
}
#endregion
chunk.keepChunk = false;
chunk.isCore = false;
chunk.tp = tp;
chunk.transform.SetParent(side.transform); a++;
}
}
}
return;
}
private int checkIfOnSide(int currentChunk, int totalChunks)
{
int sqr = (int)Mathf.Sqrt(totalChunks + 1);
int sqr2 = 2 * sqr;
int sqr3 = 3 * sqr;
int sqr4 = 4 * sqr;
int sqr5 = 5 * sqr;
int sqr6 = 6 * sqr;
if (currentChunk < sqr && currentChunk != 1)
{
return 1;
}
else if (currentChunk == sqr2 || currentChunk == sqr3 || currentChunk == sqr4 || currentChunk == sqr5 || currentChunk == sqr6)
{
return 2;
}
else if (currentChunk > sqr6 + 1 && currentChunk <= totalChunks)
{
return 3;
}
else if (currentChunk == sqr2 + 1 || currentChunk == sqr3 + 1 || currentChunk == sqr4 + 1 || currentChunk == sqr5 + 1 || currentChunk == sqr + 1)
{
return 4;
}
else if (currentChunk == sqr)
{
return 5;
}
else if (currentChunk == 1)
{
return 6;
}
else if (currentChunk == totalChunks + 1)
{
return 7;
}
else if (currentChunk == sqr6 + 1)
{
return 8;
}
else
{
return 0;
}
}
bool checkSavedChunks(float x, float z)
{
Vector2 pos = new Vector2(x / chunkWidth, z / chunkWidth);
for (int a = 0; a < chunkMap.Count; a++)
{
Vector2 pos2 = new Vector2(chunkMap[a].transform.position.x / chunkWidth, chunkMap[a].transform.position.z / chunkWidth);
if (pos2 == pos)
{
numChunk = a;
return true;
}
}
return false;
}
IEnumerator ChunkSpawner()
{
for (float x = player.transform.position.x - viewRange; x < player.transform.position.x + viewRange; x += chunkWidth)
{
for (float z = player.transform.position.z - viewRange; z < player.transform.position.z + viewRange; z += chunkWidth)
{
Vector3 pos = new Vector3(x, 0, z);
pos.x = Mathf.Floor(pos.x / (float)chunkWidth) * chunkWidth;
pos.z = Mathf.Floor(pos.z / (float)chunkWidth) * chunkWidth;
yield return null;
Chunk chunk = Chunk.findChunk(pos);
yield return null;
if (chunk != null) continue;
yield return null;
chunk = (Chunk)Instantiate(chunkPrefab, pos, Quaternion.identity);
yield return 1f;
chunk.transform.SetParent(this.transform);
}
yield return null;
}
yield return null;
}
public static Biome getIdealBiome(float moisture, float rockiness)
{
float bestBid = 0;
Biome biome = cWorld.biomes[0];
for (int a = 0; a < cWorld.biomes.Length; a++)
{
float bid = cWorld.biomes[a].Bid(moisture, rockiness);
if (bid > bestBid)
{
bestBid = bid;
biome = cWorld.biomes[a];
}
}
return biome;
}
}
Chunk
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using SimplexNoise;
using System.Runtime.InteropServices;
using System.Threading;
using SimpleThreadPool;
public enum Blocks
{
Void,
Grass,
Stone,
Dirt,
IronOre,
Sand,
Bedrock
}
[StructLayout(LayoutKind.Explicit)]
public struct FloatIntUnion
{
[FieldOffset(0)]
public float f;
[FieldOffset(0)]
public int tmp;
}
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshCollider))]
[RequireComponent(typeof(MeshFilter))]
public class Chunk : MonoBehaviour
{
public static List<Chunk> chunksWaiting = new List<Chunk>();
public static List<Chunk> chunks = new List<Chunk>();
public static float chunkWidth
{
get { return World.cWorld.chunkWidth; }
}
public static float chunkHeight
{
get { return World.cWorld.chunkHeight; }
}
public Vector2 worldPos;
public byte[,,] map;
public Mesh visualMesh;
public string f;
public bool keepChunk;
public bool isCore = false;
public bool loaded = false;
private static byte tempBlock;
protected MeshRenderer meshRenderer;
protected MeshCollider meshCollider;
protected MeshFilter meshFilter;
private static string BiomeName;
private static bool grassEnabled = true;
private static bool biomeDetailsSet = false;
protected bool initialized = false;
public static NoiseTest.OpenSimplexNoise os = new NoiseTest.OpenSimplexNoise();
public SimpleThreadPool.ThreadPool tp;
public bool onEdge1 = false;
public bool onEdge2 = false;
public bool onEdge3 = false;
public bool onEdge4 = false;
public Vector3 pubPos;
public bool worldSource = false;
public bool generated = false;
static Vector3 grain0Offset;
static Vector3 grain1Offset;
static Vector3 grain2Offset;
// Use this for initialization
void Start()
{
if (isCore == false)
{
Random.seed = World.cWorld.seed;
grain0Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
grain1Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
grain2Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
chunks.Add(this);
meshRenderer = GetComponent<MeshRenderer>();
meshCollider = GetComponent<MeshCollider>();
meshFilter = GetComponent<MeshFilter>();
chunksWaiting.Add(this);
if (chunksWaiting[0] == this)
{
StartCoroutine(calculateWorldMap());
}
}
}
public static byte getPossibleByte(Vector3 pos)
{
return calculateByte2(pos, grain0Offset, grain1Offset, grain2Offset);
}
void OnDestroy()
{
chunks.Remove(this);
}
public void saveChunk()
{
World.cWorld.chunkMap.Add(this);
}
public chunkSystem makeChunkSystem(byte[,,] map, Vector3 pos)
{
chunkSystem cs = new chunkSystem();
cs.chunkMap = map;
cs.pos = new Vector2(pos.x / chunkWidth, pos.z / chunkWidth);
return cs;
}
public static byte calculateByte2(Vector3 pos, Vector3 offset1, Vector3 offset2, Vector3 offset3)
{
float moisture = calculateNoise(pos, offset2, 0.003f);
float rockiness = calculateNoise(pos, offset2, 0.002f);
Biome biome = World.getIdealBiome(moisture, rockiness);
if (biome.grassEnabled == false)
{
grassEnabled = false;
}
float heightBase = biome.minHeight;
float maxHeight = biome.maxHeight;
float heightSwing = maxHeight - heightBase;
float blobValue = calculateNoise(pos, offset2, 0.01f);
float mountainValue = calculateNoise(pos, offset1, 0.01f);
mountainValue += biome.mountainPowerBonus;
mountainValue = Mathf.Pow(mountainValue, 0.5f * biome.mountainPower);
//if (mountainValue < 0) mountainValue = 0;
byte block = biome.getBlock(Mathf.FloorToInt(pos.y), mountainValue, blobValue);
mountainValue *= heightSwing;
mountainValue += heightBase;
mountainValue += (blobValue * 10) - 5f;
if (mountainValue >= pos.y)
{
return block;
}
return 0;
}
public static byte calculateByte(Vector3 pos, Vector3 offset1, Vector3 offset2, Vector3 offset3)
{
float moisture = calculateNoise(pos, offset2, 0.003f);
float rockiness = calculateNoise(pos, offset2, 0.002f);
Biome biome = World.getIdealBiome(moisture, rockiness);
float clusterValue = calculateNoise(pos, offset2, 0.0001f);
if (biomeDetailsSet == false)
{
BiomeName = biome.name;
grassEnabled = biome.grassEnabled;
biomeDetailsSet = true;
}
float heightBase = biome.minHeight;
float maxHeight = biome.maxHeight;
float heightSwing = maxHeight - heightBase;
float blobValue = calculateNoise(pos, offset2, 0.01f);
float mountainValue = calculateNoise(pos, offset1, 0.01f);
mountainValue += biome.mountainPowerBonus;
mountainValue = Mathf.Pow(mountainValue, 0.5f * biome.mountainPower);
//if (mountainValue < 0) mountainValue = 0;
byte block = biome.getBlock(Mathf.FloorToInt(pos.y), mountainValue, blobValue);
mountainValue *= heightSwing;
mountainValue += heightBase;
mountainValue += (blobValue * 10) - 5f;
if (mountainValue >= pos.y)
{
return block;
}
return 0;
}
public static double Pow(double a, double b)
{
int tmp = (int)(System.BitConverter.DoubleToInt64Bits(a) >> 32);
int tmp2 = (int)(b * (tmp - 1072632447) + 1072632447);
return System.BitConverter.Int64BitsToDouble(((long)tmp2) << 32);
}
public static float Sqrt2(float z)
{
if (z == 0) return 0;
FloatIntUnion u;
u.tmp = 0;
float xhalf = 0.5f * z;
u.f = z;
u.tmp = 0x5f375a86 - (u.tmp >> 1);
u.f = u.f * (1.5f - xhalf * u.f * u.f);
return u.f * z;
}
public virtual IEnumerator calculateWorldMap()
{
map = new byte[(byte)chunkWidth, (byte)chunkHeight, (byte)chunkWidth];
Random.seed = World.cWorld.seed;
Vector3 grain0Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
Vector3 grain1Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
Vector3 grain2Offset = new Vector3(Random.value * 10000, Random.value * 10000, Random.value * 10000);
Vector3 pos = transform.position;
pubPos = pos;
bool threadFinsihed = false;
tp.QueueTask(() =>
{
//Thread t = new Thread(() => {
if (loaded == false)
{
for (int x = 0; x < chunkWidth; x++)
{
for (int y = 0; y < chunkHeight; y++)
{
for (int z = 0; z < chunkWidth; z++)
{
if (y == 0)
{
map[x, y, z] = 6;
}
else
{
map[x, y, z] = calculateByte(new Vector3(x, y, z) + pos, grain0Offset, grain1Offset, grain2Offset);
if (grassEnabled)
{
if (map[x, y, z] == 0 && map[x, y - 1, z] != 1 && map[x, y - 1, z] != 0 && map[x, y - 1, z] != 5 && map[x, y + 1, z] == 0 && map[x, y - 1, z] != 2)
{
map[x, y, z] = 1;
}
}
}
}
}
}
}
worldSource = true;
threadFinsihed = true;
});
initialized = true;
yield return new WaitUntil(() => threadFinsihed == true);
StartCoroutine(createVisualMesh());
chunksWaiting.Remove(this);
if (chunksWaiting.Count > 0)
{
StartCoroutine(chunksWaiting[0].calculateWorldMap());
}
generated = true;
yield return 0;
}
public static float calculateNoise(Vector3 pos, Vector3 offset, float scale)
{
float x = ((pos.x + offset.x) * scale);
float y = ((pos.y + offset.y) * scale);
float z = ((pos.z + offset.z) * scale);
float noiseX = x < 0 ? -x : x; //Mathf.Abs((pos.x + offset.x) * scale);
float noiseY = y < 0 ? -y : y;//Mathf.Abs((pos.y + offset.y) * scale);
float noiseZ = z < 0 ? -z : z;//Mathf.Abs((pos.z + offset.z) * scale);
return Noise.Generate(noiseX, noiseY, noiseZ);
//return (float)os.Evaluate(noiseX, noiseY, noiseZ);
}
public virtual IEnumerator createVisualMesh()
{
visualMesh = new Mesh();
List<Vector3> verts = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> tris = new List<int>();
for (byte x = 0; x < chunkWidth; x++)
{
for (byte y = 0; y < chunkHeight; y++)
{
for (byte z = 0; z < chunkWidth; z++)
{
if (map[x, y, z] == 0)
{
continue;
}
byte block = map[x, y, z];
//Left Right
if (isTransparent(x - 1, y, z))
buildFace(block, new Vector3(x, y, z), Vector3.up, Vector3.forward, false, verts, uvs, tris);
if (isTransparent(x + 1, y, z))
buildFace(block, new Vector3(x + 1, y, z), Vector3.up, Vector3.forward, true, verts, uvs, tris);
//Bottom Top
if (isTransparent(x, y - 1, z))
buildFace(block, new Vector3(x, y, z), Vector3.forward, Vector3.right, false, verts, uvs, tris);
if (isTransparent(x, y + 1, z))
buildFace(block, new Vector3(x, y + 1, z), Vector3.forward, Vector3.right, true, verts, uvs, tris);
//Back Forward
if (isTransparent(x, y, z - 1))
buildFace(block, new Vector3(x, y, z), Vector3.up, Vector3.right, true, verts, uvs, tris);
if (isTransparent(x, y, z + 1))
buildFace(block, new Vector3(x, y, z + 1), Vector3.up, Vector3.right, false, verts, uvs, tris);
}
}
yield return null;
}
yield return null;
visualMesh.vertices = verts.ToArray();
visualMesh.uv = uvs.ToArray();
visualMesh.triangles = tris.ToArray();
visualMesh.RecalculateBounds();
visualMesh.RecalculateNormals();
yield return null;
meshFilter.mesh = visualMesh;
meshCollider.sharedMesh = visualMesh;
}
public virtual IEnumerator createVisualMesh2()
{
visualMesh = new Mesh();
List<Vector3> verts = new List<Vector3>();
List<Vector2> uvs = new List<Vector2>();
List<int> tris = new List<int>();
for (byte x = 0; x < chunkWidth; x++)
{
for (byte y = 0; y < chunkHeight; y++)
{
for (byte z = 0; z < chunkWidth; z++)
{
if (map[x, y, z] == 0)
{
continue;
}
byte block = map[x, y, z];
//Left Right
if (isTransparent(x - 1, y, z))
buildFace(block, new Vector3(x, y, z), Vector3.up, Vector3.forward, false, verts, uvs, tris);
if (isTransparent(x + 1, y, z))
buildFace(block, new Vector3(x + 1, y, z), Vector3.up, Vector3.forward, true, verts, uvs, tris);
//Bottom Top
if (isTransparent(x, y - 1, z))
buildFace(block, new Vector3(x, y, z), Vector3.forward, Vector3.right, false, verts, uvs, tris);
if (isTransparent(x, y + 1, z))
buildFace(block, new Vector3(x, y + 1, z), Vector3.forward, Vector3.right, true, verts, uvs, tris);
//Back Forward
if (isTransparent(x, y, z - 1))
buildFace(block, new Vector3(x, y, z), Vector3.up, Vector3.right, true, verts, uvs, tris);
if (isTransparent(x, y, z + 1))
buildFace(block, new Vector3(x, y, z + 1), Vector3.up, Vector3.right, false, verts, uvs, tris);
}
}
}
yield return null;
visualMesh.vertices = verts.ToArray();
visualMesh.uv = uvs.ToArray();
visualMesh.triangles = tris.ToArray();
visualMesh.RecalculateBounds();
visualMesh.RecalculateNormals();
meshFilter.mesh = visualMesh;
meshCollider.sharedMesh = visualMesh;
}
public virtual void buildFace(byte block, Vector3 corner, Vector3 up, Vector3 right, bool reversed, List<Vector3> verts, List<Vector2> uvs, List<int> tris)
{
int index = verts.Count;
Vector2 uvCorner = getTexturePos(block);
verts.Add(corner);
verts.Add(corner + up);
verts.Add(corner + up + right);
verts.Add(corner + right);
Vector2 uvWidth = new Vector2(0.25f, 0.25f);
uvs.Add(uvCorner);
uvs.Add(new Vector2(uvCorner.x, uvCorner.y + uvWidth.y));
uvs.Add(new Vector2(uvCorner.x + uvWidth.x, uvCorner.y + uvWidth.y));
uvs.Add(new Vector2(uvCorner.x + uvWidth.x, uvCorner.y));
if (reversed)
{
tris.Add(index + 0);
tris.Add(index + 1);
tris.Add(index + 2);
tris.Add(index + 2);
tris.Add(index + 3);
tris.Add(index + 0);
}
else
{
tris.Add(index + 1);
tris.Add(index + 0);
tris.Add(index + 2);
tris.Add(index + 3);
tris.Add(index + 2);
tris.Add(index + 0);
}
}
public virtual bool isTransparent(int x, int y, int z)
{
if (y < -1) return false;
byte block = getByte(x, y, z);
if (y == -1)
{
return true;
}
if (onEdge1 == true && x == -1)
{
return true;
}
else if (onEdge2 == true && z == chunkWidth)
{
return true;
}
else if (onEdge3 == true && x == chunkWidth)
{
return true;
}
else if (onEdge4 == true && z == -1)
{
return true;
}
switch (block)
{
case 0:
return true;
default:
return false;
}
}
public virtual byte getByte(int x, int y, int z)
{
if ((y < 0) || (y >= chunkHeight))
{
return 0;
}
Vector3 worldPos = new Vector3(x, y, z) + transform.position;
if (!initialized)
{
return getPossibleByte(worldPos);
}
if ((x < 0) || (y < 0) || (z < 0) || (y >= chunkHeight) || x >= chunkWidth || z >= chunkWidth)
{
Chunk chunk = findChunk(worldPos);
if (chunk == this) { return 0; }
if (chunk == null) { return getPossibleByte(worldPos); }
return chunk.getByte(worldPos);
}
return map[x, y, z];
}
public virtual byte getByte(Vector3 worldPos)
{
worldPos -= transform.position;
int x = Mathf.FloorToInt(worldPos.x);
int y = Mathf.FloorToInt(worldPos.y);
int z = Mathf.FloorToInt(worldPos.z);
return getByte(x, y, z);
}
public static Chunk findChunk(Vector3 pos)
{
for (int a = 0; a < chunks.Count; a++)
{
Vector3 cpos = chunks[a].transform.position;
if ((pos.x < cpos.x) || (pos.z < cpos.z) || (pos.x >= cpos.x + chunkWidth) || (pos.z >= cpos.z + chunkWidth)) continue;
return chunks[a];
}
return null;
}
public bool setBlock(byte block, Vector3 worldPos)
{
worldPos -= transform.position;
return setBlock(block, Mathf.FloorToInt(worldPos.x), Mathf.FloorToInt(worldPos.y), Mathf.FloorToInt(worldPos.z));
}
public bool setBlock(byte block, int x, int y, int z)
{
if ((x < 0) || (y < 0) || (z < 0) || (x >= chunkWidth) || (y >= chunkHeight) || (z >= chunkWidth))
{
return false;
}
if (map[x, y, z] == block) return false;
map[x, y, z] = block;
StartCoroutine(createVisualMesh2());
if (x == 0)
{
Chunk chunk = findChunk(new Vector3(x - 2, y, z) + transform.position);
if (chunk != null)
StartCoroutine(chunk.createVisualMesh2());
}
if (x == chunkWidth - 1)
{
Chunk chunk = findChunk(new Vector3(x + 2, y, z) + transform.position);
if (chunk != null)
StartCoroutine(chunk.createVisualMesh2());
}
if (z == 0)
{
Chunk chunk = findChunk(new Vector3(x, y, z - 2) + transform.position);
if (chunk != null)
StartCoroutine(chunk.createVisualMesh2());
}
if (z == chunkWidth - 1)
{
Chunk chunk = findChunk(new Vector3(x, y, z + 2) + transform.position);
if (chunk != null)
StartCoroutine(chunk.createVisualMesh2());
}
return true;
}
public string getBiomeName()
{
return BiomeName;
}
public static Vector2 getTexturePos(byte block)
{
byte b1 = block;
float lenght = 0.00f;
float height = 0.75f;
while (b1 > 1)
{
if (b1 < 5)
{
lenght += 0.25f;
b1 -= 1;
}
else
{
height -= 0.25f;
b1 -= 4;
}
}
return new Vector2(lenght, height);
}
public bool checkForChunk(Vector3 pos)
{
pos = new Vector3(Mathf.FloorToInt(pos.x / chunkWidth), 0, Mathf.FloorToInt(pos.z / chunkWidth));
Transform par = transform.parent;
for (int a = 0; a < par.childCount; a++)
{
}
return false;
}
}
Any Ideas? -Euan
Comment