/// <summary> /// Call this method from your DoWork() / AddDetail() code if you modify the chunk contents to ensure world is updated accordingly /// </summary> public void SetChunkIsDirty(VoxelChunk chunk) { chunk.MarkAsInconclusive(); }
void ModelPlace(Vector3 position, ModelDefinition model, ref Bounds bounds, int rotationDegrees = 0, float colorBrightness = 1f, bool fitTerrain = false, List <VoxelIndex> indices = null, int indexStart = -1, int indexEnd = -1) { if (model == null) { return; } if (indexStart < 0) { indexStart = 0; } if (indexEnd < 0) { indexEnd = model.bits.Length - 1; } Vector3 pos; int modelOneYRow = model.sizeZ * model.sizeX; int modelOneZRow = model.sizeX; int halfSizeX = model.sizeX / 2; int halfSizeZ = model.sizeZ / 2; if (rotationDegrees == 360) { switch (UnityEngine.Random.Range(0, 4)) { case 0: rotationDegrees = 90; break; case 1: rotationDegrees = 180; break; case 2: rotationDegrees = 270; break; } } bool indicesProvided = indices != null; if (indicesProvided && indexStart < 0 && indexEnd < 0) { indices.Clear(); } VoxelIndex index = new VoxelIndex(); VoxelChunk lastChunk = null; int tmp; Vector3 min = bounds.min; Vector3 max = bounds.max; for (int b = indexStart; b <= indexEnd; b++) { int bitIndex = model.bits [b].voxelIndex; int py = bitIndex / modelOneYRow; int remy = bitIndex - py * modelOneYRow; int pz = remy / modelOneZRow; int px = remy - pz * modelOneZRow; switch (rotationDegrees) { case 90: tmp = px; px = halfSizeZ - pz; pz = halfSizeX - tmp; break; case 180: px = halfSizeX - px; pz = halfSizeZ - pz; break; case 270: tmp = px; px = pz - halfSizeZ; pz = tmp - halfSizeX; break; default: px -= halfSizeX; pz -= halfSizeZ; break; } pos.x = position.x + model.offsetX + px; pos.y = position.y + model.offsetY + py; pos.z = position.z + model.offsetZ + pz; VoxelChunk chunk; int voxelIndex; if (GetVoxelIndex(pos, out chunk, out voxelIndex)) { Color32 color = model.bits [b].finalColor; VoxelDefinition vd = model.bits [b].voxelDefinition ?? defaultVoxel; bool emptyVoxel = model.bits [b].isEmpty; if (emptyVoxel) { chunk.voxels [voxelIndex] = Voxel.Empty; } else { if (colorBrightness != 1f) { color.r = (byte)(color.r * colorBrightness); color.g = (byte)(color.g * colorBrightness); color.b = (byte)(color.b * colorBrightness); } chunk.voxels [voxelIndex].Set(vd, color); // Add index if (indicesProvided) { index.chunk = chunk; index.voxelIndex = voxelIndex; index.position = pos; indices.Add(index); } if (pos.x < min.x) { min.x = pos.x; } if (pos.y < min.y) { min.y = pos.y; } if (pos.z < min.z) { min.z = pos.z; } if (pos.x > max.x) { max.x = pos.x; } if (pos.y > max.y) { max.y = pos.y; } if (pos.z > max.z) { max.z = pos.z; } } // Prevent tree population chunk.allowTrees = false; chunk.modified = true; if (fitTerrain && !emptyVoxel) { // Fill beneath row 1 if (py == 0) { Vector3 under = pos; under.y -= 1; for (int k = 0; k < 100; k++, under.y--) { VoxelChunk lowChunk; int vindex; GetVoxelIndex(under, out lowChunk, out vindex, false); if (lowChunk != null && lowChunk.voxels [vindex].opaque < FULL_OPAQUE) { lowChunk.voxels [vindex].Set(vd, color); if (lowChunk != lastChunk) { lastChunk = lowChunk; if (!lastChunk.inqueue) { ChunkRequestRefresh(lastChunk, true, true); } } } else { break; } } } } if (chunk != lastChunk) { lastChunk = chunk; if (!lastChunk.inqueue) { lastChunk.MarkAsInconclusive(); ChunkRequestRefresh(lastChunk, true, true); } } } } FastVector.Floor(ref min); FastVector.Ceiling(ref max); bounds.center = (max + min) * 0.5f; bounds.size = max - min; }