private VFVoxelChunkData[] GenerateFluidConstWater(VFVoxelChunkData curChunk, VFVoxelChunkData[] neibourChunks, VFVoxelChunkData[] dirtyNeibourChunks, bool bRebuildNow) { byte[] data = curChunk.DataVT; byte[] terData = GetTerraDataForWater(curChunk); int fluidDataLevel1, fluidDataLevel2, fluidDataLevel3, fluidDataLevel4, fluidDataLevel5, fluidDataLevel6; int terraDataLevel6; for (int j = 0; j < VoxelTerrainConstants._numVoxelsPerAxis; j++) // Y { for (int k = 0; k < VoxelTerrainConstants._numVoxelsPerAxis; k++) // X { for (int l = 0; l < VoxelTerrainConstants._numVoxelsPerAxis; l++) // Z { int idx6 = VFVoxelChunkData.OneIndex(k, j, l); int idxVT6 = idx6 * VFVoxel.c_VTSize; fluidDataLevel6 = data[idxVT6]; terraDataLevel6 = terData[idxVT6]; // Stratege: Fluid only if volume>terVolume if (fluidDataLevel6 > terraDataLevel6) { byte type = data[idxVT6 + 1]; int idxVT3 = idxVT6 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT; // y-1 fluidDataLevel3 = data[idxVT3]; if (fluidDataLevel3 < 255 && (terData[idxVT3] < 255 || terraDataLevel6 == 0)) // avoiding water-mesh z-fight with ter-mesh { fluidDataLevel3 = 255; VFVoxelChunkData.ModVolumeType(curChunk, idxVT3, (byte)fluidDataLevel3, type, neibourChunks, dirtyNeibourChunks); } EulerianMatrix eulerianMatrix = EulerianMatrix.None; int idxVT1 = idxVT6 - VFVoxel.c_VTSize; // x-1 int idxVT2 = idxVT6 + VFVoxel.c_VTSize; // x+1 int idxVT4 = idxVT6 + VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SQUARED_VT; // z+1 int idxVT5 = idxVT6 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SQUARED_VT; // z-1 fluidDataLevel1 = data[idxVT1]; fluidDataLevel2 = data[idxVT2]; fluidDataLevel4 = data[idxVT4]; fluidDataLevel5 = data[idxVT5]; int maxFluidableLevel = fluidDataLevel6 - Viscosity; if (fluidDataLevel1 < maxFluidableLevel && terData[idxVT1] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Left; } if (fluidDataLevel2 < maxFluidableLevel && terData[idxVT2] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Right; } if (fluidDataLevel4 < maxFluidableLevel && terData[idxVT4] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Forward; } if (fluidDataLevel5 < maxFluidableLevel && terData[idxVT5] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Backward; } if (eulerianMatrix != EulerianMatrix.None) { if (0 != (eulerianMatrix & EulerianMatrix.Left) && data[idxVT1] != maxFluidableLevel) { VFVoxelChunkData.ModVolumeType(curChunk, idxVT1, (byte)maxFluidableLevel, type, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Right) && data[idxVT2] != maxFluidableLevel) { VFVoxelChunkData.ModVolumeType(curChunk, idxVT2, (byte)maxFluidableLevel, type, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Forward) && data[idxVT4] != maxFluidableLevel) { VFVoxelChunkData.ModVolumeType(curChunk, idxVT4, (byte)maxFluidableLevel, type, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Backward) && data[idxVT5] != maxFluidableLevel) { VFVoxelChunkData.ModVolumeType(curChunk, idxVT5, (byte)maxFluidableLevel, type, neibourChunks, dirtyNeibourChunks); } } } } } } if (bRebuildNow) { for (int i = 0; i < 27; i++) { if (dirtyNeibourChunks[i] != null) { dirtyNeibourChunks[i].EndBatchWriteVoxels(); } } } return(dirtyNeibourChunks); }
private VFVoxelChunkData[] GenerateFluid(VFVoxelChunkData curChunk, VFVoxelChunkData[] neibourChunks, VFVoxelChunkData[] dirtyNeibourChunks, bool bRebuildNow) { byte[] data = curChunk.DataVT; if (data.Length < VoxelTerrainConstants.VOXEL_ARRAY_LENGTH_VT) // Safe code for multi mode may no data { return(dirtyNeibourChunks); } byte[] terData = GetTerraDataForWater(curChunk); int fluidDataLevel1, fluidDataLevel2, fluidDataLevel3, fluidDataLevel4, fluidDataLevel5, fluidDataLevel6; int terraDataLevel6; for (int j = 0; j < VoxelTerrainConstants._numVoxelsPerAxis; j++) // Y { for (int k = 0; k < VoxelTerrainConstants._numVoxelsPerAxis; k++) // X { for (int l = 0; l < VoxelTerrainConstants._numVoxelsPerAxis; l++) // Z { int idx6 = VFVoxelChunkData.OneIndex(k, j, l); int idxVT6 = idx6 * VFVoxel.c_VTSize; fluidDataLevel6 = data[idxVT6]; terraDataLevel6 = terData[idxVT6]; // Stratege: Fluid only if volume>terVolume if (fluidDataLevel6 > terraDataLevel6) { byte type = data[idxVT6 + 1]; bool bConstWater = type >= (byte)VFVoxel.EType.WaterSourceBeg; int idxVT3 = idxVT6 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT; // y-1 fluidDataLevel3 = data[idxVT3]; if (fluidDataLevel3 < 255 && (terData[idxVT3] < 255 || terData[idxVT6] == 0)) // Add terData[idxVT6] == 0 to avoid seam between terrain and water { if (bConstWater) //TMP CODE { fluidDataLevel3 = 255; VFVoxelChunkData.ModVolumeType(curChunk, idxVT3, (byte)fluidDataLevel3, type, neibourChunks, dirtyNeibourChunks); if (data[idxVT6 + VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT] != 0) { fluidDataLevel6 = 255; } if (data[idxVT6] != fluidDataLevel6) { VFVoxelChunkData.ModVolumeType(curChunk, idxVT6, (byte)fluidDataLevel6, type, neibourChunks, dirtyNeibourChunks); continue; } } else { this.FlowBottom(ref fluidDataLevel6, ref fluidDataLevel3); VFVoxelChunkData.ModVolume(curChunk, idxVT3, (byte)fluidDataLevel3, neibourChunks, dirtyNeibourChunks); } } if (fluidDataLevel6 > terraDataLevel6) { EulerianMatrix eulerianMatrix = EulerianMatrix.None; int idxVT1 = idxVT6 - VFVoxel.c_VTSize; // x-1 int idxVT2 = idxVT6 + VFVoxel.c_VTSize; // x+1 int idxVT4 = idxVT6 + VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SQUARED_VT; // z+1 int idxVT5 = idxVT6 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SQUARED_VT; // z-1 fluidDataLevel1 = data[idxVT1]; fluidDataLevel2 = data[idxVT2]; fluidDataLevel4 = data[idxVT4]; fluidDataLevel5 = data[idxVT5]; int maxFluidableLevel = fluidDataLevel6 - Viscosity; if (fluidDataLevel1 < maxFluidableLevel && terData[idxVT1] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Left; } if (fluidDataLevel2 < maxFluidableLevel && terData[idxVT2] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Right; } if (fluidDataLevel4 < maxFluidableLevel && terData[idxVT4] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Forward; } if (fluidDataLevel5 < maxFluidableLevel && terData[idxVT5] < fluidDataLevel6) { eulerianMatrix |= EulerianMatrix.Backward; } if (eulerianMatrix != EulerianMatrix.None) { switch (eulerianMatrix) { case EulerianMatrix.Left: this.Flow1(ref fluidDataLevel6, ref fluidDataLevel1); break; case EulerianMatrix.Right: this.Flow1(ref fluidDataLevel6, ref fluidDataLevel2); break; case EulerianMatrix.Left | EulerianMatrix.Right: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel1, ref fluidDataLevel2); break; case EulerianMatrix.Forward: this.Flow1(ref fluidDataLevel6, ref fluidDataLevel4); break; case EulerianMatrix.Left | EulerianMatrix.Forward: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel1); break; case EulerianMatrix.Right | EulerianMatrix.Forward: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel2); break; case EulerianMatrix.Left | EulerianMatrix.Right | EulerianMatrix.Forward: this.Flow3(ref fluidDataLevel6, ref fluidDataLevel1, ref fluidDataLevel2, ref fluidDataLevel4); break; case EulerianMatrix.Backward: this.Flow1(ref fluidDataLevel6, ref fluidDataLevel5); break; case EulerianMatrix.Left | EulerianMatrix.Backward: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel5, ref fluidDataLevel1); break; case EulerianMatrix.Right | EulerianMatrix.Backward: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel5, ref fluidDataLevel2); break; case EulerianMatrix.Left | EulerianMatrix.Right | EulerianMatrix.Backward: this.Flow3(ref fluidDataLevel6, ref fluidDataLevel1, ref fluidDataLevel2, ref fluidDataLevel5); break; case EulerianMatrix.Forward | EulerianMatrix.Backward: this.Flow2(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel5); break; case EulerianMatrix.Left | EulerianMatrix.Forward | EulerianMatrix.Backward: this.Flow3(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel5, ref fluidDataLevel1); break; case EulerianMatrix.Right | EulerianMatrix.Forward | EulerianMatrix.Backward: this.Flow3(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel5, ref fluidDataLevel2); break; case EulerianMatrix.Left | EulerianMatrix.Right | EulerianMatrix.Forward | EulerianMatrix.Backward: this.Flow4(ref fluidDataLevel6, ref fluidDataLevel4, ref fluidDataLevel5, ref fluidDataLevel1, ref fluidDataLevel2); break; } // Stratege: Sea(type>=128) can not be flowed into except from top if (0 != (eulerianMatrix & EulerianMatrix.Left) && data[idxVT1 + 1] < (byte)VFVoxel.EType.WaterSourceBeg && data[idxVT1] != fluidDataLevel1 && data[idxVT1 + 1 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT] < (byte)VFVoxel.EType.WaterSourceBeg) { VFVoxelChunkData.ModVolume(curChunk, idxVT1, (byte)fluidDataLevel1, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Right) && data[idxVT2 + 1] < (byte)VFVoxel.EType.WaterSourceBeg && data[idxVT2] != fluidDataLevel2 && data[idxVT2 + 1 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT] < (byte)VFVoxel.EType.WaterSourceBeg) { VFVoxelChunkData.ModVolume(curChunk, idxVT2, (byte)fluidDataLevel2, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Forward) && data[idxVT4 + 1] < (byte)VFVoxel.EType.WaterSourceBeg && data[idxVT4] != fluidDataLevel4 && data[idxVT4 + 1 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT] < (byte)VFVoxel.EType.WaterSourceBeg) { VFVoxelChunkData.ModVolume(curChunk, idxVT4, (byte)fluidDataLevel4, neibourChunks, dirtyNeibourChunks); } if (0 != (eulerianMatrix & EulerianMatrix.Backward) && data[idxVT5 + 1] < (byte)VFVoxel.EType.WaterSourceBeg && data[idxVT5] != fluidDataLevel5 && data[idxVT5 + 1 - VoxelTerrainConstants.VOXEL_ARRAY_AXIS_SIZE_VT] < (byte)VFVoxel.EType.WaterSourceBeg) { VFVoxelChunkData.ModVolume(curChunk, idxVT5, (byte)fluidDataLevel5, neibourChunks, dirtyNeibourChunks); } } } if (data[idxVT6] != fluidDataLevel6 && !bConstWater) { VFVoxelChunkData.ModVolume(curChunk, idxVT6, (byte)fluidDataLevel6, neibourChunks, dirtyNeibourChunks); } } } } } if (bRebuildNow) { for (int i = 0; i < 27; i++) { if (dirtyNeibourChunks[i] != null) { dirtyNeibourChunks[i].EndBatchWriteVoxels(); } } } return(dirtyNeibourChunks); }