Пример #1
0
    /// <summary>
    /// Create a new empty CachedMeshHolder
    /// </summary>
    private CachedMeshHolder CreateNewBlock(QuadTreeNode <NodeData> node)
    {
        GameObject block = GameObject.Instantiate(BlockPrefab);

        block.name = "Block_" + node.Depth;
        block.transform.SetParent(gameObject.transform);
        block.transform.localPosition = node.Position - node.Size * new Vector3(0.5f, 0, 0.5f);
        block.transform.localScale    = new Vector3(node.Size, 1, node.Size);

        Mesh blockMesh = meshGenerator.BuildPatch(node.Position, node.Size, ResolutionMultiplier, HeightMap, HeightMultiplier);

        //blockMesh.RecalculateNormals(); // TO DO: place these heavy calculations somewhere else
        blockMesh.RecalculateBounds(); // TO DO: place these heavy calculations somewhere else
        block.GetComponent <MeshFilter>().mesh = blockMesh;
        //block.GetComponent<MeshFilter>().mesh.bounds = new Bounds(Vector3.zero, new Vector3(1, 0.5f, 1) * node.Size * 0.4f);
        block.GetComponent <MeshCollider>().sharedMesh = blockMesh;
        block.GetComponent <MeshRenderer>().material   = TerrainMaterial;

        CachedMeshHolder holder = new CachedMeshHolder()
        {
            gameObject = block,
            filter     = gameObject.GetComponent <MeshFilter>(),
            collider   = gameObject.GetComponent <MeshCollider>(),
            renderer   = gameObject.GetComponent <MeshRenderer>()
        };

        return(holder);
    }
Пример #2
0
    /// <summary>
    /// Either creates or shows the already existing mesh corresponding to this node
    /// </summary>
    private void ShowNode(QuadTreeNode <NodeData> node, HashSet <QuadTreeNode <NodeData> > newActiveNodes)
    {
        if (RenderTerrain)
        {
            // If there isn't already a mesh linked to this node
            if (RenderTerrain && !nodeMeshMap.ContainsKey(node))
            {
                // Create an empty mesh holder object
                CachedMeshHolder container = CreateNewBlock(node);

                // Set chunk data...?
                // ...

                // Call highest detail action...?
                // ...

                // Add the newly created mesh to the lists
                activeMeshes.Add(container);
                nodeMeshMap[node] = container;
            }

            // Show the mesh
            nodeMeshMap[node].gameObject.SetActive(true);
        }

        // If the newActiveNodes don't already contain this node, add it
        if (!newActiveNodes.Contains(node))
        {
            newActiveNodes.Add(node);
        }
    }
Пример #3
0
        /// <summary>
        /// Pop an unused container from the queue, or generate new containers if required
        /// </summary>
        /// <returns></returns>
        private CachedMeshHolder PopMeshContainer()
        {
            while (meshPool.Count < 3)
            {
                GameObject g = new GameObject("Chunk");
                g.transform.SetParent(go.transform);
                g.transform.localPosition = Vector3.zero;

                MeshFilter meshFilter = g.AddComponent <MeshFilter>();
                Mesh       m          = new Mesh();
                m.name = "Cached Chunk Mesh";
                meshFilter.sharedMesh = m;

                MeshRenderer meshRenderer = g.AddComponent <MeshRenderer>();
                meshRenderer.sharedMaterial = this.material;
                g.SetActive(false);

                MeshCollider collider = g.AddComponent <MeshCollider>();
                collider.enabled = false;

                CachedMeshHolder holder = new CachedMeshHolder();
                holder.gameObject = g;
                holder.filter     = meshFilter;
                holder.collider   = collider;

                meshPool.Enqueue(holder);
            }

            CachedMeshHolder container = meshPool.Dequeue();

            return(container);
        }
