/// <summary> /// Builds the chunk's mesh. /// </summary> public void RegenerateVisualMesh(float aVoxelScale) { //float startTime = Time.realtimeSinceStartup; VoxelBlob blob = manager.m_blob; int3 blobSize = blob.size; if (sm_regenInUse) { Debug.Log("Somehow calling two regens at the same time"); //throw new System.Exception("Cannot run two RegenerateVisualMesh at the same time. If needed, make more static RegenData"); return; } sm_regenInUse = true; sm_regenData.Clear(); needsRegen = false; int chunkSize = manager.chunkSize; for (int i = 0; i < 6; ++i) { m_hasBuild[0][i] = false; m_hasWater[i] = false; m_hasPattern[i] = false; } m_mesh.Clear(); m_mesh.subMeshCount = kSubMeshCount; int3 currVoxel = new int3(); bool hasFaces = false; int3 maxVals = blobSize - position; for (int i = 0; i < 3; ++i) { maxVals[i] = Mathf.Min(maxVals[i], chunkSize); } //Debug.Log("Starting main block"); for (int z = 0; z < maxVals.z && z + position.z < blobSize.z; z += 2) { for (int y = 0; y < maxVals.y && y + position.y < blobSize.y; y += 2) { for (int x = 0; x < maxVals.x && x + position.x < blobSize.x; x += 2) { currVoxel.x = x; currVoxel.y = y; currVoxel.z = z; int2[][] buildIndex = new int2[kNumBuildMats][]; for (int i = 0; i < kNumBuildMats; ++i) { buildIndex[i] = new int2[6]; } int2[] waterIndex = new int2[6]; int2[] patternIndex = new int2[6]; byte voxel; for (int i = 0; i < 2 && x + i + position.x < blobSize.x; ++i) { for (int j = 0; j < 2 && y + j + position.y < blobSize.y; ++j) { for (int k = 0; k < 2 && z + k + position.z < blobSize.z; ++k) { int3 curr = new int3(currVoxel.x + i, currVoxel.y + j, currVoxel.z + k); voxel = VoxelAt(curr, blob); if (voxel != 0) { int2[] voxelIndex = null; switch (voxel) { case MeshManager.kVoxelWater: voxelIndex = waterIndex; break; case MeshManager.kVoxelObjectDef: voxelIndex = patternIndex; break; default: voxelIndex = buildIndex[(int)(voxel - MeshManager.kVoxelFirstMat)]; break; } if (curr.x + position.x == 0 || VoxelAt(curr.x - 1, curr.y, curr.z, blob) == 0) { voxelIndex[0][i] += (1 << (j * 2 + k)); } if (curr.x + position.x == blobSize.x - 1 || VoxelAt(curr.x + 1, curr.y, curr.z, blob) == 0) { voxelIndex[1][i] += (1 << (j * 2 + k)); } if (curr.y + position.y == 0 || VoxelAt(curr.x, curr.y - 1, curr.z, blob) == 0) { voxelIndex[2][j] += (1 << (k * 2 + i)); } if (curr.y + position.y == blobSize.y - 1 || VoxelAt(curr.x, curr.y + 1, curr.z, blob) == 0) { voxelIndex[3][j] += (1 << (k * 2 + i)); } if (curr.z + position.z == 0 || VoxelAt(curr.x, curr.y, curr.z - 1, blob) == 0) { voxelIndex[4][k] += (1 << (i * 2 + j)); } if (curr.z + position.z == blobSize.z - 1 || VoxelAt(curr.x, curr.y, curr.z + 1, blob) == 0) { voxelIndex[5][k] += (1 << (i * 2 + j)); } } } } } for (int i = 0; i < kNumBuildMats; ++i) { GenNegXFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); GenPosXFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); GenNegYFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); GenPosYFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); GenNegZFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); GenPosZFaces(currVoxel, ref hasFaces, m_hasBuild[i], buildIndex[i], m_buildOffsets[i]); } GenNegXFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenNegXFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); GenPosXFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenPosXFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); GenNegYFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenNegYFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); GenPosYFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenPosYFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); GenNegZFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenNegZFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); GenPosZFaces(currVoxel, ref hasFaces, m_hasWater, waterIndex, kWaterOffset); GenPosZFaces(currVoxel, ref hasFaces, m_hasPattern, patternIndex, kPatternOffset); } } } //Debug.Log("Finished main block"); if (!hasFaces) { sm_regenInUse = false; return; } m_mesh.name = "Visual Mesh"; m_mesh.vertices = sm_regenData.verts.ToArray(); for (int i = 0; i < kSubMeshCount; ++i) { if (sm_regenData.tris[i].Count > 0) { m_mesh.SetTriangles(sm_regenData.tris[i].ToArray(), i); } } if (m_mesh.vertexCount > 0) { manager.EnableMesh(this); } else { manager.DisableMesh(this); } m_mesh.Optimize(); sm_regenInUse = false; }