// populate the planet
    protected void Initialize(float elevationScale, GameObject[] templates, int numObjects, int randomSeed, bool favorHigherElevations, float minScale, float maxScale)
    {
        Debug.Log("Placing " + numObjects + " objects under " + transform.name + " with using a random seed of " + randomSeed + "...");

        // remove all of the current objects
        Tools.DestroyChildrenOf(gameObject);

        // if we don't want to place anything then stop here now
        if (numObjects == 0)
        {
            return;
        }

        // reset random number generator to a deterministic value (so objects are always in the same place for each planet)
        Random.InitState(randomSeed);

        // get the number of template objects we have to clone from
        var numTemplateObjects = templates.Length;

        // calculate the minimum elevation we'd like to place objects at
        var minimumElevation = (m_planetGenerator.m_maximumElevation - m_planetGenerator.m_waterElevation) * 0.05f + m_planetGenerator.m_waterElevation;

        // we'll keep track of the surface normal and position for this object
        var normal   = Vector3.zero;
        var position = Vector3.zero;

        // start placing objects
        for (var i = 0; i < numObjects; i++)
        {
            // grab the template for the next object
            var template = templates[i % numTemplateObjects];

            // we'll figure out what values to use for these in the loop
            var mapX = 0.0f;
            var mapY = 0.0f;

            var elevation = 0.0f;

            // maximum of 10 tries to put this object somewhere decent
            var spotFound = false;

            for (var j = 0; j < 10; j++)
            {
                // pick a random place on the planet surface
                mapX = Random.Range(0.0f, m_planetGenerator.m_textureMapWidth);
                mapY = Random.Range(m_planetGenerator.m_textureMapHeight * 0.125f, m_planetGenerator.m_textureMapHeight * 0.875f);

                // Debug.Log( "Object #" + ( i + 1 ) + ", trying mapX=" + mapX + ", mapY=" + mapY + "..." );

                // get the surface normal
                normal = m_planetGenerator.GetBilinearSmoothedNormal(mapX, mapY, elevationScale * 0.125f);

                // is the surface steep (more that 45 degree slope)?
                if (normal.y < 0.707f)
                {
                    // Debug.Log( "...too steep!" );

                    // yes - let's not put it here
                    continue;
                }

                // get the elevation
                elevation = m_planetGenerator.GetBilinearSmoothedElevation(mapX, mapY);

                // is the elevation is below the minimum elevation
                if (elevation < minimumElevation)
                {
                    // Debug.Log( "...below minimum elevation!" );

                    // yes - let's not put it here
                    continue;
                }

                // pick a random elevation somewhere between the minimum and the maximum elevation
                var randomElevation = Random.Range(minimumElevation, m_planetGenerator.m_maximumElevation);

                // do we want to favor the higher elevations?
                if (favorHigherElevations)
                {
                    // yes - are we below the random elevation?
                    if (elevation <= randomElevation)
                    {
                        // Debug.Log( "...below random elevation!" );

                        // yes - let's not put it here
                        continue;
                    }
                }
                else
                {
                    // no - are we above the random elevation?
                    if (elevation >= randomElevation)
                    {
                        // Debug.Log( "...above random elevation!" );

                        // yes - let's not put it here
                        continue;
                    }
                }

                // calculate the position of this object in world coordinates
                position = Tools.MapToWorldCoordinates(mapX, mapY, m_planetGenerator.m_textureMapWidth, m_planetGenerator.m_textureMapHeight);

                position.y = elevation * elevationScale;

                // check if this object is too close to another object we've already placed

                if (OverlapsSomething(position))
                {
                    // Debug.Log( "...overlaps another object!" );

                    // nope - let's not put it here
                    continue;
                }

                // yay! let's put it here
                spotFound = true;
                break;
            }

            // did we find a good spot to put this object?
            if (!spotFound)
            {
                // no - ok let's skip this one
                continue;
            }

            // give the object a random rotation and align it with the surface normal
            var rotation = Quaternion.FromToRotation(Vector3.up, normal) * Quaternion.Euler(0.0f, Random.Range(0.0f, 360.0f), 0.0f) * template.transform.localRotation;

            // tell unity to clone an object from the selected template with the position and rotation we want it to have
            var clonedObject = Instantiate(template, position, rotation, transform);

            clonedObject.name = "Clone #" + (i + 1) + " (from " + template.name + ")";

            // give the cloned object a random scale
            clonedObject.transform.localScale = Vector3.one * Random.Range(minScale, maxScale);

            // add object to the spawn list
            AddToSpawnList(position);
        }
    }