private static void PlaceOutsideObjects(GenerationRandom genRan, Blacksmith smith, BuildingVoxels vox, Vec2i outMin, Vec2i outMax) { List <WorldObjectData> toPlace = new List <WorldObjectData>(new WorldObjectData[] { new Anvil(), new Anvil() }); bool isFinished = false; while (!isFinished) { WorldObjectData toPlaceCur = toPlace[0]; toPlace.RemoveAt(0); Vector3 pos = genRan.RandomVector3(outMin.x, outMax.x, 0, 0, outMin.z, outMax.z); toPlaceCur.SetPosition(pos); while (!BuildingGenerator.AddObject(smith, vox, toPlaceCur)) { pos = genRan.RandomVector3(outMin.x, outMax.x, 0, 0, outMin.z, outMax.z); toPlaceCur.SetPosition(pos); } if (toPlace.Count == 0) { isFinished = true; } } }
/// <summary> /// /// </summary> /// <param name="genRan">The RNG used for this building</param> /// <param name="obj">The object to place in the building</param> /// <param name="height">The height above the ground the object should sit</param> /// <param name="vox">The voxel data of this building. Only required if 'requireWallBacking' is true</param> /// <param name="build">The building to place the object in</param> /// <param name="distFromWall">The distance from a wall the object should be placed</param> /// <param name="wallIndex">Defines the wall we should attempt to place this object on. The 'i'th wall defines the wall /// connecting build.BoundingWall[i] -> build.BoundingWall[i+1]. If left as default value (-1), an index will be randomly generated</param> /// <param name="requireWallBacking">If true, then we will search for a point on the wall that is backed against a wall. /// Used to stop certain objects being placed in front of windows</param> /// <param name="forcePlace">If true, then we do not check for intersection with other objects in the building</param> /// <param name="attemptsCount">The number of attempts made to place the object on this wall</param> /// <returns>True if object is placed sucesfully, false otherwise</returns> public static bool PlaceObjectAgainstWall(GenerationRandom genRan, WorldObjectData obj, float height, BuildingVoxels vox, Building build, float distFromWall = 0, bool requireWallBacking = false, int distToEntr = 2, bool forcePlace = false, int attemptsCount = 5) { if (build.InsideWallPoints == null) { build.InsideWallPoints = FindInsideWallBoundryPoints(vox, build); } //Check attempts count attemptsCount--; if (attemptsCount == 0) { return(false); } float wallDisp = genRan.Random(); //Define the position as the start pos + lambda*dir //Select a random position from all wall points Vec2i pos = genRan.RandomFromArray(build.InsideWallPoints); //If too close to entrance, try another placement if (build.Entrance != null && pos.QuickDistance(build.Entrance) < distToEntr * distToEntr) { return(PlaceObjectAgainstWall(genRan, obj, height, vox, build, distFromWall, requireWallBacking, distToEntr, forcePlace, attemptsCount)); } //If the object is too close to any of the corners, try again foreach (Vec2i v in build.BoundingWall) { if (v.QuickDistance(pos) < 2) { return(PlaceObjectAgainstWall(genRan, obj, height, vox, build, distFromWall, requireWallBacking, distToEntr, forcePlace, attemptsCount)); } } Vec2i faceDirection = GetWallPointDirection(build, pos); //If we require a backing wall, we check the position if (requireWallBacking) { Vec2i wPos = pos - faceDirection; for (int y = 0; y < 4; y++) { VoxelNode vn = vox.GetVoxelNode(wPos.x, y, wPos.z); //If there is no node (nothing set) then this position is not valid if (!vn.IsNode) { return(PlaceObjectAgainstWall(genRan, obj, height, vox, build, distFromWall, requireWallBacking, distToEntr, forcePlace, attemptsCount)); } if (vn.Voxel == Voxel.glass || vn.Voxel == Voxel.none) { return(PlaceObjectAgainstWall(genRan, obj, height, vox, build, distFromWall, requireWallBacking, distToEntr, forcePlace, attemptsCount)); } } } Vector3 finPos = pos.AsVector3() + faceDirection.AsVector3() * distFromWall + Vector3.up * height; float rotation = Vec2i.Angle(Vec2i.Forward, faceDirection); obj.SetPosition(finPos).SetRotation(rotation); if (!forcePlace) { foreach (WorldObjectData obj_ in build.GetBuildingExternalObjects()) { if (obj.Intersects(obj_)) { return(PlaceObjectAgainstWall(genRan, obj, height, vox, build, distFromWall, requireWallBacking, distToEntr, forcePlace, attemptsCount)); } } } //obj.SetPosition(finPos); build.AddInternalObject(obj); return(true); }
public void SetChunkData(ChunkData chunk, ChunkData[] neighbors, bool forceLoad = false) { Debug.BeginDeepProfile("set_data"); //Debug.BeginProfile("set_data"); Chunk = chunk; transform.position = new Vector3(Chunk.X * World.ChunkSize, 0, Chunk.Z * World.ChunkSize); LoadedWorldObjects = new WorldObject[World.ChunkSize, World.ChunkSize]; Debug.BeginDeepProfile("chunk_create_mesh"); int waterDepth = -5; List <Vector3> verticies = new List <Vector3>(); List <int> triangles = new List <int>(); List <Color> colours = new List <Color>(); List <Vector3> normals = new List <Vector3>(); int tri = 0; bool hasWater = false; ///Iterate every point in chunk, define terrain mesh based on tiles. #region mesh_gen for (int z = 0; z < World.ChunkSize; z++) { for (int x = 0; x < World.ChunkSize; x++) { normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); normals.Add(Vector3.up); Tile t = Chunk.GetTile(x, z); Color c = t == null?Tile.GRASS.GetColor() : t.GetColor(); int y = 0; //Check if this tile is water, if so then height=-1 if (t == Tile.WATER) { hasWater = true; y = waterDepth; } verticies.Add(new Vector3(x, y, z)); colours.Add(c); //If we are within non-extremes of chunk if (x < World.ChunkSize - 1 && z < World.ChunkSize - 1) { verticies.Add(new Vector3(x, chunk.GetTile(x, z + 1) == Tile.WATER? waterDepth : 0, z + 1)); colours.Add(chunk.GetTile(x, z + 1).GetColor()); verticies.Add(new Vector3(x + 1, chunk.GetTile(x + 1, z + 1) == Tile.WATER ? waterDepth : 0, z + 1)); colours.Add(chunk.GetTile(x + 1, z + 1).GetColor()); verticies.Add(new Vector3(x + 1, chunk.GetTile(x + 1, z) == Tile.WATER ? waterDepth : 0, z)); colours.Add(chunk.GetTile(x + 1, z).GetColor()); } else { //We are at an extreme //Check x extreme, if we are not in x extreme then this must be Z extreme if (x < World.ChunkSize - 1) { //Z EXTREME Tile t1 = neighbors[0] != null ? neighbors[0].GetTile(x, 0) : null; Tile t2 = neighbors[0] != null ? neighbors[0].GetTile(x + 1, 0) : null; Tile t3 = chunk.GetTile(x + 1, z); if (t1 == null) { verticies.Add(new Vector3(x, y, z + 1)); colours.Add(c); } else { if (t1 == Tile.WATER) { verticies.Add(new Vector3(x, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x, 0, z + 1)); } colours.Add(t1.GetColor()); } if (t2 == null) { verticies.Add(new Vector3(x + 1, y, z + 1)); colours.Add(c); } else { if (t2 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x + 1, 0, z + 1)); } colours.Add(t2.GetColor()); } if (t3 == null) { verticies.Add(new Vector3(x + 1, y, z)); colours.Add(c); } else { if (t3 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z)); } else { verticies.Add(new Vector3(x + 1, 0, z)); } colours.Add(t3.GetColor()); } } else if (z < World.ChunkSize - 1) { //X EXTREME Tile t1 = chunk.GetTile(x, z + 1); Tile t2 = neighbors[2] != null ? neighbors[2].GetTile(0, z + 1) : null; Tile t3 = neighbors[2] != null ? neighbors[2].GetTile(0, z) : null; if (t1 == null) { verticies.Add(new Vector3(x, y, z + 1)); colours.Add(c); } else { if (t1 == Tile.WATER) { verticies.Add(new Vector3(x, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x, 0, z + 1)); } colours.Add(t1.GetColor()); //colours.Add(Color.red); } if (t2 == null) { verticies.Add(new Vector3(x + 1, y, z + 1)); colours.Add(c); } else { if (t2 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x + 1, 0, z + 1)); } //colours.Add(Color.magenta); colours.Add(t2.GetColor()); //colours.Add(Color.yellow); } if (t3 == null) { verticies.Add(new Vector3(x + 1, y, z)); colours.Add(c); } else { if (t3 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z)); } else { verticies.Add(new Vector3(x + 1, 0, z)); } colours.Add(t3.GetColor()); } } else { //BOTH EXTREME Tile t1 = neighbors[0] != null ? neighbors[0].GetTile(x, 0) : null; Tile t2 = neighbors[1] != null ? neighbors[1].GetTile(0, 0) : null; Tile t3 = neighbors[2] != null ? neighbors[2].GetTile(0, z) : null; if (t1 == null) { verticies.Add(new Vector3(x, y, z + 1)); colours.Add(c); } else { if (t1 == Tile.WATER) { verticies.Add(new Vector3(x, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x, 0, z + 1)); } colours.Add(t1.GetColor()); } if (t2 == null) { verticies.Add(new Vector3(x + 1, y, z + 1)); colours.Add(c); } else { if (t2 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z + 1)); } else { verticies.Add(new Vector3(x + 1, 0, z + 1)); } colours.Add(t2.GetColor()); } if (t3 == null) { verticies.Add(new Vector3(x + 1, y, z)); colours.Add(c); } else { if (t3 == Tile.WATER) { verticies.Add(new Vector3(x + 1, waterDepth, z)); } else { verticies.Add(new Vector3(x + 1, 0, z)); } colours.Add(t3.GetColor()); } } } triangles.Add(tri); triangles.Add(tri + 1); triangles.Add(tri + 2); triangles.Add(tri); triangles.Add(tri + 2); triangles.Add(tri + 3); tri += 4; } } if (!hasWater) { foreach (Vector3 v in verticies) { if (v.y != 0) { hasWater = true; break; } } } Debug.EndDeepProfile("chunk_create_mesh"); Debug.BeginDeepProfile("chunk_set_mesh"); MeshFilter meshFilt = GetComponent <MeshFilter>(); meshFilt.mesh = new Mesh(); meshFilt.mesh.vertices = verticies.ToArray(); meshFilt.mesh.triangles = triangles.ToArray(); meshFilt.mesh.colors = colours.ToArray(); meshFilt.mesh.normals = normals.ToArray(); GetComponent <MeshRenderer>().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; gameObject.GetComponent <MeshRenderer>().material = ResourceManager.GetMaterial("Chunk"); #endregion Vector3[] colVerts = new Vector3[] { new Vector3(0, 0, 0), new Vector3(0, 0, World.ChunkSize), new Vector3(World.ChunkSize, 0, World.ChunkSize), new Vector3(World.ChunkSize, 0, 0) }; int[] colTris = new int[] { 0, 1, 2, 0, 2, 3 }; Mesh colMesh = GetComponent <MeshCollider>().sharedMesh = new Mesh(); if (hasWater) { colMesh.vertices = GetComponent <MeshFilter>().mesh.vertices; colMesh.triangles = GetComponent <MeshFilter>().mesh.triangles; } else { colMesh.vertices = colVerts; colMesh.triangles = colTris; } this.name = this.name + chunk.DEBUG; Debug.EndDeepProfile("chunk_set_mesh"); Vec2i chunkWorldPos = new Vec2i(chunk.X, chunk.Z) * World.ChunkSize; if (Chunk.Objects == null) { Debug.EndDeepProfile("set_data"); return; } Debug.BeginDeepProfile("chunk_set_obj"); for (int x = 0; x < World.ChunkSize; x++) { for (int z = 0; z < World.ChunkSize; z++) { WorldObjectData wObj = Chunk.GetObject(x, z); if (wObj != null) { wObj.SetPosition(new Vec2i(chunk.X * World.ChunkSize + x, chunk.Z * World.ChunkSize + z)); //Debug.BeginDeepProfile("CreateWorldObj"); //objs.Add(wObj); WorldObject loaded = wObj.CreateWorldObject(transform); LoadedWorldObjects[x, z] = loaded; } } } Debug.EndDeepProfile("chunk_set_obj"); Debug.EndDeepProfile("set_data"); //Debug.EndProfile(); }