Пример #1
0
 //returns the lodpos of 1 higher level that contains the given lodpos
 private LODPos getAbove(LODPos pos)
 {
     return(new LODPos(pos.level + 1,
                       Mathf.FloorToInt(pos.x / 2.0f),
                       Mathf.FloorToInt(pos.y / 2.0f),
                       Mathf.FloorToInt(pos.z / 2.0f)));
 }
Пример #2
0
    //returns true if land (probably) exists within the given lod chunk
    public bool containsLand(LODPos pos)
    {
        //length of this specific lod chunk
        float sideLength = TerrainObject.chunkWidth * Mathf.Pow(2, pos.level);

        bool pointInLand = false;

        for (int x = 0; x <= 1; x++)
        {
            for (int y = 0; y <= 1; y++)
            {
                for (int z = 0; z <= 1; z++)
                {
                    bool insideLand;
                    if (pointContainsLand(sideLength, new Vector3(x, y, z), pos, out insideLand))
                    {
                        return(true);
                    }

                    if (x == 0 && y == 0 && z == 0)
                    {
                        pointInLand = insideLand;
                    }
                    else if (pointInLand != insideLand)
                    {
                        return(true);
                    }
                }
            }
        }


        return(false);
    }
Пример #3
0
    //creates (instantiates) a terrain chunk (but does not render it yet)
    public void CreateChunk(LODPos pos, bool render)
    {
        //if the chunk has aready been created, dont build it again!
        if (chunks.ContainsKey(pos))
        {
            return;
        }

        totalChunks++;

        //build the terrainobject and add its gameobject to the chunks list(may remove this last thing later)
        //TerrainObject chunk = Build.buildObject<TerrainObject>(pos.toVector3(), Quaternion.identity);
        GameObject terrainGO = Pool.getTerrain();

        terrainGO.name = "Terrain Chunk " + pos.ToString();
        TerrainObject chunk = terrainGO.GetComponent <TerrainObject>();

        chunk.init(pos, planet);
        chunks.Add(pos, chunk);
        //Debug.Log("chunks added key :" + pos.ToString());
        visChunks.Add(pos);

        if (render)
        {
            chunk.calculateNoise();
            chunk.Render();            //renders the chunk immediately
        }
        //RequestSystem.terrainToRender.Add(chunk);
    }
Пример #4
0
    //deletes all pieces of the given chunk and reactivates it or "combines" all its pieces into it
    public void combineChunk(LODPos pos)
    {
        //reactivate the chunk
        chunks[pos].gameObject.SetActive(true);
        //Debug.Log(pos.ToString() + " was activated");


        //now find all of its pieces and destroy them

        //1 level lower
        int newLev = pos.level - 1;
        //the position of the first subchunk in this chunk
        WorldPos newStart = new WorldPos(pos.x * 2, pos.y * 2, pos.z * 2);

        for (int x = 0; x <= 1; x++)
        {
            for (int y = 0; y <= 1; y++)
            {
                for (int z = 0; z <= 1; z++)
                {
                    LODPos        newChunk = new LODPos(newLev, newStart.x + x, newStart.y + y, newStart.z + z);
                    TerrainObject tobj     = null;
                    if (chunks.TryGetValue(newChunk, out tobj))
                    {
                        //if the chunk to be deleted is split, combine it first
                        if (splitChunks.Contains(newChunk))
                        {
                            combineChunk(newChunk);
                        }

                        //remove it from vischunks
                        visChunks.Remove(newChunk);

                        //remove from chunkstosplitrender if it is in it
                        if (chunksToSplitRender.Contains(newChunk))
                        {
                            chunksToSplitRender.Remove(newChunk);
                        }

                        //finally remove from the chunks dictionary and utterly DESTROY IT (but it will later be pooled
                        chunks.Remove(newChunk);
                        //Object.Destroy(tobj);
                        Pool.deleteTerrain(tobj);
                        //Debug.Log("chunk " + newChunk.ToString() + " was deleted");
                    }
                }
            }
        }

        chunks[pos].isSplit = false;
        if (chunksToSplitRender.Contains(pos))
        {
            chunksToSplitRender.Remove(pos);
        }
        //move this from splitchunks to vischunks
        splitChunks.Remove(pos);
        visChunks.Add(pos);
    }
