public void SetData(IReadableDataset <VoxelData> readableData, IWriteableDataset <VoxelData> writeableData) { readable = readableData; writeable = writeableData; for (int i = 0; i < m_dirty.Length; i++) { m_dirty[i] = true; } }
public void Rebuild(IReadableDataset <VoxelData> data, IntRect region) { if (region.size.x <= 0 || region.size.y <= 0) { ClearBuffers(); AssignMeshData(); transform.position = nextPosition; return; } m_rebuildTask = new Task(() => { ClearBuffers(); GenerateMesh(data, region, m_meshOut); }); m_rebuildTask.Start(); }
private void GenerateGreedyQuad(IReadableDataset <VoxelData> data, IntRect region, int x, int y, MeshOutput o) { float voxelSize = m_settings.voxelSize; int startX = x; int startY = y; int endX = x; int endY = y; VoxelData compare = data.Sample(region.origin.x + x, region.origin.y + y); for (int xx = x + 1; xx < region.size.x - 1; xx++) { if (o.batched[y * m_maxWidth + xx] == true) { break; } // Encountered another batch, stop expanding VoxelData a = data.Sample(region.origin.x + xx + 1, region.origin.y + y); VoxelData b = data.Sample(region.origin.x + xx + 1, region.origin.y + y + 1); if (compare.CompareWithoutExtent(a) && compare.CompareWithoutExtent(b)) { endX = xx; } else { break; } // Change in voxel data detected, stop extending } bool validUp = true; for (int yy = y + 1; yy < region.size.y - 1 && validUp == true; yy++) { for (int xx = startX; xx <= endX && validUp == true; xx++) { if (o.batched[yy * m_maxWidth + xx] == true) { validUp = false; break; } // Encountered another batch, stop expanding VoxelData a = data.Sample(region.origin.x + xx + 1, region.origin.y + yy + 1); VoxelData b = data.Sample(region.origin.x + xx, region.origin.y + yy + 1); if (compare.CompareWithoutExtent(a) == false || compare.CompareWithoutExtent(b) == false) { validUp = false; break; } } if (validUp == true) // Collect line { endY = yy; } } // Mark batch for (int yy = startY; yy <= endY; yy++) { for (int xx = startX; xx <= endX; xx++) { o.batched[yy * m_maxWidth + xx] = true; } } // Build quad mesh data float x0 = startX * voxelSize; float x1 = (endX + 1) * voxelSize; float y0 = startY * voxelSize; float y1 = (endY + 1) * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); }
private void GenerateMesh(IReadableDataset <VoxelData> data, IntRect region, MeshOutput o) { float voxelSize = m_settings.voxelSize; for (int y = 0; y < region.size.y - 1; y++) { for (int x = 0; x < region.size.x - 1; x++) { if (o.batched[y * m_maxWidth + x] == true) { continue; } // Cell is already a part of existing batch, skip it... VoxelData bottomLeft = data.Sample(region.origin.x + x, region.origin.y + y); // v = 1 VoxelData bottomRight = data.Sample(region.origin.x + x + 1, region.origin.y + y); // v = 2 VoxelData topRight = data.Sample(region.origin.x + x + 1, region.origin.y + y + 1); // v = 4 VoxelData topLeft = data.Sample(region.origin.x + x, region.origin.y + y + 1); // v = 8 byte index = 0; if ((bottomLeft.cell & VoxelData.CELL_MASK_SOLID) > 0) { index |= (1 << 0); } if ((bottomRight.cell & VoxelData.CELL_MASK_SOLID) > 0) { index |= (1 << 1); } if ((topRight.cell & VoxelData.CELL_MASK_SOLID) > 0) { index |= (1 << 2); } if ((topLeft.cell & VoxelData.CELL_MASK_SOLID) > 0) { index |= (1 << 3); } float x0 = x * voxelSize; float x1 = (x + 1) * voxelSize; float y0 = y * voxelSize; float y1 = (y + 1) * voxelSize; switch (index) { case 0: break; // Empty cell case 1: { float xstep = bottomLeft.GetExtentRightNormalized() * voxelSize; float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y0 + ystep); Vector3 v2 = new Vector3(x0 + xstep, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); AppendContour(v1, v2, o); } break; case 2: { float xstep = bottomRight.GetExtentLeftNormalized() * voxelSize; float ystep = bottomRight.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x1 - xstep, y0); Vector3 v1 = new Vector3(x1, y0 + ystep); Vector3 v2 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); AppendContour(v0, v1, o); } break; case 3: { float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize; float ystep2 = bottomRight.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y0 + ystep); Vector3 v2 = new Vector3(x1, y0 + ystep2); Vector3 v3 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); AppendContour(v1, v2, o); } break; case 4: { float xstep = topRight.GetExtentLeftNormalized() * voxelSize; float ystep = topRight.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x1, y1); Vector3 v1 = new Vector3(x1, y1 - ystep); Vector3 v2 = new Vector3(x1 - xstep, y1); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); AppendContour(v1, v2, o); } break; case 5: { float xstep = bottomLeft.GetExtentRightNormalized() * voxelSize; float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize; float xstep2 = topRight.GetExtentLeftNormalized() * voxelSize; float ystep2 = topRight.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y0 + ystep); Vector3 v2 = new Vector3(x0 + xstep, y0); Vector3 v3 = new Vector3(x1 - xstep2, y1); Vector3 v4 = new Vector3(x1, y1); Vector3 v5 = new Vector3(x1, y1 - ystep2); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.verts.Add(v5); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount + 4); o.tris.Add(vcount + 5); o.tris.Add(vcount + 1); o.tris.Add(vcount + 3); o.tris.Add(vcount + 2); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount + 5); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v5) / m_settings.voxelSize); AppendContour(v1, v3, o); AppendContour(v5, v2, o); } break; case 6: { float xstep = topRight.GetExtentLeftNormalized() * voxelSize; float xstep2 = bottomRight.GetExtentLeftNormalized() * voxelSize; Vector3 v0 = new Vector3(x1 - xstep2, y0); Vector3 v1 = new Vector3(x1 - xstep, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); AppendContour(v0, v1, o); } break; case 7: { float xstep = topRight.GetExtentLeftNormalized() * voxelSize; float ystep = bottomLeft.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y0 + ystep); Vector3 v2 = new Vector3(x1 - xstep, y1); Vector3 v3 = new Vector3(x1, y1); Vector3 v4 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 4); o.tris.Add(vcount + 4); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount + 4); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); AppendContour(v1, v2, o); } break; case 8: { float xstep = topLeft.GetExtentRightNormalized() * voxelSize; float ystep = topLeft.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y1 - ystep); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x0 + xstep, y1); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); AppendContour(v2, v0, o); } break; case 9: { float xstep = topLeft.GetExtentRightNormalized() * voxelSize; float xstep2 = bottomLeft.GetExtentRightNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x0 + xstep, y1); Vector3 v3 = new Vector3(x0 + xstep2, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); AppendContour(v2, v3, o); } break; case 10: { float xstep = topLeft.GetExtentRightNormalized() * voxelSize; float ystep = topLeft.GetExtentBottomNormalized() * voxelSize; float xstep2 = bottomRight.GetExtentLeftNormalized() * voxelSize; float ystep2 = bottomRight.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y1 - ystep); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x0 + xstep, y1); Vector3 v3 = new Vector3(x1 - xstep2, y0); Vector3 v4 = new Vector3(x1, y0 + ystep2); Vector3 v5 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.verts.Add(v5); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount + 4); o.tris.Add(vcount + 5); o.tris.Add(vcount + 3); o.tris.Add(vcount + 0); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount + 2); o.tris.Add(vcount + 4); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v5) / m_settings.voxelSize); AppendContour(v3, v0, o); AppendContour(v2, v4, o); } break; case 11: { float xstep = topLeft.GetExtentRightNormalized() * voxelSize; float ystep = bottomRight.GetExtentTopNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x0 + xstep, y1); Vector3 v3 = new Vector3(x1, y0 + ystep); Vector3 v4 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount); o.tris.Add(vcount + 3); o.tris.Add(vcount + 4); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); AppendContour(v2, v3, o); } break; case 12: { float ystep = topLeft.GetExtentBottomNormalized() * voxelSize; float ystep2 = topRight.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y1 - ystep); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y1 - ystep2); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); AppendContour(v3, v0, o); } break; case 13: { float xstep = bottomLeft.GetExtentRightNormalized() * voxelSize; float ystep = topRight.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y1 - ystep); Vector3 v4 = new Vector3(x0 + xstep, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 4); o.tris.Add(vcount + 4); o.tris.Add(vcount + 1); o.tris.Add(vcount + 3); o.tris.Add(vcount + 3); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); AppendContour(v3, v4, o); } break; case 14: { float xstep = bottomRight.GetExtentLeftNormalized() * voxelSize; float ystep = topLeft.GetExtentBottomNormalized() * voxelSize; Vector3 v0 = new Vector3(x0, y1 - ystep); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y0); Vector3 v4 = new Vector3(x1 - xstep, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.verts.Add(v4); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.tris.Add(vcount); o.tris.Add(vcount + 3); o.tris.Add(vcount + 4); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v4) / m_settings.voxelSize); AppendContour(v4, v0, o); } break; case 15: { if (topLeft.CompareWithoutExtent(bottomLeft) && topRight.CompareWithoutExtent(bottomRight) && bottomLeft.CompareWithoutExtent(bottomRight)) { GenerateGreedyQuad(data, region, x, y, o); } else { Vector3 v0 = new Vector3(x0, y0); Vector3 v1 = new Vector3(x0, y1); Vector3 v2 = new Vector3(x1, y1); Vector3 v3 = new Vector3(x1, y0); int vcount = o.verts.Count; o.verts.Add(v0); o.verts.Add(v1); o.verts.Add(v2); o.verts.Add(v3); o.tris.Add(vcount); o.tris.Add(vcount + 1); o.tris.Add(vcount + 2); o.tris.Add(vcount); o.tris.Add(vcount + 2); o.tris.Add(vcount + 3); o.uvs.Add((m_worldPos + v0) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v1) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v2) / m_settings.voxelSize); o.uvs.Add((m_worldPos + v3) / m_settings.voxelSize); } } break; } } } CombineContours(o); if (m_settings.generateCollision) { BuildCollision(o); } if (m_settings.meshContour) { BuildContourMesh(o); } if (m_settings.generateNormals) { for (int v = 0; v < o.verts.Count; v++) { o.normals.Add(Vector3.back); } } }