//TODO: why is this called try place ground if you can specify the anchor type?
    /// <summary>
    /// Tries to place object on the ground.
    /// </summary>
    /// <returns><c>true</c>, if location to spawn object is found, <c>false</c> otherwise.</returns>
    /// <param name="bounds">Bounds.</param>
    /// <param name="anchorType">Anchor type, can be Ground, Ceiling, or Wall.</param>
    /// <param name="finalX">x coord where object should spawn.</param>
    /// <param name="finalY">y coord where object should spawn.</param>
    /// <param name="modScale">Modified scale.</param>
    /// <seealso cref="PrefabDatabase.GetSceneScale">modScale is retrieved via this method.</seealso>
    /// <param name="whichPlane">Which height plane the object should spawn on.</param>
    ///
    private bool TryPlaceGroundObject(Bounds bounds, float modScale, GeneratablePrefab.AttachAnchor anchorType, out int finalX, out int finalY, out HeightPlane whichPlane)
    {
        finalX = 0;
        finalY = 0;
        whichPlane = null;

        /*
        modScale = 1.0f;
        if (shouldUseStandardizedSize)
        {
            modScale = Mathf.Min(
                standardizedSize.x / bounds.extents.x,
                standardizedSize.y / bounds.extents.y,
                standardizedSize.z / bounds.extents.z);
        }
        */

        Bounds testBounds = new Bounds(bounds.center, modScale * 2f * bounds.extents);
        int boundsWidth = Mathf.CeilToInt(2 * testBounds.extents.x / gridDim);
        int boundsLength = Mathf.CeilToInt(2 * testBounds.extents.z / gridDim);
        float boundsHeight = testBounds.extents.y;

        List<int> randomPlanesOrder = new List<int>();
        int randomOrderValue = _rand.Next(0, int.MaxValue);

        for(int i = 0; i < _allHeightPlanes.Count; ++i)
            randomPlanesOrder.Insert(randomOrderValue % (randomPlanesOrder.Count + 1), i);
        if (_forceStackObject)
            randomPlanesOrder.Remove(0);

        bool foundValid = false;
        foreach(int planeNum in randomPlanesOrder)
        {
            HeightPlane curHeightPlane = _allHeightPlanes[planeNum];
            // Make sure we aren't hitting the ceiling
            if (boundsHeight >= curHeightPlane.planeHeight || curHeightPlane.cornerPos.y + boundsHeight >= _curRoomHeight)
                continue;
            // Only get grid squares which are valid to place on.
            List<GridInfo> validValues = curHeightPlane.myGridSpots.FindAll((GridInfo info)=>{return info.rightSquares >= (boundsWidth-1) && info.downSquares > (boundsLength-1) && !info.inUse;});
            while(validValues.Count > 0 && !foundValid)
            {
                int randIndex = _rand.Next(0, validValues.Count);
                GridInfo testInfo = validValues[randIndex];
                validValues.RemoveAt(randIndex);
                if (curHeightPlane.TestGrid(testInfo, boundsWidth, boundsLength))
                {
                    Vector3 centerPos = curHeightPlane.cornerPos + new Vector3(gridDim * (testInfo.x + (0.5f * boundsWidth)), 0.1f+boundsHeight, gridDim * (testInfo.y + (0.5f * boundsLength)));
                    if (anchorType == GeneratablePrefab.AttachAnchor.Ceiling)
                        centerPos.y = _roomCornerPos.y + _curRoomHeight - (0.1f+boundsHeight);
                    if (Physics.CheckBox(centerPos, testBounds.extents))
                    {
                        // Found another object here, let the plane know that there's something above messing with some of the squares
                        string debugText = "";
                        Collider[] hitObjs = Physics.OverlapBox(centerPos, testBounds.extents);
                        HashSet<string> hitObjNames = new HashSet<string>();
                        foreach(Collider col in hitObjs)
                        {
                            if (col.attachedRigidbody != null)
                                hitObjNames.Add(col.attachedRigidbody.name);
                            else
                                hitObjNames.Add(col.gameObject.name );
                            curHeightPlane.RestrictBounds(col.bounds);
                        }
                        foreach(string hitName in hitObjNames)
                            debugText += hitName + ", ";
                        if (showProcGenDebug)
                            Debug.LogFormat("Unexpected objects: ({0}) at ({1},{2}) on plane {3} with test {5} ext: {4}", debugText, testInfo.x, testInfo.y, curHeightPlane.name, testBounds.extents, centerPos);
                    }
                    else
                    {
        //                        Debug.LogFormat("Selecting ({0},{1}) which has ({2},{3}) to place ({4},{5})", testInfo.x, testInfo.y, testInfo.rightSquares, testInfo.downSquares, boundsWidth, boundsLength);
                        finalX = testInfo.x;
                        finalY = testInfo.y;
                        whichPlane = curHeightPlane;
                        foundValid = true;
                        return foundValid;
                    }
                }
            }
        }

        return foundValid;
    }
 private void DrawTestGrid(HeightPlane plane)
 {
     // Create debug test grid on the floor
     if (DEBUG_testGridPrefab != null)
     {
         GameObject child = new GameObject("TEST GRIDS " + plane.name);
         child.transform.SetParent(_curRoom);
         foreach(GridInfo g in plane.myGridSpots)
         {
             TextMesh test = GameObject.Instantiate<TextMesh>(DEBUG_testGridPrefab);
             test.transform.SetParent(child.transform);
     //                test.text = string.Format("  {0}\n{2}  {1}\n  {3}", g.upSquares, g.leftSquares, g.rightSquares, g.downSquares);
             test.text = string.Format("{0},{1}", g.x, g.y);
             test.color = g.inUse ? Color.red: Color.cyan;
             test.transform.position = plane.GridToWorld(new Point2(g.x, g.y));
             test.name = string.Format("{0}: ({1},{2})", DEBUG_testGridPrefab.name, g.x, g.y);
             test.transform.localScale = gridDim * Vector3.one;
         }
     }
 }
    public void CreateRoom(Vector3 roomDimensions, Vector3 roomCenter)
    {
        Debug.Log ("Create 1.");
        _curRoom = new GameObject("New Room").transform;
        _roomCornerPos = (roomCenter - (0.5f *roomDimensions)) + (gridDim * 0.5f * Vector3.one);
        _roomCornerPos.y = 0f;
        Debug.Log ("Create 2.");
        // Create floor and ceiling
        Vector3 floorSize = new Vector3(roomDimensions.x, WALL_WIDTH, roomDimensions.z);
        Vector3 floorStart = roomCenter + new Vector3(-0.5f * roomDimensions.x, -WALL_WIDTH, -0.5f * roomDimensions.z);
        Vector3 ceilingStart = floorStart + (roomDimensions.y + WALL_WIDTH) * Vector3.up;
        Debug.Log ("Create 3.");
        GameObject floor = WallInfo.CreateBoxMesh(floorStart, floorSize, floorMaterial, "Floor", _curRoom);
        floor.AddComponent<SemanticObjectSimple>();
        floor.GetComponent<Rigidbody>().isKinematic = true;
        Debug.Log ("Create 4.");
        Renderer[] RendererList = floor.GetComponentsInChildren<Renderer>();
        foreach (Renderer _rend in RendererList)
        {
            foreach (Material _mat in _rend.materials)
            {
                _mat.SetColor("_idval", new Color(0f,0f,1f/256f));
            }
        }
        Debug.Log ("Create 5.");
        //{
        //	_rend.material.SetInt("_idval", 1);
        //}
        //floor.GetComponent<Renderer>().material.SetInt("_idval", 1);

        GameObject borktest = Resources.Load<GameObject> ("Prefabs/PointSpawn");
        Debug.Log ("borktest");
        if (borktest == null) {
            Debug.Log ("its null");
        }
        Debug.Log(borktest.name);
        // Make a spawn plane
        SpawnArea floorSpawn = GameObject.Instantiate<SpawnArea>(Resources.Load<SpawnArea>("Prefabs/PlaneSpawn"));
        Debug.Log ("Create 6.");
        floorSpawn.gameObject.transform.position = roomCenter;
        Debug.Log ("Create 7.");
        //retrieve ratio between spawn plane and floor
        float xRatio = floorSize.x / floorSpawn.gameObject.GetComponent<Collider>().bounds.size.x;
        float zRatio = floorSize.z / floorSpawn.gameObject.GetComponent<Collider>().bounds.size.z;
        Debug.Log ("Create 8.");
        floorSpawn.gameObject.transform.localScale = new Vector3 (xRatio * floorSpawn.gameObject.transform.localScale.x, 0, zRatio * floorSpawn.gameObject.transform.localScale.z);
        Debug.Log ("Create 9.");
        Debug.LogFormat ("Created floor: {0}", floorSpawn.name);
        Debug.Log ("Create 10.");
        GameObject top = WallInfo.CreateBoxMesh(ceilingStart, floorSize, ceilingMaterial, "Ceiling", _curRoom);
        Debug.Log ("Create 11.");
        top.AddComponent<SemanticObjectSimple>();
        Debug.Log ("Create 12.");
        top.GetComponent<Rigidbody>().isKinematic = true;
        Debug.Log ("Create 13.");
        RendererList = top.GetComponentsInChildren<Renderer>();
        foreach (Renderer _rend in RendererList)
        {
            foreach (Material _mat in _rend.materials)
            {
                _mat.SetColor("_idval", new Color(0f,0f,2f/256f));
            }
        }
        Debug.Log ("Create 14.");
        //{
        //	_rend.material.SetInt("_idval", 2);
        //}

        //top.GetComponent<Renderer>().material.SetInt("_idval", 2);

        // Setup floor plane
        _allHeightPlanes.Clear();
        HeightPlane basePlane = new HeightPlane();
        basePlane.gridDim = gridDim;
        basePlane.planeHeight = roomDim.y;
        basePlane.name = "Plane Floor";
        _allHeightPlanes.Add(basePlane);
        _curRoomWidth = Mathf.FloorToInt(roomDim.x / gridDim);
        _curRoomLength = Mathf.FloorToInt(roomDim.z / gridDim);
        _curRoomHeight = roomDim.y;
        basePlane.cornerPos = _roomCornerPos;
        basePlane.Clear(_curRoomWidth, _curRoomLength);
        Debug.Log ("Create 15.");

        // Create walls
        SubdivideRoom();
        Debug.Log ("Create 16.");
    }
    private bool AddObjects(List<PrefabDatabase.PrefabInfo> prefabList)
    {
        if (prefabList.Count == 0)
        {
            _failures++;
            return false;
        }

        // Randomly add next one?
        int temp_rand_index     = _rand.Next(0, prefabList.Count);
        PrefabDatabase.PrefabInfo info = prefabList[temp_rand_index];

        if (info.loaded==0) {
            // Load it now
            Debug.Log("From http loaded!");
            var www = WWW.LoadFromCacheOrDownload (info.fileName, 0);
            var loadedAssetBundle = www.assetBundle;
            string[] assetList = loadedAssetBundle.GetAllAssetNames ();

            foreach (string asset in assetList) {

                GameObject gObj = loadedAssetBundle.LoadAsset<GameObject> (asset);
                GeneratablePrefab[] prefab = gObj.GetComponents<GeneratablePrefab> ();
                if (prefab.GetLength (0) == 0) {
                    Debug.LogFormat ("Cannot load GeneratablePrefab component on {0}", gObj);
                    continue;
                }
                GeneratablePrefab prefab_temp   = prefab [0];
                info.loaded     = 1;
                info.complexity = prefab_temp.myComplexity;
                info.bounds     = prefab_temp.myBounds;
                info.isLight    = prefab_temp.isLight;
                info.anchorType = prefab_temp.attachMethod;
                foreach (GeneratablePrefab.StackableInfo stackRegion in prefab_temp.stackableAreas)
                    info.stackableAreas.Add (stackRegion);
                prefabList[temp_rand_index]     = info;

            }
            loadedAssetBundle.Unload (false);
        }

        // Check for excess complexity
        int maxComplexity = (complexityLevelToCreate - _curComplexity);
        if (info.complexity > maxComplexity)
        {
            // Change for lazy loading
            /*
            prefabList.RemoveAll((PrefabDatabase.PrefabInfo testInfo)=>{
                return (testInfo.complexity > maxComplexity) | (testInfo.complexity == 0);
            });
            if (showProcGenDebug)
                Debug.LogFormat("Filtering for complexity {0} > {1} leaving {2} objects ", info.complexity, maxComplexity, prefabList.Count);
            if (prefabList.Count == 0)
                return false;
            */

            prefabList.Remove(info);
            return true;
            //info = prefabList[_rand.Next(0, prefabList.Count)];
        }

        // Find a spot to place this object
        int spawnX, spawnZ;
        //float modScale = prefabDatabase.GetSceneScale (info);
        float modScale = 1.0f;

        // For option "Multi_size"
        if (info.option_scale=="Multi_size")
        {
            modScale    = modScale*info.dynamic_scale;
        }

        // For option "Absol_size"
        if (info.option_scale=="Absol_size")
        {
            float longest_axis      = info.bounds.size.magnitude;
            Debug.Log("Longest axis: " + longest_axis.ToString());
            modScale                = info.dynamic_scale/longest_axis;
        }

        HeightPlane targetHeightPlane;
        Quaternion modifiedRotation = Quaternion.identity;

        if (info.stackableAreas.Count == 0)
            modifiedRotation = Quaternion.Euler(new Vector3(0, (float) _rand.NextDouble() * 360f,0));
        Bounds modifiedBounds = info.bounds.Rotate(modifiedRotation);

        if (TryPlaceGroundObject(modifiedBounds, modScale, info.anchorType, out spawnX, out spawnZ, out targetHeightPlane))
        {
            int boundsWidth = Mathf.CeilToInt(modScale* 2f * modifiedBounds.extents.x / gridDim) - 1;
            int boundsLength = Mathf.CeilToInt(modScale* 2f * modifiedBounds.extents.z / gridDim) - 1;
            float modHeight = 0.1f+(modifiedBounds.extents.y * modScale);
            Vector3 centerPos = targetHeightPlane.cornerPos + new Vector3(gridDim * (spawnX + (0.5f * boundsWidth)), modHeight, gridDim * (spawnZ + (0.5f * boundsLength)));
            if (info.anchorType == GeneratablePrefab.AttachAnchor.Ceiling)
                centerPos.y = _roomCornerPos.y + _curRoomHeight - modHeight;

        //            GameObject newPrefab = Resources.Load<GameObject>(info.
            GameObject newPrefab;
            if (info.fileName.ToLowerInvariant().Contains("http://")) {
                Debug.Log("From http");
                newPrefab = PrefabDatabase.LoadAssetFromBundleWWW(info.fileName);
            } else {
                newPrefab = PrefabDatabase.LoadAssetFromBundle(info.fileName);
            }
            // TODO: Factor in complexity to the arrangement algorithm?
            _curComplexity += info.complexity;

            GameObject newInstance = UnityEngine.Object.Instantiate<GameObject>(newPrefab.gameObject);
            newInstance.transform.position = centerPos - (modifiedBounds.center * modScale);
            newInstance.transform.localScale = newInstance.transform.localScale * modScale;
            newInstance.transform.rotation = modifiedRotation * newInstance.transform.rotation;
            //newInstance.name = string.Format("{0} #{1} on {2}", newPrefab.name, (_curRoom != null) ? _curRoom.childCount.ToString() : "?", targetHeightPlane.name);

            newInstance.name = string.Format("{0}, {1}, {2}", info.fileName, newPrefab.name, (_curRoom != null) ? _curRoom.childCount.ToString() : "?");
            Renderer[] RendererList = newInstance.GetComponentsInChildren<Renderer>();
            Color colorID = getNewUIDColor ();
            foreach (Renderer _rend in RendererList)
            {
                    foreach (Material _mat in _rend.materials)
                    {
                            _mat.SetColor("_idval", colorID);
                    }
            }

            // Create test cube
            if (DEBUG_testCubePrefab != null)
            {
                GameObject testCube = UnityEngine.Object.Instantiate<GameObject>(DEBUG_testCubePrefab);
                testCube.transform.localScale = modScale * 2f * modifiedBounds.extents;
                testCube.transform.position = centerPos;
                testCube.name = string.Format("Cube {0}", newInstance.name);
                testCube.transform.SetParent(_curRoom);
            }

            if (showProcGenDebug)
                Debug.LogFormat("{0}: @{1} R:{2} G:{3} BC:{4} MS:{5}", info.fileName, newInstance.transform.position, targetHeightPlane.cornerPos, new Vector3(gridDim * spawnX, info.bounds.extents.y, gridDim * spawnZ), info.bounds.center, modScale);
            if (_curRoom != null)
                newInstance.transform.SetParent(_curRoom);

            // For stackable objects, create a new height plane to stack
            if (info.anchorType == GeneratablePrefab.AttachAnchor.Ground)
            {
                targetHeightPlane.UpdateGrid(spawnX, spawnZ, boundsWidth, boundsLength);
                foreach(GeneratablePrefab.StackableInfo stackInfo in info.stackableAreas)
                {
                    int width = Mathf.FloorToInt(stackInfo.dimensions.x / gridDim);
                    int length = Mathf.FloorToInt(stackInfo.dimensions.z / gridDim);
                    if (width <= 0 || length <= 0)
                        continue;
                    HeightPlane newPlane = new HeightPlane();
                    newPlane.gridDim = gridDim;
                    // TODO: Set rotation matrix for new plane?
                    newPlane.rotMat = modifiedRotation;
                    newPlane.cornerPos = newInstance.transform.position + (modifiedRotation * (stackInfo.bottomCenter + info.bounds.center));
                    newPlane.cornerPos = newPlane.GridToWorld(new Vector2((width-1) * -0.5f, (length-1) * -0.5f));
                    newPlane.planeHeight = stackInfo.dimensions.y;
                    if (stackInfo.dimensions.y <= 0)
                        newPlane.planeHeight = _curRoomHeight - newPlane.cornerPos.y;
                    newPlane.Clear(width, length);
                    newPlane.name = string.Format("Plane for {0}", newInstance.name);
                    _allHeightPlanes.Add(newPlane);
                }
            }
        }
        else
        {
            // TODO: Mark item as unplaceable and continue with smaller objects?
            if (showProcGenDebug)
                Debug.LogFormat("Couldn't place: {0}. {1} object types, {2} complexity left", info.fileName, prefabList.Count, complexityLevelToCreate - _curComplexity);
            prefabList.Remove(info);
            ++_failures;
        }
        return true;
    }
    private bool AddObjects(List<PrefabDatabase.PrefabInfo> prefabList)
    {
        if (prefabList.Count == 0)
        {
            _failures++;
            return false;
        }

        // Randomly add next one?
        int temp_rand_index     = _rand.Next(0, prefabList.Count);
        PrefabDatabase.PrefabInfo info = prefabList[temp_rand_index];

        // Deprecated
        if (info.loaded==0) {
            // Load it now
            Debug.Log("From http loaded!");
            Debug.Log(info.fileName);
            var www = WWW.LoadFromCacheOrDownload (info.fileName, 0);
            var loadedAssetBundle = www.assetBundle;
            string[] assetList = loadedAssetBundle.GetAllAssetNames ();

            foreach (string asset in assetList) {

                GameObject gObj = loadedAssetBundle.LoadAsset<GameObject> (asset);
                GeneratablePrefab[] prefab = gObj.GetComponents<GeneratablePrefab> ();
                if (prefab.GetLength (0) == 0) {
                    Debug.LogFormat ("Cannot load GeneratablePrefab component on {0}", gObj);
                    continue;
                }
                GeneratablePrefab prefab_temp   = prefab [0];
                info.loaded     = 1;
                info.complexity = prefab_temp.myComplexity;
                info.bounds     = prefab_temp.myBounds;
                info.isLight    = prefab_temp.isLight;
                info.anchorType = prefab_temp.attachMethod;
                foreach (GeneratablePrefab.StackableInfo stackRegion in prefab_temp.stackableAreas)
                    info.stackableAreas.Add (stackRegion);
                prefabList[temp_rand_index]     = info;

            }
            loadedAssetBundle.Unload (false);
        }

        // Check for excess complexity
        int maxComplexity = (complexityLevelToCreate - _curComplexity);
        if (info.complexity > maxComplexity)
        {
            // Change for lazy loading
            /*
            prefabList.RemoveAll((PrefabDatabase.PrefabInfo testInfo)=>{
                return (testInfo.complexity > maxComplexity) | (testInfo.complexity == 0);
            });
            if (showProcGenDebug)
                Debug.LogFormat("Filtering for complexity {0} > {1} leaving {2} objects ", info.complexity, maxComplexity, prefabList.Count);
            if (prefabList.Count == 0)
                return false;
            */

            prefabList.Remove(info);
            return true;
            //info = prefabList[_rand.Next(0, prefabList.Count)];
        }

        // Find a spot to place this object
        int spawnX, spawnZ;
        //float modScale = prefabDatabase.GetSceneScale (info);
        float modScale = 1.0f;
        float offset_y = 0.1f;

        // For global setting
        if (enable_global_unit_scale==1){
            float longest_axis      = info.bounds.size.magnitude;
            //Debug.Log("Longest axis: " + longest_axis.ToString());
            modScale                = 1/longest_axis;
        }

        //TODO Verify that we want to scale by the longest_axis here first (DOSCH very big otherwise)
        if (scene_scale_con=="Multi_size")
        {
            float longest_axis = info.bounds.size.magnitude;
            modScale = list_rands[0].Next_Gaussian(scene_scale_mean, scene_scale_var);
            modScale = modScale/longest_axis;
        }

        if (scene_scale_con=="Absol_size"){
            float longest_axis      = info.bounds.size.magnitude;
            modScale                = list_rands[0].Next_Gaussian(scene_scale_mean, scene_scale_var)/longest_axis;
        }

        // For option "Multi_size"
        if (info.option_scale=="Multi_size"){
            if (info.apply_to_inst)
                modScale    = list_rands[info.rand_index].Next_Gaussian(info.dynamic_scale, info.scale_var);
            else
                modScale    = info.first_rand;
        }

        // For option "Absol_size"
        if (info.option_scale=="Absol_size"){
            float longest_axis      = info.bounds.size.magnitude;
            if (info.apply_to_inst)
                modScale            = list_rands[info.rand_index].Next_Gaussian(info.dynamic_scale, info.scale_var)/longest_axis;
            else
                modScale            = info.first_rand/longest_axis;
        }

        HeightPlane targetHeightPlane;
        Quaternion modifiedRotation = Quaternion.identity;

        if (info.stackableAreas.Count == 0)
            modifiedRotation = Quaternion.Euler(new Vector3(0, (float) _rand.NextDouble() * 360f,0));
        Bounds modifiedBounds = info.bounds.Rotate(modifiedRotation);

        if (TryPlaceGroundObject(modifiedBounds, modScale, info.anchorType, out spawnX, out spawnZ, out targetHeightPlane, out offset_y))
        {
            int boundsWidth = Mathf.CeilToInt(modScale* 2f * modifiedBounds.extents.x / gridDim) - 1;
            int boundsLength = Mathf.CeilToInt(modScale* 2f * modifiedBounds.extents.z / gridDim) - 1;
            //float modHeight = 0.1f+(modifiedBounds.extents.y * modScale);
            float modHeight = offset_y+(modifiedBounds.extents.y * modScale);
            Vector3 centerPos = targetHeightPlane.cornerPos + new Vector3(gridDim * (spawnX + (0.5f * boundsWidth)), modHeight, gridDim * (spawnZ + (0.5f * boundsLength)));
            if (info.anchorType == GeneratablePrefab.AttachAnchor.Ceiling)
                centerPos.y = _roomCornerPos.y + _curRoomHeight - modHeight;

        //            GameObject newPrefab = Resources.Load<GameObject>(info.
            GameObject newPrefab;
            if (info.fileName.ToLowerInvariant().Contains("http://")) {
                if (use_cache_self==1) {
                    //Debug.Log("From cache!");
                    //StartCoroutine(PrefabDatabase.LoadAssetFromBundleWWW_cached_self(info.fileName));
                    //newPrefab = PrefabDatabase.LoadAssetFromBundleWWW(info.fileName);
                    //newPrefab = PrefabDatabase.LoadAssetFromBundleWWW_cache_in_file(info.fileName, info._id_str, info.aws_version, cache_folder);
                    //
                    //
                    //I need to do this here becuase StartCoroutine can not be correctly used in PrefabDatabase
                    string cache_fileName   = cache_folder + info._id_str + "_" + info.aws_version + ".bundle";
                    newPrefab   = PrefabDatabase.LoadAssetFromBundle(cache_fileName);
                    if (newPrefab==null){
                        // Loading it twice now, might influence the efficiency, TODO: load only once
                        // Currently the WWW can not be wrote when used for assetbundle

                        //Debug.Log("Build the cache!");
                        StartCoroutine(PrefabDatabase.LoadAssetFromBundleWWW_cached_self(info.fileName, cache_fileName));
                        newPrefab = PrefabDatabase.LoadAssetFromBundleWWW(info.fileName);
                    }
                } else {
                    //Debug.Log("From http");
                    newPrefab = PrefabDatabase.LoadAssetFromBundleWWW(info.fileName);
                }
            } else {
                newPrefab = PrefabDatabase.LoadAssetFromBundle(info.fileName);
            }
            // TODO: Factor in complexity to the arrangement algorithm?
            _curComplexity += info.complexity;

            GameObject newInstance = UnityEngine.Object.Instantiate<GameObject>(newPrefab.gameObject);
            newInstance.transform.position = centerPos - (modifiedBounds.center * modScale);
            newInstance.transform.localScale = newInstance.transform.localScale * modScale;
            newInstance.transform.rotation = modifiedRotation * newInstance.transform.rotation;
            //newInstance.name = string.Format("{0} #{1} on {2}", newPrefab.name, (_curRoom != null) ? _curRoom.childCount.ToString() : "?", targetHeightPlane.name);

            newInstance.name = string.Format("{0}, {1}, {2}", info.fileName, newPrefab.name, (_curRoom != null) ? _curRoom.childCount.ToString() : "?");
            newInstance.GetComponent<SemanticObject>().isStatic = false;
            Renderer[] RendererList = newInstance.GetComponentsInChildren<Renderer>();
            Color colorID = getNewUIDColor ();
            foreach (Renderer _rend in RendererList)
            {
                    foreach (Material _mat in _rend.materials)
                    {
                            // Always use standard shader
                            if(useStandardShader)
                                _mat.shader = Shader.Find("Standard");

                            // Set glossiness and metallic randomly
                            if(randomMaterials) {
                                float GLOSS_MEAN = 0.588270935961f;
                                float GLOSS_STD = 0.265175303096f;
                                float METALLIC_MEAN = 0.145517241379f;
                                float METALLIC_STD = 0.271416832554f;

                                // Set glossiness using statistical properties derived from a test set
                                Random_help random_gloss = new Random_help(_rand.Next());
                                float glossiness = GLOSS_MEAN;
                                if(_mat.HasProperty("_Glossiness"))
                                    glossiness = _mat.GetFloat("_Glossiness");
                                //glossiness = glossiness + Convert.ToSingle(_rand.NextDouble()) * GLOSS_STD * 2 - GLOSS_STD;
                                glossiness = random_gloss.Next_Gaussian(glossiness, GLOSS_STD);
                                glossiness = Mathf.Min(glossiness, 1.0f);
                                glossiness = Mathf.Max(glossiness, 0.0f);
                                _mat.SetFloat("_Glossiness", glossiness);

                                // Set metallic using statistical properties derived from a test set
                                Random_help random_metallic = new Random_help(_rand.Next());
                                float metallic = METALLIC_MEAN;
                                if(_mat.HasProperty("_Metallic"))
                                    metallic = _mat.GetFloat("_Metallic");
                                //metallic = metallic + Convert.ToSingle(_rand.NextDouble()) * METALLIC_STD * 2 - METALLIC_STD;
                                metallic = random_metallic.Next_Gaussian(metallic, METALLIC_STD);
                                metallic = Mathf.Min(metallic, 1.0f);
                                metallic = Mathf.Max(metallic, 0.0f);
                                _mat.SetFloat("_Metallic", metallic);
                            }

                            // Add idval to shader
                            _mat.SetColor("_idval", colorID);
                    }
            }

            // Create test cube
            if (DEBUG_testCubePrefab != null)
            {
                GameObject testCube = UnityEngine.Object.Instantiate<GameObject>(DEBUG_testCubePrefab);
                testCube.transform.localScale = modScale * 2f * modifiedBounds.extents;
                testCube.transform.position = centerPos;
                testCube.name = string.Format("Cube {0}", newInstance.name);
                testCube.transform.SetParent(_curRoom);
            }

            if (showProcGenDebug)
                Debug.LogFormat("{0}: @{1} R:{2} G:{3} BC:{4} MS:{5}", info.fileName, newInstance.transform.position, targetHeightPlane.cornerPos, new Vector3(gridDim * spawnX, info.bounds.extents.y, gridDim * spawnZ), info.bounds.center, modScale);
            if (_curRoom != null)
                newInstance.transform.SetParent(_curRoom);

            // For stackable objects, create a new height plane to stack
            if (info.anchorType == GeneratablePrefab.AttachAnchor.Ground)
            {
                if (disable_rand_stacking==1) {
                    targetHeightPlane.UpdateGrid(spawnX, spawnZ, boundsWidth, boundsLength);
                }
                foreach(GeneratablePrefab.StackableInfo stackInfo in info.stackableAreas)
                {
                    int width = Mathf.FloorToInt(stackInfo.dimensions.x / gridDim);
                    int length = Mathf.FloorToInt(stackInfo.dimensions.z / gridDim);
                    if (width <= 0 || length <= 0)
                        continue;
                    HeightPlane newPlane = new HeightPlane();
                    newPlane.gridDim = gridDim;
                    // TODO: Set rotation matrix for new plane?
                    newPlane.rotMat = modifiedRotation;
                    newPlane.cornerPos = newInstance.transform.position + (modifiedRotation * (stackInfo.bottomCenter + info.bounds.center));
                    newPlane.cornerPos = newPlane.GridToWorld(new Vector2((width-1) * -0.5f, (length-1) * -0.5f));
                    newPlane.planeHeight = stackInfo.dimensions.y;
                    if (stackInfo.dimensions.y <= 0)
                        newPlane.planeHeight = _curRoomHeight - newPlane.cornerPos.y;
                    newPlane.Clear(width, length);
                    newPlane.name = string.Format("Plane for {0}", newInstance.name);
                    _allHeightPlanes.Add(newPlane);
                }
            }
        }
        else
        {
            // TODO: Mark item as unplaceable and continue with smaller objects?
            if (showProcGenDebug)
                Debug.LogFormat("Couldn't place: {0}. {1} object types, {2} complexity left", info.fileName, prefabList.Count, complexityLevelToCreate - _curComplexity);
            prefabList.Remove(info);
            ++_failures;
        }
        return true;
    }