Esempio n. 1
0
        private static void Generator(int version, int seed, float size, out CompositeShapeGeneratedDataBuilder data)
        {
            var random = MyRandom.Instance;

            using (var stateToken = random.PushSeed(seed))
            {
                data = new CompositeShapeGeneratedDataBuilder();
                data.FilledShapes  = new CsgShapeBaseBuilder[2];
                data.RemovedShapes = new CsgShapeBaseBuilder[2];
                data.MacroModule   = new MySimplexFast(seed: seed, frequency: 7f / size);
                switch (random.Next() & 0x1)
                {
                case 0:
                    data.DetailModule = new MyRidgedMultifractalFast(
                        seed: seed,
                        quality: MyNoiseQuality.Low,
                        frequency: random.NextFloat() * 0.09f + 0.11f,
                        layerCount: 1);
                    break;

                case 1:
                default:
                    data.DetailModule = new MyBillowFast(
                        seed: seed,
                        quality: MyNoiseQuality.Low,
                        frequency: random.NextFloat() * 0.07f + 0.13f,
                        layerCount: 1);
                    break;
                }

                var   halfSize        = size * 0.5f;
                float storageSize     = VRageMath.MathHelper.GetNearestBiggerPowerOfTwo(size);
                var   halfStorageSize = storageSize * 0.5f;
                var   storageOffset   = halfStorageSize - halfSize;

                CsgShapeBaseBuilder primaryShape;
                { // determine primary shape
                    var primaryType = random.Next() % 3;
                    switch (primaryType)
                    {
                    case 0:     //ShapeType.Torus
                    {
                        var secondaryRadius = (random.NextFloat() * 0.05f + 0.1f) * size;
                        var torus           = new CsgTorusBuilder(
                            translation: new Vector3(halfStorageSize),
                            invRotation: CreateRandomRotation(random),
                            primaryRadius: (random.NextFloat() * 0.1f + 0.2f) * size,
                            secondaryRadius: secondaryRadius,
                            secondaryHalfDeviation: (random.NextFloat() * 0.4f + 0.4f) * secondaryRadius,
                            deviationFrequency: random.NextFloat() * 0.8f + 0.2f,
                            detailFrequency: random.NextFloat() * 0.6f + 0.4f);
                        primaryShape = torus;
                    }
                    break;

                    case 1:     //ShapeType.Sphere
                    default:
                    {
                        var sphere = new CsgSphereBuilder(
                            translation: new Vector3(halfStorageSize),
                            radius: (random.NextFloat() * 0.1f + 0.35f) * size,
                            halfDeviation: (random.NextFloat() * 0.05f + 0.05f) * size + 1f,
                            deviationFrequency: random.NextFloat() * 0.8f + 0.2f,
                            detailFrequency: random.NextFloat() * 0.6f + 0.4f);
                        primaryShape = sphere;
                    }
                    break;
                    }
                }

                { // add some additional shapes
                    var filledShapeCount = 0;
                    data.FilledShapes[filledShapeCount++] = primaryShape;
                    while (filledShapeCount < data.FilledShapes.Length)
                    {
                        var fromBorders           = size * (random.NextFloat() * 0.2f + 0.1f) + 2f;
                        var fromBorders2          = 2f * fromBorders;
                        var sizeMinusFromBorders2 = size - fromBorders2;
                        var shapeType             = random.Next() % 3;
                        switch (shapeType)
                        {
                        case 0:     //ShapeType.Sphere
                        {
                            var center = CreateRandomPointOnBox(random, sizeMinusFromBorders2) + fromBorders;
                            var radius = fromBorders * (random.NextFloat() * 0.4f + 0.35f);

                            var sphere = new CsgSphereBuilder(
                                translation: center + storageOffset,
                                radius: radius,
                                halfDeviation: radius * (random.NextFloat() * 0.1f + 0.1f),
                                deviationFrequency: random.NextFloat() * 0.8f + 0.2f,
                                detailFrequency: random.NextFloat() * 0.6f + 0.4f);

                            data.FilledShapes[filledShapeCount++] = sphere;
                        }
                        break;

                        case 1:     //ShapeType.Capsule
                        {
                            var start = CreateRandomPointOnBox(random, sizeMinusFromBorders2) + fromBorders;
                            var end   = new Vector3(size) - start;
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.X, ref end.X);
                            }
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.Y, ref end.Y);
                            }
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.Z, ref end.Z);
                            }
                            var radius = (random.NextFloat() * 0.25f + 0.5f) * fromBorders;

                            var capsule = new CsgCapsuleBuilder(
                                pointA: start + storageOffset,
                                pointB: end + storageOffset,
                                radius: radius,
                                halfDeviation: (random.NextFloat() * 0.25f + 0.5f) * radius,
                                deviationFrequency: (random.NextFloat() * 0.4f + 0.4f),
                                detailFrequency: (random.NextFloat() * 0.6f + 0.4f));

                            data.FilledShapes[filledShapeCount++] = capsule;
                        }
                        break;

                        case 2:     //ShapeType.Torus
                        {
                            var center          = CreateRandomPointInBox(random, sizeMinusFromBorders2) + fromBorders;
                            var rotation        = CreateRandomRotation(random);
                            var borderDistance  = ComputeBoxSideDistance(center, size);
                            var secondaryRadius = (random.NextFloat() * 0.15f + 0.1f) * borderDistance;

                            var torus = new CsgTorusBuilder(
                                translation: center + storageOffset,
                                invRotation: rotation,
                                primaryRadius: (random.NextFloat() * 0.2f + 0.5f) * borderDistance,
                                secondaryRadius: secondaryRadius,
                                secondaryHalfDeviation: (random.NextFloat() * 0.25f + 0.2f) * secondaryRadius,
                                deviationFrequency: random.NextFloat() * 0.8f + 0.2f,
                                detailFrequency: random.NextFloat() * 0.6f + 0.4f);

                            data.FilledShapes[filledShapeCount++] = torus;
                        }
                        break;
                        }
                    }
                }

                { // make some holes
                    var removedShapesCount = 0;

                    while (removedShapesCount < data.RemovedShapes.Length)
                    {
                        var fromBorders           = size * (random.NextFloat() * 0.2f + 0.1f) + 2f;
                        var fromBorders2          = 2f * fromBorders;
                        var sizeMinusFromBorders2 = size - fromBorders2;
                        var shapeType             = random.Next() % 7;
                        switch (shapeType)
                        {
                        // Sphere
                        case 0:
                        {
                            var center = CreateRandomPointInBox(random, sizeMinusFromBorders2) + fromBorders;

                            var borderDistance = ComputeBoxSideDistance(center, size);
                            var radius         = (random.NextFloat() * 0.4f + 0.3f) * borderDistance;
                            var sphere         = new CsgSphereBuilder(
                                translation: center + storageOffset,
                                radius: radius,
                                halfDeviation: (random.NextFloat() * 0.3f + 0.35f) * radius,
                                deviationFrequency: (random.NextFloat() * 0.8f + 0.2f),
                                detailFrequency: (random.NextFloat() * 0.6f + 0.4f));

                            data.RemovedShapes[removedShapesCount++] = sphere;
                            break;
                        }

                        // Torus
                        case 1:
                        case 2:
                        case 3:
                        {
                            var center          = CreateRandomPointInBox(random, sizeMinusFromBorders2) + fromBorders;
                            var rotation        = CreateRandomRotation(random);
                            var borderDistance  = ComputeBoxSideDistance(center, size);
                            var secondaryRadius = (random.NextFloat() * 0.15f + 0.1f) * borderDistance;

                            var torus = new CsgTorusBuilder(
                                translation: center + storageOffset,
                                invRotation: rotation,
                                primaryRadius: (random.NextFloat() * 0.2f + 0.5f) * borderDistance,
                                secondaryRadius: secondaryRadius,
                                secondaryHalfDeviation: (random.NextFloat() * 0.25f + 0.2f) * secondaryRadius,
                                deviationFrequency: random.NextFloat() * 0.8f + 0.2f,
                                detailFrequency: random.NextFloat() * 0.6f + 0.4f);

                            data.RemovedShapes[removedShapesCount++] = torus;
                        }
                        break;

                        // Capsule
                        default:
                        {
                            var start = CreateRandomPointOnBox(random, sizeMinusFromBorders2) + fromBorders;
                            var end   = new Vector3(size) - start;
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.X, ref end.X);
                            }
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.Y, ref end.Y);
                            }
                            if ((random.Next() % 2) == 0)
                            {
                                MyUtils.Swap(ref start.Z, ref end.Z);
                            }
                            var radius = (random.NextFloat() * 0.25f + 0.5f) * fromBorders;

                            var capsule = new CsgCapsuleBuilder(
                                pointA: start + storageOffset,
                                pointB: end + storageOffset,
                                radius: radius,
                                halfDeviation: (random.NextFloat() * 0.25f + 0.5f) * radius,
                                deviationFrequency: random.NextFloat() * 0.4f + 0.4f,
                                detailFrequency: random.NextFloat() * 0.6f + 0.4f);

                            data.RemovedShapes[removedShapesCount++] = capsule;
                        }
                        break;
                        }
                    }
                }

                { // generating materials
                    // What to do when we (or mods) change the number of materials? Same seed will then produce different results.
                    FillMaterials(version);

                    Action <List <MyVoxelMaterialDefinition> > shuffleMaterials = (list) =>
                    {
                        var n = list.Count;
                        while (n > 1)
                        {
                            var k = random.Next() % n;
                            n--;
                            var value = list[k];
                            list[k] = list[n];
                            list[n] = value;
                        }
                    };
                    shuffleMaterials(m_depositMaterials);

                    if (m_surfaceMaterials.Count == 0)
                    {
                        if (m_depositMaterials.Count == 0)
                        {
                            data.DefaultMaterial = m_coreMaterials[random.Next() % m_coreMaterials.Count];
                        }
                        else
                        {
                            data.DefaultMaterial = m_depositMaterials[random.Next() % m_depositMaterials.Count];
                        }
                    }
                    else
                    {
                        data.DefaultMaterial = m_surfaceMaterials[random.Next() % m_surfaceMaterials.Count];
                    }


                    var depositCount = Math.Max((int)Math.Log(size), data.FilledShapes.Length);
                    data.Deposits = new CompositeShapeOreDepositBuilder[depositCount];

                    var depositSize = size / 10f;

                    var material        = data.DefaultMaterial;
                    var currentMaterial = 0;
                    for (var i = 0; i < data.FilledShapes.Length; ++i)
                    {
                        if (i == 0)
                        {
                            if (m_coreMaterials.Count == 0)
                            {
                                if (m_depositMaterials.Count == 0)
                                {
                                    if (m_surfaceMaterials.Count != 0)
                                    {
                                        material = m_surfaceMaterials[random.Next() % m_surfaceMaterials.Count];
                                    }
                                }
                                else
                                {
                                    material = m_depositMaterials[currentMaterial++];
                                }
                            }
                            else
                            {
                                material = m_coreMaterials[random.Next() % m_coreMaterials.Count];
                            }
                        }
                        else
                        {
                            if (m_depositMaterials.Count == 0)
                            {
                                if (m_surfaceMaterials.Count != 0)
                                {
                                    material = m_surfaceMaterials[random.Next() % m_surfaceMaterials.Count];
                                }
                            }
                            else
                            {
                                material = m_depositMaterials[currentMaterial++];
                            }
                        }
                        data.Deposits[i] = new CompositeShapeOreDepositBuilder()
                        {
                            Shape = data.FilledShapes[i], Material = material
                        };
                        random.NextFloat();
                        //                        data.Deposits[i].Shape.ShrinkTo(random.NextFloat() * 0.15f + 0.6f);
                        if (currentMaterial == m_depositMaterials.Count)
                        {
                            currentMaterial = 0;
                            shuffleMaterials(m_depositMaterials);
                        }
                    }
                    for (var i = data.FilledShapes.Length; i < depositCount; ++i)
                    {
                        var center = CreateRandomPointInBox(random, size * 0.7f) + storageOffset + size * 0.15f;
                        var radius = random.NextFloat() * depositSize + 8f;
                        random.NextFloat(); random.NextFloat();//backwards compatibility
                        CsgShapeBaseBuilder shape = new CsgSphereBuilder(center, radius);

                        if (m_depositMaterials.Count == 0)
                        {
                            material = m_surfaceMaterials[currentMaterial++];
                        }
                        else
                        {
                            material = m_depositMaterials[currentMaterial++];
                        }

                        data.Deposits[i] = new CompositeShapeOreDepositBuilder()
                        {
                            Shape = shape, Material = material
                        };

                        if (m_depositMaterials.Count == 0)
                        {
                            if (currentMaterial == m_surfaceMaterials.Count)
                            {
                                currentMaterial = 0;
                                shuffleMaterials(m_surfaceMaterials);
                            }
                        }
                        else
                        {
                            if (currentMaterial == m_depositMaterials.Count)
                            {
                                currentMaterial = 0;
                                shuffleMaterials(m_depositMaterials);
                            }
                        }
                    }


                    m_surfaceMaterials.Clear();
                    m_coreMaterials.Clear();
                    m_depositMaterials.Clear();
                }
            }
        }
Esempio n. 2
0
 private static void Generator2(int seed, float size, out CompositeShapeGeneratedDataBuilder data)
 {
     Generator(2, seed, size, out data);
 }