Пример #5
0
    //updates level of detail by subdividing/combining chunks
    //given a level 0 lodpos (which is just a worldpos)

    /*public void updateLOD(WorldPos pos)
     * {
     *      List<LODPos> chunksToSplit = new List<LODPos>();
     *      //for every chunk that is not split, check if it is close enough to be split
     *      foreach(LODPos lpos in visChunks)
     *      {
     *              //if the distance from the player's position to the lpos is close enough and its not a level 0 pos, add it to the split list
     *              if(lodposInRange(pos, lpos) && lpos.level > 0)
     *              {
     *                      //Debug.Log(lpos);
     *                      chunksToSplit.Add(lpos);
     *                      //break;
     *              }
     *      }
     *
     *
     *      List<LODPos> chunksToCombine = new List<LODPos>();
     *
     *      //for every chunk that is split, check if it is far enough to be combined
     *      foreach(LODPos lpos in splitChunks)
     *      {
     *              //Debug.Log(lpos.ToString() + " " + chunks.ContainsKey(lpos));
     *              if(!lodposInRange(pos, lpos))
     *                      chunksToCombine.Add(lpos);
     *      }
     *      //Debug.Log(splitChunks.Count + " " + chunksToCombine.Count);
     *
     *      for(int i=chunksToSplit.Count-1; i>=0; i--)
     *      {
     *              splitChunk(chunksToSplit[i]);
     *              //Debug.Log("Apparently a chunk was split");
     *      }
     *
     *      for(int i=chunksToCombine.Count-1; i>=0; i--)
     *      {
     *
     *              //Debug.Log(lpos.ToString() + " " + chunks.ContainsKey(lpos));
     *              //Debug.Log("a chunk is being combined");
     *              combineChunk(chunksToCombine[i]);
     *      }
     *
     *
     * }*/

    //is the lodpos close enough to be split up?
    bool lodposInRange(WorldPos pos, LODPos lpos)
    {
        //length of the side of lpos in units of 16 (or one side length of a level 0 lodpos)
        float sideLength = Mathf.Pow(2, lpos.level);

        //the distance from the chunk to the player's chunk
        float dist = Vector3.Distance(new Vector3(pos.x + .5f, pos.y + .5f, pos.z + .5f),
                                      new Vector3((lpos.x + .5f) * sideLength, (lpos.y + 0.5f) * sideLength, (lpos.z + .5f) * sideLength));

        //if the distance from the player's position to the lpos is less than its side length times some constant, return true
        return(dist < sideLength * 1.2);
    }
Пример #6
0
    //checks a single corner of a chunks to see if it is worthy of containing land
    bool pointContainsLand(float sideLength, Vector3 corner, LODPos pos, out bool insideLand)
    {
        //the position of the corner chunk in relation to the center in unity units
        Vector3 absPos = new Vector3(sideLength * (pos.x + corner.x),
                                     sideLength * (pos.y + corner.y),
                                     sideLength * (pos.z + corner.z));
        //altitude of land below or above this point
        float alt = planet.noise.getAltitude(absPos);

        //is the point underground
        insideLand = absPos.magnitude < alt;
        //contains land if the dist to center of lod chunk is within a side length of the altitude
        //NOTE: may later change it to half a side legth because the corners are closer
        return(absPos.magnitude < (alt + sideLength) && absPos.magnitude > (alt - sideLength));
    }
Пример #7
0
    //Get the unit chunk position of the current chunk that the player is in
    //basically it rounds every position down to the nearest 16
    //NOTE: Delete this later by migrating to unit converter method

/*	WorldPos posToChunk()
 *      {
 *
 *              WorldPos curChunkPos = new WorldPos (
 *                      Mathf.FloorToInt(transform.position.x / chunkSize)*chunkSize,
 *                      Mathf.FloorToInt(transform.position.y / chunkSize)*chunkSize,
 *                      Mathf.FloorToInt(transform.position.z / chunkSize)*chunkSize );
 *
 *              return curChunkPos;
 *      }*/

    //the size of a terrain chunk is the same as a request chunk to keep it organized, and makes requesting it fairly simple
    void requestTerrain(WorldPos pos)
    {
        //NOTE: NEED to migrate this over to the worldhelper buildobject function
        //UniverseSystem.curPlanet.terrain.CreateChunk(pos);
        //if(Time.time<3)

        //terrain chunks are on a unit scale rather than a 16 scale, so convert it
        LODPos adjustedPos = new LODPos(0, pos.x / 16, pos.y / 16, pos.z / 16);

        //request the level 0 lodchunk
        //only request it if it contains land!!!
        if (UniverseSystem.curPlanet.lod.containsLand(adjustedPos))
        {
            UniverseSystem.curPlanet.lod.requestChunk(adjustedPos);
        }
        //print(pos);
    }
