Esempio n. 1
0
    // ********************************************************************** //

    void Awake() 
    { 
        particleLauncher = gameObject.GetComponent(typeof(ParticleLauncher)) as ParticleLauncher;
        tintColor = new Color();
        meanColor = new Color();
        savingTimer = new Timer();

        recorder = camera.GetComponent<ScreenRecorder>();

        shapeSampleStats = new ShapeSamplingStatistics();
        particleSampleStats = new ParticleSamplingStatistics();
        colourSampleStats = new ColourSamplingStatistics();

        // Our sampling settings
        datasetForm = "hierarchy";  // "flat", "singlefeature", "hierarchy"
        numPlanets = 8 * 210;  // how many planets to generate in this simulation
        featureorder = new int[] {0, 1, 2, 3, 4, 5, 6};
        //featureorder = RandomPermutation(featureorder);  // the random ordering of features in the hierarchy

        // Read in the existing record of planet details
        recordFilePath = filePath + "stimulusLookup.json";
        if (File.Exists(recordFilePath))
        {
            Debug.Log("Opening record of generated planets.");
            LoadExistingPlanets(recordFilePath);
        }
        else 
        {
            allExistingPlanets.allPlanetData = new List<PlanetData>();
            allExistingPlanets.planetColours = new Color[allExistingPlanets.nLevels];
        }
    }
    // ********************************************************************** //

    public void UpdateSettings(ShapeSettings settings, bool reset, ShapeSamplingStatistics shapeSampleStats)
    {
        this.settings = reset ? RandomizeShapeSettings(settings, shapeSampleStats) : settings;       // generate a new random planet
        noiseFilters  = new INoiseFilter[settings.noiseLayers.Length];

        for (int i = 0; i < noiseFilters.Length; i++)
        {
            noiseFilters[i] = NoiseFilterFactory.CreateNoiseFilter(settings.noiseLayers[i].noiseSettings);
        }
        elevationMinMax = new MinMax();
    }