Пример #4
0
        private void ShowNode(QuadNode <ChunkData> node, HashSet <QuadNode <ChunkData> > activeList)
        {
            if (!chunkMeshMap.ContainsKey(node))
            {
                //Buffer
                CachedMeshHolder container = PopMeshContainer();
                MeshFilter       filter    = container.filter;

                //Populate mesh
                filter.sharedMesh = meshService.Make(node.range.a, node.range.b, node.range.d, node.range.c, this.radius).mesh;
                //filter.sharedMesh = SubPlane.Make(node.range.a, node.range.b, node.range.d, node.range.c, resolution);

                //Set chunk data if it was never computed before
                if (node.value.bounds == null)
                {
                    node.value.bounds        = new Sphere(Vector3.zero, 1);
                    node.value.bounds.center = filter.sharedMesh.bounds.center;

                    /*node.value.bounds.radius = Mathf.Max (
                     *      filter.sharedMesh.bounds.extents.x,
                     *      filter.sharedMesh.bounds.extents.y,
                     *      filter.sharedMesh.bounds.extents.z
                     * );*/
                    node.value.bounds.radius = Mathf.Sqrt(
                        filter.sharedMesh.bounds.extents.x * filter.sharedMesh.bounds.extents.x +
                        filter.sharedMesh.bounds.extents.y * filter.sharedMesh.bounds.extents.y +
                        filter.sharedMesh.bounds.extents.z * filter.sharedMesh.bounds.extents.z
                        );
                }

                //Show node
                filter.gameObject.SetActive(true);

                //Call highest detail action
                if (node.depth == this.maxDepth)
                {
                    //Call listeners if exists
                    foreach (System.Action <QuadNode <ChunkData> > fn in this.listeners)
                    {
                        fn.Invoke(node);
                    }
                    //Call detailing service if available
                    if (detailService != null)
                    {
                        detailService.ShowChunkDetails(node, filter.sharedMesh);
                    }
                }

                //Add me if I don't already exist
                this.activeMeshes.Add(container);
                this.chunkMeshMap[node] = container;
            }
            if (!activeList.Contains(node))
            {
                activeList.Add(node);
            }
        }
