Chunk CreateChunk(Chunk chunk) { #if UNITY_EDITOR if (chunk == null) { Debug.LogError("Chunk must not be null!"); } #endif tempChunk = chunk; tempVoxelPosRel.Reset(); // normal chunk data // TODO can be optimized? // TODO different standard landscapes int cx = chunk.pos.x * chunkSize; int cy = chunk.pos.y * chunkSize; int cz = chunk.pos.z * chunkSize; //int noAirVoxelCount = 0; for (int i = 0, y = -1; y < chunkSizeA1; ++y) { for (int z = -1; z < chunkSizeA1; ++z) { for (int x = -1; x < chunkSizeA1; ++x, ++i) { tempVoxels[i] = GetStandardVoxel(x + cx, y + cy, z + cz); // if (!tempVoxels[i].isAir) noAirVoxelCount++; } } } // load additional voxels data for (int i = 0; i < chunk.additionalVoxelsDataNum; ++i) { int vi = chunk.additionalVoxelsDataPosIndices[i]; // if (!tempVoxels[vi].isAir) noAirVoxelCount--; tempVoxels[vi] = chunk.additionalVoxelsDataBoxIndices[i]; // if (!tempVoxels[vi].isAir) noAirVoxelCount++; } /* if (noAirVoxelCount == 0) return chunk; */ // build chunk if (!chunk.built) { chunk.m = new Mesh(); chunk.go = new GameObject("chunk " + chunk.pos); chunk.go.transform.parent = chunkParent; chunk.go.transform.position = chunk.pos.ToVector() * chunkSize; chunk.mf = chunk.go.AddComponent<MeshFilter>(); chunk.go.AddComponent<MeshRenderer>().material = material; chunk.mc = chunk.go.AddComponent<MeshCollider>(); } if (!chunk.built && randomSpawnObjects != null && randomSpawnObjects.Length > 0) { for (int y = 0; y < chunkSize; ++y) { for (int z = 0; z < chunkSize; ++z) { for (int x = 0; x < chunkSize; ++x) { if (Random.value > 0.998f && tempVoxels[GetVoxelRelPosIndex(x, y, z)].isAir) { GameObject go = (GameObject)Instantiate(randomSpawnObjects[Random.Range(0, randomSpawnObjects.Length)], new Vector3(x + cx + 0.5f, y + cy + 0.5f, z + cz + 0.5f), Random.rotationUniform); go.transform.parent = chunk.go.transform; } } } } } // create chunk mesh data TempMeshData tmd = new TempMeshData(chunkSizeA2P2 * 2); int vc = 0; // current vertex count int start = (chunkSize + 3) * chunkSizeA2 + 1; int index = start; for (tempVoxelPosRel.y = 0; tempVoxelPosRel.y < chunkSize; ++tempVoxelPosRel.y, index += chunkSizeA2M2) { for (tempVoxelPosRel.z = 0; tempVoxelPosRel.z < chunkSize; ++tempVoxelPosRel.z, index+= 2) { for (tempVoxelPosRel.x = 0; tempVoxelPosRel.x < chunkSize; ++tempVoxelPosRel.x, ++index) { if (!tempVoxels[index].isAir) { tempVoxels[index].Build(tmd, index, ref vc); } } } } // mesh creation chunk.m.Clear(); tmd.Assign(chunk.m); chunk.m.Optimize(); chunk.mf.sharedMesh = chunk.m; chunk.mc.sharedMesh = null; chunk.mc.sharedMesh = chunk.m; chunk.built = true; System.GC.Collect(); return chunk; }
// CREATE OR CHANGE A VOXEL void ChangeVoxel(Position3 posAbs, Voxel voxel, bool updateChunk = true, int padX = 0, int padY = 0, int padZ = 0) { #if UNITY_EDITOR if (padX < -1 || padX > 1) { Debug.LogError("Padding (X) too big!"); } if (padY < -1 || padY > 1) { Debug.LogError("Padding (Y) too big!"); } if (padZ < -1 || padZ > 1) { Debug.LogError("Padding (Z) too big!"); } #endif Position3 chunkPos = new Position3( (posAbs.x < 0 ? (posAbs.x - chunkSize + 1) : posAbs.x) / chunkSize - padX, // TODO: >> instead of /? (posAbs.y < 0 ? (posAbs.y - chunkSize + 1) : posAbs.y) / chunkSize - padY, // TODO: >> instead of /? (posAbs.z < 0 ? (posAbs.z - chunkSize + 1) : posAbs.z) / chunkSize - padZ // TODO: >> instead of /? ); Chunk curChunk; if (!chunks.TryGetValue(chunkPos, out curChunk)) { curChunk = new Chunk(chunkPos); } Position3 posRel = posAbs - (chunkPos * chunkSize); int posRelIndex = GetVoxelRelPosIndex(posRel); List<int> dataPosInd = new List<int>(); // using List<>s for edit mode only? List<Voxel> dataVoxel = new List<Voxel>(); if (curChunk.additionalVoxelsDataNum != 0) { // get the already created add voxel data dataPosInd.AddRange(curChunk.additionalVoxelsDataPosIndices); dataVoxel.AddRange(curChunk.additionalVoxelsDataBoxIndices); } if (dataPosInd.Contains(posRelIndex)) { // box was changed already Voxel sb = GetStandardVoxel(posAbs.x, posAbs.y, posAbs.z); int dpi = dataPosInd.IndexOf(posRelIndex); if (voxel == sb) { // is standard box? -> remove this add data dataPosInd.RemoveAt(dpi); dataVoxel.RemoveAt(dpi); curChunk.additionalVoxelsDataNum--; } else { // is new box type? -> replace it dataVoxel[dpi] = voxel; } } else { // voxel was never changed before? -> add it dataPosInd.Add(posRelIndex); dataVoxel.Add(voxel); curChunk.additionalVoxelsDataNum++; } curChunk.additionalVoxelsDataPosIndices = dataPosInd.ToArray(); curChunk.additionalVoxelsDataBoxIndices = dataVoxel.ToArray(); // somewhere at the limits? if (padY == 0 && padZ == 0 && posRel.x == 0) ChangeVoxel(posAbs, voxel, updateChunk, 1); else if (padY == 0 && padZ == 0 && posRel.x == chunkSize - 1) ChangeVoxel(posAbs, voxel, updateChunk, -1); if (padX == 0 && padZ == 0 && posRel.y == 0) ChangeVoxel(posAbs, voxel, updateChunk, 0, 1); else if (padX == 0 && padZ == 0 && posRel.y == chunkSize - 1) ChangeVoxel(posAbs, voxel, updateChunk, 0, -1); if (padX == 0 && padY == 0 && posRel.z == 0) ChangeVoxel(posAbs, voxel, updateChunk, 0, 0, 1); else if (padX == 0 && padY == 0 && posRel.z == chunkSize - 1) ChangeVoxel(posAbs, voxel, updateChunk, 0, 0, -1); // update chunk if (updateChunk) { CreateChunk(curChunk); } else { tempChunksToGetUpdated.Add(curChunk); } }
Chunk CreateChunk(Position3 pos) { Chunk chunk; chunks.TryGetValue(pos, out chunk); if (chunk == null) { chunk = new Chunk(pos); } return CreateChunk(chunk); }