Esempio n. 3
0
    // ********************************************************************** //

    void LoadNextSettings(int count)
    {
        Debug.Log("planet index: " + count);

        int colourindex;
        int heightindex;
        int roughnessindex;
        int ringindex;
        int mooninessindex;
        int atmosphereindex;
        int sunindex;

        const int LOW_LEVEL  = 0;
        const int NULL_LEVEL = 1;
        const int HIGH_LEVEL = 2;

        switch (datasetForm)
        {
        case "flat":
            // for generating a full data set (non hierarchical, all combinations)
            colourindex     = count % 3;
            heightindex     = (int)(Math.Floor(count / 3f) % 3);
            roughnessindex  = (int)(Math.Floor(count / (3f * 3f)) % 3);
            ringindex       = (int)(Math.Floor(count / (3f * 3f * 3f)) % 3);
            mooninessindex  = (int)(Math.Floor(count / (3f * 3f * 3f * 3f)) % 3);
            atmosphereindex = (int)(Math.Floor(count / (3f * 3f * 3f * 3f * 3f)) % 3);
            sunindex        = (int)(Math.Floor(count / (3f * 3f * 3f * 3f * 3f * 3f)) % 3);
            break;

        case "singlefeature":
            // for testing perception of individual levels while keeping all other parameters constant. Whichever one you want to alter, make =(count%3)
            colourindex     = 0;
            heightindex     = 0;
            roughnessindex  = 0;
            ringindex       = count % 3;
            mooninessindex  = 0;
            atmosphereindex = 0;
            sunindex        = 0;
            break;

        case "heirarchy":
            // for generating a single hierarchical dataset of level 3 (8 planets)
            // note that the -1, 0 and +1 levels in the RSA matrix correspond to 0, 1 and 2 index levels of each feature respectively.
            // the numbers 0-6 here correspond to the ordering:
            // [0] colourindex
            // [1] roughnessindex
            // [2] heightindex
            // [3] ringindex
            // [4] mooninessindex
            // [5] atmosphereindex
            // [6] sunindex
            // such that e.g. for featureorder = { 6, 0, 1, 2, 3, 4, 5 }; the 6th element of featureorder is always the sunindex, with takes the position of feature 5 in the hierarchy
            //           e.g. the 0th element of featureorder corresponds to the colourindex, which takes the position of the 6th feature in the hierarchy
            //int[] featureorder = { 0, 1, 2, 3, 4, 5, 6 };  // HRS can also make a function that uses a random permutation but keep fixed for now

            int[] featureindex = new int[featureorder.Length];

            // Populate the feature index array to be equal to the null level so that it makes setting the hierarchy easier
            for (int i = 0; i < featureindex.Length; i++)
            {
                featureindex[i] = NULL_LEVEL;
            }

            // set the hierarchy logic - yes this could be simplified for better coding practice HRS
            if (numPlanets % 8 != 0)
            {
                Debug.Log("Warning: generating a number of planets that will not correctly fill the 3 level hierarchy. Check numPlanets.");
            }

            float x = 8f;
            count = count % 8;
            float rightsidecount = count;
            featureindex[0] = LessThanHalfOfX((float)count, x) ? LOW_LEVEL: HIGH_LEVEL;
            if (featureindex[0] == LOW_LEVEL)      // fill in the left side of the tree from root, N0
            {
                x = x / 2f;
                featureindex[1] = LessThanHalfOfX((float)count, x) ? LOW_LEVEL : HIGH_LEVEL;
                if (featureindex[1] == LOW_LEVEL)        // left side of tree from N1
                {
                    x = x / 2f;
                    featureindex[3] = LessThanHalfOfX((float)count, x) ? LOW_LEVEL : HIGH_LEVEL;
                }
                else                                     // right side of tree from N1
                {
                    x = x / 2f;
                    rightsidecount  = rightsidecount - x;
                    featureindex[4] = LessThanHalfOfX(rightsidecount, x) ? LOW_LEVEL : HIGH_LEVEL;
                }
            }
            else        // right side of tree from root, N0
            {
                x = x / 2f;
                rightsidecount  = rightsidecount - x;
                featureindex[2] = LessThanHalfOfX(rightsidecount, x) ? LOW_LEVEL : HIGH_LEVEL;
                if (featureindex[2] == LOW_LEVEL)        // left side of tree from N2
                {
                    x = x / 2f;
                    featureindex[5] = LessThanHalfOfX(rightsidecount, x) ? LOW_LEVEL : HIGH_LEVEL;
                }
                else                                     // right side of tree from N2
                {
                    x = x / 2f;
                    rightsidecount  = rightsidecount - x;
                    featureindex[6] = LessThanHalfOfX(rightsidecount, x) ? LOW_LEVEL : HIGH_LEVEL;
                }
            }

            // print these out to check its working properly
            for (int i = 0; i < featureindex.Length; i++)
            {
                Debug.Log("feature index [" + i + "]: " + featureindex[i]);
            }

            colourindex     = featureindex[featureorder[0]];           // 0th element on feature order says which feature this is the RSA matrix
            roughnessindex  = featureindex[featureorder[1]];           // 1
            heightindex     = featureindex[featureorder[2]];           // 2
            ringindex       = featureindex[featureorder[3]];           // 3
            mooninessindex  = featureindex[featureorder[4]];           // 4
            atmosphereindex = featureindex[featureorder[5]];           // 5
            sunindex        = featureindex[featureorder[6]];           // 6
            break;

        default:
            colourindex     = 0;
            roughnessindex  = 0;
            heightindex     = 0;
            ringindex       = 0;
            mooninessindex  = 0;
            atmosphereindex = 0;
            sunindex        = 0;
            break;
        }

        Color colour = allExistingPlanets.planetColours[colourindex];
        GaussianSummaryStats height           = allExistingPlanets.mountainHeights[heightindex];
        GaussianSummaryStats roughness        = allExistingPlanets.mountainRoughnesses[roughnessindex];
        GaussianSummaryStats ringradius       = allExistingPlanets.ringRadii[ringindex];
        GaussianSummaryStats mooniness        = allExistingPlanets.mooninesses[mooninessindex];
        GaussianSummaryStats atmosphere       = allExistingPlanets.atmosphereLevels[atmosphereindex];
        GaussianSummaryStats sunradius        = allExistingPlanets.sunRadii[sunindex];
        GaussianSummaryStats coloursaturation = allExistingPlanets.saturationLevels[colourindex];

        colourSampleStats         = new ColourSamplingStatistics();
        colourSampleStats.setMean = true;

        colourSampleStats.colourLevel    = colourindex; // try using this as a key for saturation level rather than colour
        colourSampleStats.meanColour     = colour;
        colourSampleStats.stdev          = allExistingPlanets.colourStd;
        colourSampleStats.meanSaturation = coloursaturation.mean;

        shapeSampleStats         = new ShapeSamplingStatistics();
        shapeSampleStats.setMean = true;

        shapeSampleStats.mountainRoughnessLevel = roughnessindex;
        shapeSampleStats.meanBaseRoughness      = roughness.mean;
        shapeSampleStats.stdBaseRoughness       = roughness.stdev;

        shapeSampleStats.mountainHeightLevel = heightindex;
        shapeSampleStats.meanStrength        = height.mean;
        shapeSampleStats.stdStrength         = height.stdev;

        particleSampleStats         = new ParticleSamplingStatistics();
        particleSampleStats.setMean = true;

        particleSampleStats.ringLevel      = ringindex;
        particleSampleStats.meanRingRadius = ringradius.mean;
        particleSampleStats.stdRingRadius  = ringradius.stdev;

        particleSampleStats.mooninessLevel = mooninessindex;
        particleSampleStats.meanMooniness  = mooniness.mean;
        particleSampleStats.stdMooniness   = mooniness.stdev;

        particleSampleStats.atmosphereLevel = atmosphereindex;
        particleSampleStats.meanAtmosphere  = atmosphere.mean;
        particleSampleStats.stdAtmosphere   = atmosphere.stdev;

        particleSampleStats.sunLevel      = sunindex;
        particleSampleStats.meanSunRadius = sunradius.mean;
        particleSampleStats.stdSunRadius  = sunradius.stdev;
    }
    // ********************************************************************** //

    public ShapeSettings RandomizeShapeSettings(ShapeSettings settings, ShapeSamplingStatistics shapeSampleStats)
    {
        // Planet physical shape settings
        settings.planetRadius           = 1f;
        settings.mountainHeightLevel    = shapeSampleStats.mountainHeightLevel;
        settings.mountainRoughnessLevel = shapeSampleStats.mountainRoughnessLevel;

        for (int i = 0; i < settings.noiseLayers.Length; i++)
        {
            ShapeSettings.NoiseLayer noiseLayer = settings.noiseLayers[i];
            noiseLayer.enabled             = true;
            noiseLayer.useFirstLayerAsMask = true;

            // ***HRS these are for playing with so that we are modifying values in reasonable-looking ranges across the features that we want
            switch (noiseLayer.noiseSettings.filterType)
            {
            case NoiseSettings.FilterType.Simple:

                // constant feature values
                noiseLayer.noiseSettings.simpleNoiseSettings.persistence = 0.6f;                                  //  keep this fixed around .5f
                noiseLayer.noiseSettings.simpleNoiseSettings.minValue    = 0.95f;                                 //  keep this fixed around .95f, because the height-based colours start f*****g up
                noiseLayer.noiseSettings.simpleNoiseSettings.numLayers   = 4;

                // variable feature values

                if (shapeSampleStats.setMean)
                {
                    // note that these will appear weird if they take on negative values, so be aware of that. We dont want to truncate at 0 though because then we effectively limit the variability.
                    mountainHeight    = GaussianRandom(shapeSampleStats.meanStrength, shapeSampleStats.stdStrength) * (i + 1);
                    mountainRoughness = GaussianRandom(shapeSampleStats.meanBaseRoughness, shapeSampleStats.stdBaseRoughness) * (i + 1);     // we may want to keep this one fixed around 1f
                    noiseLayer.noiseSettings.simpleNoiseSettings.strength      = mountainHeight;
                    noiseLayer.noiseSettings.simpleNoiseSettings.baseRoughness = mountainRoughness;
                }
                else
                {
                    noiseLayer.noiseSettings.simpleNoiseSettings.strength      = RandomNumberInRange(0.01f, 0.3f) * (i + 1);
                    noiseLayer.noiseSettings.simpleNoiseSettings.baseRoughness = RandomNumberInRange(0.7f, 1.1f) * (i + 1); // we may want to keep this one fixed around 1f
                }
                noiseLayer.noiseSettings.simpleNoiseSettings.roughness = 2.2f;                                              // RandomNumberInRange(1f, 3.0f);       // looks nice around 2.2f

                // change the position of the noise on the planet (almost the same as creating new noise object, if we do this for each layer independently its fine
                noiseLayer.noiseSettings.simpleNoiseSettings.centre.x = RandomNumberInRange(-.5f, .5f);
                noiseLayer.noiseSettings.simpleNoiseSettings.centre.y = RandomNumberInRange(-.5f, .5f);
                noiseLayer.noiseSettings.simpleNoiseSettings.centre.z = RandomNumberInRange(-.5f, .5f);
                break;

            case NoiseSettings.FilterType.Rigid:
                // HRS note in generated stimulus set version we dont have any rigid noise filters to keep the stimuli dimensions clearly separable

                /*
                 * // constant feature values
                 * noiseLayer.noiseSettings.rigidNoiseSettings.persistence = 0.5f;                              //  keep this fixed around .5f
                 * noiseLayer.noiseSettings.rigidNoiseSettings.minValue = 0.95f;                                //  keep this fixed around .95f, because the height-based colours start f*****g up
                 * noiseLayer.noiseSettings.rigidNoiseSettings.numLayers = 4;
                 *
                 * // variable feature values
                 * noiseLayer.noiseSettings.rigidNoiseSettings.strength = RandomNumberInRange(0.05f, 0.4f) * (i + 1);      // height of mountains
                 * noiseLayer.noiseSettings.rigidNoiseSettings.baseRoughness =  RandomNumberInRange(0.8f, 3f) * (i + 1); // roughness of mountains
                 * noiseLayer.noiseSettings.rigidNoiseSettings.roughness = 2.2f;  // RandomNumberInRange(1f, 3.0f);       // looks nice around 2.2f
                 *
                 * // change the position of the noise on the planet (almost the same as creating new noise object, if we do this for each layer independently its fine
                 * noiseLayer.noiseSettings.rigidNoiseSettings.centre.x = RandomNumberInRange(-.5f, .5f);
                 * noiseLayer.noiseSettings.rigidNoiseSettings.centre.y = RandomNumberInRange(-.5f, .5f);
                 * noiseLayer.noiseSettings.rigidNoiseSettings.centre.z = RandomNumberInRange(-.5f, .5f);
                 */
                break;
            }
            settings.noiseLayers[i] = noiseLayer;
        }
        return(settings);
    }