Пример #8
0
    //generates a chunk if it will exist but first generates all chunk levels above it and subdivides them
    //returns true if the chunk is successfully created
    public bool requestChunk(LODPos pos)
    {
        //Debug.Log(pos.ToString());
        //if it is already built, we are done
        if (chunks.ContainsKey(pos))
        {
            return(true);
        }

        LODPos abovePos = getAbove(pos);

        if (chunks.ContainsKey(getAbove(pos)))
        {
            TerrainObject above = null;
            chunks.TryGetValue(abovePos, out above);

            //if it is already split, the current terrian chunk will never exist
            if (above.isSplit)
            {
                return(false);
            }
            else
            {
                //split the chunk and then check if the chunk exists now
                splitChunk(abovePos);
                return(chunks.ContainsKey(pos));
            }
        }
        else        //the above chunk does not exist
        {
            //request the above chunk to be generated, and if it is, split it and check if the current chunk is generated
            if (requestChunk(abovePos))
            {
                splitChunk(abovePos);
                return(chunks.ContainsKey(pos));
            }

            return(false);
        }
    }
Пример #9
0
    //renders the pieces of a chunk that has already been split
    public void splitRender(LODPos pos)
    {
        //if(!chunks.ContainsKey(pos))
        //	return;


        //Debug.Log("Chunks contains key :" + pos.ToString() + " " + chunks.ContainsKey(pos));
        //hide this terrain object but don't delete it
        //chunks[pos].gameObject.SetActive(false);

        //now find all of its pieces and render them

        //1 level lower
        int newLev = pos.level - 1;
        //the position of the first subchunk in this chunk
        WorldPos newStart = new WorldPos(pos.x * 2, pos.y * 2, pos.z * 2);

        //render all 8 chunks (that exist)
        for (int x = 0; x <= 1; x++)
        {
            for (int y = 0; y <= 1; y++)
            {
                for (int z = 0; z <= 1; z++)
                {
                    LODPos        newChunk = new LODPos(newLev, newStart.x + x, newStart.y + y, newStart.z + z);
                    TerrainObject tobj     = null;
                    if (chunks.TryGetValue(newChunk, out tobj))
                    {
                        tobj.Render();
                    }
                }
            }
        }

        //splitChunks.
        //Debug.Log(pos.ToString() + " is being splitrendered " + chunksToSplitRender.IndexOf(pos) + " " + chunksToSplitRender.LastIndexOf(pos));
        chunks[pos].gameObject.SetActive(false);
        //Debug.Log(pos.ToString() + " was deactivated");
    }
Пример #10
0
    //splits up a terrain chunk into 8 smaller chunks
    public void splitChunk(LODPos pos)
    {
        //	TerrainObject to;
        //don't do anything if the chunk list does not contain the pos
        //	if(!chunks.TryGetValue(pos, out to))
        //		return;

        //hide this terrain object but don't delete it
        //to.gameObject.SetActive(false);
        //1 level lower
        int newLev = pos.level - 1;
        //the position of the first subchunk in this chunk
        WorldPos newStart = new WorldPos(pos.x * 2, pos.y * 2, pos.z * 2);

        //build all of the 8 chunks that contain land
        for (int x = 0; x <= 1; x++)
        {
            for (int y = 0; y <= 1; y++)
            {
                for (int z = 0; z <= 1; z++)
                {
                    LODPos newChunk = new LODPos(newLev, newStart.x + x, newStart.y + y, newStart.z + z);
                    if (containsLand(newChunk))
                    {
                        CreateChunk(newChunk);
                    }
                }
            }
        }

        //it is now split, this is kind of a useless comment and the more i type the more time i waste soo um yeah. how's your day been reader of my code? I know this comment is getting unjustifiably long so I should probably stop typing it but i wont today is feb. 10 2016 and i am currently working on the lod system for this game. hopefully this game will get popular in the future which will cause me to hire employees and one of them will see this comment and think "what the heck?" but then they will laugh and show it to their coworker and call me in from my luxury office to ask me if i remember writing this comment
        chunks[pos].isSplit = true;
        splitChunks.Add(pos);
        visChunks.Remove(pos);
        //RequestSystem.terrainToSplitRender.Add(to);
        chunksToSplitRender.Add(pos);
        //Debug.Log(pos.ToString() + " was added to splitrenderlist");
    }
Пример #11
0
    //calculate the noise values and mesh data for each child chunk
    public void splitCalc(LODPos pos)
    {
        int newLev = pos.level - 1;
        //the position of the first subchunk in this chunk
        WorldPos newStart = new WorldPos(pos.x * 2, pos.y * 2, pos.z * 2);

        //render all 8 chunks (that exist)
        for (int x = 0; x <= 1; x++)
        {
            for (int y = 0; y <= 1; y++)
            {
                for (int z = 0; z <= 1; z++)
                {
                    LODPos        newChunk = new LODPos(newLev, newStart.x + x, newStart.y + y, newStart.z + z);
                    TerrainObject tobj     = null;
                    if (chunks.TryGetValue(newChunk, out tobj))
                    {
                        tobj.calculateNoise();
                        //tobj.calculateMesh();
                    }
                }
            }
        }
    }
