Exemple #1
0
        /// <summary>
        /// The two parameters are the normalised (0->1) elevation and moisture values.
        /// </summary>
        /// <param name="elevationPercentage"></param>
        /// <param name="moisturePercentage"></param>
        /// <returns></returns>
        public int GetBiomeID(float elevationPercentage, float moisturePercentage)
        {
            //Simple linear search through elevation zones
            StartEndRange moisturelevels = new StartEndRange()
            {
                start = 0, end = 0
            };

            for (int i = 0; i < allElevationZones.Length; i++)
            {
                var zone = allElevationZones[i];
                moisturelevels = zone.moistureLevels;
                if (elevationPercentage < zone.maxElevationPercentage)
                {
                    break;
                }
            }

            //Simple linear search through moisture levels
            int biomeID = 0;

            for (int i = moisturelevels.start; i < moisturelevels.end; i++)
            {
                var moistureDef = allMoistureDefs[i];
                biomeID = moistureDef.biomeID;
                if (moisturePercentage < moistureDef.maxMoisturePercentage)
                {
                    break;
                }
            }
            return(biomeID);
        }
Exemple #2
0
        public static NativeVoxelTypeDatabase FromTypeData(List <VoxelTypeData> typeData)
        {
            List <float>         zIndicesPerFaceList             = new List <float>();
            List <StartEndRange> voxelTypeToZIndicesRangeMapList = new List <StartEndRange>();
            List <bool>          voxelTypeToIsPassableMapList    = new List <bool>();

            //AIR
            voxelTypeToZIndicesRangeMapList.Add(new StartEndRange());
            voxelTypeToIsPassableMapList.Add(true);

            for (int i = 1; i < typeData.Count; i++)
            {
                StartEndRange range = new StartEndRange();
                range.start = zIndicesPerFaceList.Count;

                var zIndices = typeData[i].zIndicesPerFace;
                zIndicesPerFaceList.AddRange(zIndices);

                range.end = zIndicesPerFaceList.Count;
                voxelTypeToZIndicesRangeMapList.Add(range);
                voxelTypeToIsPassableMapList.Add(typeData[i].definition.isPassable);
            }

            NativeVoxelTypeDatabase database = new NativeVoxelTypeDatabase();

            database.zIndicesPerFace             = new NativeArray <float>(zIndicesPerFaceList.ToArray(), Allocator.Persistent);
            database.voxelTypeToZIndicesRangeMap = new NativeArray <StartEndRange>(voxelTypeToZIndicesRangeMapList.ToArray(), Allocator.Persistent);
            database.voxelTypeToIsPassableMap    = new NativeArray <bool>(voxelTypeToIsPassableMapList.ToArray(), Allocator.Persistent);
            return(database);
        }