Пример #5
0
        private void ShowNodeSplit(QuadNode <ChunkData> parent, MeshData[] meshes, HashSet <QuadNode <ChunkData> > activeList)
        {
            for (int i = 0; i < 4; i++)
            {
                QuadNode <ChunkData> child = parent[(Quadrant)i];
                if (!chunkMeshMap.ContainsKey(child))
                {
                    //Buffer
                    CachedMeshHolder container = PopMeshContainer();
                    MeshFilter       filter    = container.filter;
                    filter.sharedMesh             = meshes[i].mesh;
                    container.collider.sharedMesh = filter.sharedMesh;
                    container.collider.enabled    = true;

                    container.renderer.sharedMaterial = textureService.GetMaterialFor(this, child, filter.sharedMesh);

                    if (child.value.bounds == null)
                    {
                        child.value.bounds        = new Sphere(Vector3.zero, 1);
                        child.value.bounds.center = filter.sharedMesh.bounds.center;
                        child.value.bounds.radius = Mathf.Sqrt(
                            filter.sharedMesh.bounds.extents.x * filter.sharedMesh.bounds.extents.x +
                            filter.sharedMesh.bounds.extents.y * filter.sharedMesh.bounds.extents.y +
                            filter.sharedMesh.bounds.extents.z * filter.sharedMesh.bounds.extents.z
                            );
                    }

                    //Show node
                    filter.gameObject.SetActive(true);

                    //Call highest detail action
                    if (child.depth == this.maxDepth)
                    {
                        //Call listeners if exists
                        foreach (System.Action <QuadNode <ChunkData> > fn in this.listeners)
                        {
                            fn.Invoke(child);
                        }
                        //Call detailing service if available
                        if (detailService != null)
                        {
                            detailService.ShowChunkDetails(child, filter.sharedMesh);
                        }
                    }

                    //Add me if I don't already exist
                    this.activeMeshes.Add(container);
                    this.chunkMeshMap[child] = container;
                }
                if (!activeList.Contains(child))
                {
                    activeList.Add(child);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Pop an unused container from the queue, or generate new containers if required
        /// </summary>
        /// <returns></returns>
        private CachedMeshHolder PopMeshContainer()
        {
            PoolablePool meshPool = PoolManager.Current.CustomPool(PlanetFacePoolTag, 3, 3);

            while (meshPool.Count < 3)
            {
                GameObject g = new GameObject("Chunk");
                g.transform.SetParent(go.transform);
                g.transform.localPosition = Vector3.zero;
                g.transform.localScale    = Vector3.one;

                MeshFilter meshFilter = g.AddComponent <MeshFilter>();
                Mesh       m          = new Mesh();
                m.name = "Cached Chunk Mesh";
                meshFilter.sharedMesh = m;

                MeshRenderer meshRenderer = g.AddComponent <MeshRenderer>();
                meshRenderer.sharedMaterial = null;
                g.SetActive(false);

                MeshCollider collider = g.AddComponent <MeshCollider>();
                //collider.enabled = false;

                CachedMeshHolder holder = new CachedMeshHolder();
                holder.gameObject = g;
                holder.filter     = meshFilter;
                holder.collider   = collider;
                holder.renderer   = meshRenderer;

                meshPool.Push(holder);
            }

            CachedMeshHolder container = (CachedMeshHolder)meshPool.Pop();

            if (container.gameObject.transform.parent != go.transform)
            {
                container.gameObject.transform.SetParent(go.transform);
                container.gameObject.transform.localPosition = Vector3.zero;
                container.gameObject.transform.localScale    = Vector3.one;
            }
            return(container);
        }
Пример #7
0
    /// <summary>
    /// Basically ShowNode(...) but it runs 4 times, once for each child of the passed node
    /// </summary>
    private void ShowNodeSplit(QuadTreeNode <NodeData> node, HashSet <QuadTreeNode <NodeData> > newActiveNodes)
    {
        for (int i = 0; i < 4; i++)
        {
            QuadTreeNode <NodeData> subNode = node.SubNodes[i];

            if (RenderTerrain)
            {
                // If there is no mesh corresponding to this node
                if (RenderTerrain && !nodeMeshMap.ContainsKey(subNode))
                {
                    // Create an empty mesh holder object
                    CachedMeshHolder container = CreateNewBlock(subNode);

                    // Set chunk data...?
                    // ...

                    // Call highest detail action...?
                    // ...

                    // Add the newly created mesh to the lists
                    activeMeshes.Add(container);
                    nodeMeshMap[subNode] = container;
                }

                // Show the subNode mesh
                nodeMeshMap[subNode].gameObject.SetActive(true);
            }

            // If the newActiveNodes don't already contain this node, add it
            if (!newActiveNodes.Contains(subNode))
            {
                newActiveNodes.Add(subNode);
            }
        }

        // Discard the parent mesh
        DiscardNode(node);
    }
Пример #8
0
    /// <summary>
    /// Merges 4 nodes into their parent
    /// </summary>
    private void ShowNodeMerge(QuadTreeNode <NodeData> node, HashSet <QuadTreeNode <NodeData> > newActiveList)
    {
        if (RenderTerrain)
        {
            // If there is no mesh corresponding to this node
            if (!nodeMeshMap.ContainsKey(node))
            {
                // Create an empty mesh holder object
                CachedMeshHolder container = CreateNewBlock(node);

                // Set chunk data...?
                // ...

                // Call highest detail action...?
                // ...

                // Add the newly created mesh to the lists
                activeMeshes.Add(container);

                nodeMeshMap[node] = container;
            }

            // Show the node mesh
            nodeMeshMap[node].gameObject.SetActive(true);
        }

        // Discard children nodes
        foreach (var subNode in node.SubNodes)
        {
            DiscardNode(subNode);
        }

        // If the newActiveNodes don't already contain this node, add it
        if (!newActiveList.Contains(node))
        {
            newActiveList.Add(node);
        }
    }