Пример #12
0
    //initialize the gameObject's things
    //I'm losing touch with reality
    public void init(LODPos lpos, Planet p)
    {
        planet = p;
        pos    = lpos;
        //this lod chunk scale
        //level 0 has scale 1, level 1 has scale 2, level 2 has scale 4, etc.
        scale = (int)(Mathf.Pow(2, pos.level));       //TerrainObject.wsRatio;



        //positions and scales the gameobject (maybe should move this elsewhere)
        //if it should be in unispace
        if (pos.level > LODSystem.uniCutoff)
        {
            //add it to stellar and make its parent proud
            transform.SetParent(planet.scaledRep.transform);
            gameObject.layer = (int)spaces.Stellar;            //add to Unispace layer


            //finds the adjusted scale of this terrain obj when in stellar space
            float absScale = ((float)scale) / 10000;
            gameObject.transform.localScale = new Vector3(absScale, absScale, absScale) * TerrainObject.wsRatio;

            //the adjusted position of this terrain obj whin in unispace
            gameObject.transform.localPosition = pos.toVector3() * TerrainObject.chunkWidth * absScale;
            gameObject.transform.localRotation = Quaternion.identity;
        }
        else                      //it is in normal space
        {
            gameObject.layer = 0; //TODO:?
            //gameObject.transform.parent = null;
            gameObject.transform.localScale    = new Vector3(scale, scale, scale) * TerrainObject.wsRatio;
            gameObject.transform.localPosition = CoordinateHandler.planetSpace.getFloatingPos(pos.toVector3() * scale * TerrainObject.chunkWidth);
            //gameObject.transform.localRotation = Quaternion.identity;
        }
    }
Пример #13
0
 //overloaded createchunk
 public void CreateChunk(LODPos pos)
 {
     CreateChunk(pos, false);
 }
Пример #14
0
    //instantiates the unispace rep of the planet
    protected override void createRep()
    {
        scaledRep = new GameObject("Planet " + seed + "radius: " + radius);


        //the gameobject that holds the scaledRep's mesh data so it can be scaled
        GameObject meshobj = GameObject.CreatePrimitive(PrimitiveType.Sphere);

        meshobj.transform.SetParent(scaledRep.transform);
        GameObject.Destroy(meshobj.GetComponent <SphereCollider>());       //remove this pesky component


        scaledRep.layer = (int)spaces.Stellar;        //add to Unispace layer
        meshobj.layer   = (int)spaces.Stellar;

        //arbitrary unipos for testing
        scaledRep.transform.position = CoordinateHandler.stellarSpace.getFloatingPos(scaledPos);
        //scaledRep.transform.rotation = Quaternion.Euler(0,45,0);
        scaledRep.transform.rotation = Quaternion.Euler(0, 0, 0);

        meshobj.transform.localScale = new Vector3(scaledRadius * 2, scaledRadius * 2, scaledRadius * 2);

        /*for(int x = -1; x <= 0; x++)
         *      for(int y = -1; y <= 0; y++)
         *              for(int z = -1; z <= 0; z++)
         *              {
         *                      LODPos lp = new LODPos(startLev, x, y, z);
         *                      lod.CreateChunk(lp, true);
         *                      lod.splitChunk(lp);
         *                      lod.splitCalc(lp);
         *                      lod.splitRender(lp);
         *              }*/
        //build all the starting lev chunks
        for (int x = -2; x <= 1; x++)
        {
            for (int y = -2; y <= 1; y++)
            {
                for (int z = -2; z <= 1; z++)
                {
                    LODPos lp = new LODPos(startLev, x, y, z);
                    if (lod.containsLand(lp))
                    {
                        lod.CreateChunk(lp, true);
                        lod.splitChunk(lp);
                        lod.splitCalc(lp);
                        lod.splitRender(lp);
                    }
                }
            }
        }

        startLev--;
        //lod.splitChunk(new LODPos(14,0,0,0));
        //lod.splitChunk(new LODPos(13,1,1,1));
        //lod.requestChunk(new LODPos(0, 3000,5400,9000));

        //Debug.Log(lod.containsLand(new LODPos(14,0,0,0)));
        //Debug.Log(lod.containsLand(new LODPos(12,3,3,3)));


        //add some fun color
        meshobj.GetComponent <MeshRenderer>().material = Resources.Load("Water") as Material;       //loads the default material, will remove this
        meshobj.SetActive(false);
    }