Exemple #3
0
        /// <summary>
        /// Generate the database from a list of type data
        /// </summary>
        public static NativeMeshDatabase FromTypeData(List <VoxelTypeData> typeData)
        {
            List <Node>          allMeshNodesList             = new List <Node>();
            List <StartEndRange> nodesUsedByFacesList         = new List <StartEndRange>();
            List <int>           allRelativeTrianglesList     = new List <int>();
            List <StartEndRange> relativeTrianglesByFacesList = new List <StartEndRange>();
            List <bool>          isFaceSolidList = new List <bool>();

            List <StartEndRange> meshTypeRangesList           = new List <StartEndRange>();
            List <int>           voxelTypeToMeshTypeMapList   = new List <int>();
            List <ushort>        voxelTypeToMaterialIDMapList = new List <ushort>();

            List <bool> meshIdToIncludeBackfacesMapList = new List <bool>();

            Dictionary <SOMeshDefinition, int> uniqueMeshIDs = new Dictionary <SOMeshDefinition, int>();

            //AIR
            voxelTypeToMeshTypeMapList.Add(0);
            voxelTypeToMaterialIDMapList.Add(0);

            for (ushort voxelId = 1; voxelId < typeData.Count; voxelId++)
            {
                var item = typeData[voxelId];


                var SODef = item.definition.meshDefinition;
                if (!uniqueMeshIDs.TryGetValue(SODef, out var meshID))
                {
                    //New Unique mesh defintion
                    meshID = meshTypeRangesList.Count;
                    uniqueMeshIDs.Add(SODef, meshID);
                    StartEndRange meshTypeRange = new StartEndRange();
                    meshTypeRange.start = nodesUsedByFacesList.Count;

                    Flatten(SODef, allMeshNodesList, nodesUsedByFacesList, allRelativeTrianglesList, relativeTrianglesByFacesList, isFaceSolidList);

                    meshTypeRange.end = nodesUsedByFacesList.Count;
                    meshTypeRangesList.Add(meshTypeRange);
                    meshIdToIncludeBackfacesMapList.Add(SODef.includeBackfaces);
                }
                voxelTypeToMeshTypeMapList.Add(meshID);
                voxelTypeToMaterialIDMapList.Add(item.materialID);
            }

            NativeMeshDatabase nativeMeshDatabase = new NativeMeshDatabase();

            nativeMeshDatabase.allMeshNodes             = new NativeArray <Node>(allMeshNodesList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.nodesUsedByFaces         = new NativeArray <StartEndRange>(nodesUsedByFacesList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.allRelativeTriangles     = new NativeArray <int>(allRelativeTrianglesList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.relativeTrianglesByFaces = new NativeArray <StartEndRange>(relativeTrianglesByFacesList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.isFaceSolid                 = new NativeArray <bool>(isFaceSolidList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.meshTypeRanges              = new NativeArray <StartEndRange>(meshTypeRangesList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.voxelTypeToMeshTypeMap      = new NativeArray <int>(voxelTypeToMeshTypeMapList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.voxelTypeToMaterialIDMap    = new NativeArray <ushort>(voxelTypeToMaterialIDMapList.ToArray(), Allocator.Persistent);
            nativeMeshDatabase.meshIdToIncludeBackfacesMap = meshIdToIncludeBackfacesMapList.ToArray().ToNative(Allocator.Persistent);

            return(nativeMeshDatabase);
        }
Exemple #4
0
        public static IEnumerable <Vector3Int> AllPositionsOnChunkBorder(Direction dir, Vector3Int chunkDimensions)
        {
            StartEndRange xRange = new StartEndRange()
            {
                start = 0, end = chunkDimensions.x
            };
            StartEndRange yRange = new StartEndRange()
            {
                start = 0, end = chunkDimensions.y
            };
            StartEndRange zRange = new StartEndRange()
            {
                start = 0, end = chunkDimensions.z
            };

            switch (dir)
            {
            case Direction.up:
                yRange.start = yRange.end - 1;
                break;

            case Direction.down:
                yRange.end = yRange.start + 1;
                break;

            case Direction.north:
                zRange.start = zRange.end - 1;
                break;

            case Direction.south:
                zRange.end = zRange.start + 1;
                break;

            case Direction.east:
                xRange.start = xRange.end - 1;
                break;

            case Direction.west:
                xRange.end = xRange.start + 1;
                break;

            default:
                throw new ArgumentException($"direction {dir} was not recognised");
            }


            for (int z = zRange.start; z < zRange.end; z++)
            {
                for (int y = yRange.start; y < yRange.end; y++)
                {
                    for (int x = xRange.start; x < xRange.end; x++)
                    {
                        yield return(new Vector3Int(x, y, z));
                    }
                }
            }
        }
Exemple #5
0
        /// <summary>
        /// Flatten a mesh definition into the working lists
        /// </summary>
        /// <param name="def"></param>
        /// <param name="allMeshNodesList"></param>
        /// <param name="nodesUsedByFacesList"></param>
        /// <param name="allRelativeTrianglesList"></param>
        /// <param name="relativeTrianglesByFacesList"></param>
        /// <param name="isFaceSolidList"></param>
        private static void Flatten(SOMeshDefinition def,
                                    List <Node> allMeshNodesList,
                                    List <StartEndRange> nodesUsedByFacesList,
                                    List <int> allRelativeTrianglesList,
                                    List <StartEndRange> relativeTrianglesByFacesList,
                                    List <bool> isFaceSolidList
                                    )
        {
            for (int i = 0; i < def.Faces.Length; i++)
            {
                var faceDef = def.Faces[i];
                isFaceSolidList.Add(faceDef.isSolid);

                StartEndRange nodesUsedIndexers = new StartEndRange();
                nodesUsedIndexers.start = allMeshNodesList.Count;

                //Add all used nodes
                for (int j = 0; j < faceDef.UsedVertices.Length; j++)
                {
                    Node node = new Node()
                    {
                        vertex = def.AllVertices[faceDef.UsedVertices[j]],
                        uv     = def.AllUvs[faceDef.UsedUvs[j]],
                        normal = def.AllNormals[faceDef.UsedNormals[j]]
                    };

                    allMeshNodesList.Add(node);
                }

                nodesUsedIndexers.end = allMeshNodesList.Count;
                nodesUsedByFacesList.Add(nodesUsedIndexers);

                StartEndRange trianglesIndexers = new StartEndRange();
                trianglesIndexers.start = allRelativeTrianglesList.Count;
                //Add all relative triangles
                for (int j = 0; j < faceDef.Triangles.Length; j++)
                {
                    allRelativeTrianglesList.Add(faceDef.Triangles[j]);
                }
                trianglesIndexers.end = allRelativeTrianglesList.Count;

                relativeTrianglesByFacesList.Add(trianglesIndexers);
            }
        }
        public NativeBiomeDatabase ConfigToNative(SOBiomeConfiguration config, VoxelTypeManager typeManager)
        {
            List <NativeVoxelRange> allLayersList   = new List <NativeVoxelRange>();
            List <StartEndRange>    biomeLayersList = new List <StartEndRange>();
            List <NativeBiomeMoistureDefinition> allMoistureDefsList   = new List <NativeBiomeMoistureDefinition>();
            List <NativeElevationZone>           allElevationZonesList = new List <NativeElevationZone>();


            foreach (var elevationEntry in config.elevationLowToHigh)
            {
                NativeElevationZone elevationZone = new NativeElevationZone();
                elevationZone.maxElevationPercentage = elevationEntry.max;
                elevationZone.moistureLevels         = new StartEndRange()
                {
                    start = allMoistureDefsList.Count
                };

                foreach (var moistureEntry in elevationEntry.moistureLevelsLowToHigh)
                {
                    NativeBiomeMoistureDefinition moistureDef = new NativeBiomeMoistureDefinition();
                    moistureDef.maxMoisturePercentage = moistureEntry.max;

                    if (!biomeIds.TryGetValue(moistureEntry.biomeDefinition, out var id))
                    {
                        //Create new biome data
                        id = biomeLayersList.Count;
                        biomeIds.Add(moistureEntry.biomeDefinition, id);
                        biomeDefinitionsById.Add(moistureEntry.biomeDefinition);

                        Assert.IsTrue(moistureEntry.biomeDefinition.topLayers.Count > 0, $"All biome definitions must have at least one layer,{moistureEntry.biomeDefinition.name} does not");
                        StartEndRange layersForThisBiome = new StartEndRange()
                        {
                            start = allLayersList.Count
                        };

                        foreach (var layer in moistureEntry.biomeDefinition.topLayers)
                        {
                            NativeVoxelRange nativeLayer = new NativeVoxelRange();
                            nativeLayer.depth   = layer.depth;
                            nativeLayer.voxelID = typeManager.GetId(layer.voxelType);
                            allLayersList.Add(nativeLayer);
                        }

                        layersForThisBiome.end = allLayersList.Count;
                        biomeLayersList.Add(layersForThisBiome);
                    }

                    moistureDef.biomeID = id;

                    allMoistureDefsList.Add(moistureDef);
                }

                elevationZone.moistureLevels.end = allMoistureDefsList.Count;
                allElevationZonesList.Add(elevationZone);
            }

            NativeBiomeDatabase biomeDatabase = new NativeBiomeDatabase();

            VoxelTypeID defaultVoxelType = new VoxelTypeID(VoxelTypeID.AIR_ID);

            if (config.defaultVoxelType != null)
            {
                defaultVoxelType = typeManager.GetId(config.defaultVoxelType);
            }

            biomeDatabase.defaultVoxelType = defaultVoxelType;

            biomeDatabase.allLayers         = new NativeArray <NativeVoxelRange>(allLayersList.ToArray(), Allocator.Persistent);
            biomeDatabase.biomeLayers       = new NativeArray <StartEndRange>(biomeLayersList.ToArray(), Allocator.Persistent);
            biomeDatabase.allMoistureDefs   = new NativeArray <NativeBiomeMoistureDefinition>(allMoistureDefsList.ToArray(), Allocator.Persistent);
            biomeDatabase.allElevationZones = new NativeArray <NativeElevationZone>(allElevationZonesList.ToArray(), Allocator.Persistent);

            return(biomeDatabase);
        }
Exemple #7
0
        /// <summary>
        /// Compute lighting contributions from the borders of all (valid) neighbouring chunks
        /// </summary>
        private void CheckBoundaries()
        {
            for (int i = 0; i < data.directionVectors.Length; i++)
            {
                Direction dir = (Direction)i;
                if (data.directionsValid[(int)dir])
                {
                    var offset = data.directionVectors[i];

                    StartEndRange xRange = new StartEndRange()
                    {
                        start = 0, end = data.dimensions.x
                    };
                    StartEndRange yRange = new StartEndRange()
                    {
                        start = 0, end = data.dimensions.y
                    };
                    StartEndRange zRange = new StartEndRange()
                    {
                        start = 0, end = data.dimensions.z
                    };

                    switch (dir)
                    {
                    case Direction.up:
                        yRange.start = yRange.end - 1;
                        break;

                    case Direction.down:
                        yRange.end = yRange.start + 1;
                        break;

                    case Direction.north:
                        zRange.start = zRange.end - 1;
                        break;

                    case Direction.south:
                        zRange.end = zRange.start + 1;
                        break;

                    case Direction.east:
                        xRange.start = xRange.end - 1;
                        break;

                    case Direction.west:
                        xRange.end = xRange.start + 1;
                        break;

                    default:
                        throw new ArgumentException($"direction {dir} was not recognised");
                    }


                    for (int z = zRange.start; z < zRange.end; z++)
                    {
                        for (int y = yRange.start; y < yRange.end; y++)
                        {
                            for (int x = xRange.start; x < xRange.end; x++)
                            {
                                var localPos  = new int3(x, y, z);
                                var localFlat = MultiIndexToFlat(localPos, dx, dxdy);
                                var localLv   = data.lights[localFlat];

                                var neighPos = localPos + offset;
                                var neighLv  = GetLightValue(neighPos, data.lights, data.dimensions, data.neighbourData);

                                var voxel      = data.voxels[localFlat];
                                var absorption = data.voxelTypeToAbsorptionMap[voxel];

                                //Check dynamic propagation
                                if (neighLv.Dynamic > 1)
                                {
                                    var next = neighLv.Dynamic - absorption;

                                    if (next > localLv.Dynamic)
                                    {
                                        localLv.Dynamic = next;
                                        dynamicPropagationQueue.Enqueue(localPos);
                                    }
                                }

                                //Check sun propagation
                                if (neighLv.Sun > 1)
                                {
                                    var sunlight = neighLv.Sun;

                                    if (absorption < LightValue.MaxIntensity && sunlight > 1)
                                    {
                                        if ((offset.y == 1) && absorption == 1 && sunlight == LightValue.MaxIntensity)
                                        {
                                            //Do nothing, sunlight preserved going downwards
                                        }
                                        else
                                        {
                                            sunlight -= absorption;
                                        }

                                        if (sunlight > localLv.Sun)
                                        {
                                            localLv.Sun = sunlight;
                                            sunlightPropagationQueue.Enqueue(localPos);
                                        }
                                    }
                                }

                                data.lights[localFlat] = localLv;
                            }
                        }
                    }
                }
            }
        }
Exemple #8
0
        public NativeArray <LightValue> BorderToNativeLight(Direction dir, Allocator allocator = Allocator.Persistent)
        {
            StartEndRange xRange = new StartEndRange()
            {
                start = 0, end = Dimensions.x
            };
            StartEndRange yRange = new StartEndRange()
            {
                start = 0, end = Dimensions.y
            };
            StartEndRange zRange = new StartEndRange()
            {
                start = 0, end = Dimensions.z
            };

            switch (dir)
            {
            case Direction.up:
                yRange.start = yRange.end - 1;
                break;

            case Direction.down:
                yRange.end = yRange.start + 1;
                break;

            case Direction.north:
                zRange.start = zRange.end - 1;
                break;

            case Direction.south:
                zRange.end = zRange.start + 1;
                break;

            case Direction.east:
                xRange.start = xRange.end - 1;
                break;

            case Direction.west:
                xRange.end = xRange.start + 1;
                break;

            default:
                throw new ArgumentException($"direction {dir} was not recognised");
            }

            NativeArray <LightValue> lightData = new NativeArray <LightValue>(xRange.Length * yRange.Length * zRange.Length, allocator);

            int i = 0;

            for (int z = zRange.start; z < zRange.end; z++)
            {
                for (int y = yRange.start; y < yRange.end; y++)
                {
                    for (int x = xRange.start; x < xRange.end; x++)
                    {
                        lightData[i] = lightChunk[x, y, z];

                        i++;
                    }
                }
            }

            return(lightData);
        }