Ejemplo n.º 1
0
 public FImp_ColliderData_Terrain(TerrainCollider collider)
 {
     Collider         = collider;
     TerrCollider     = collider;
     ColliderType     = EFColliderType.Terrain;
     TerrainComponent = collider.GetComponent <Terrain>();
 }
Ejemplo n.º 2
0
        public static void PushOutFromTerrain(TerrainCollider terrainCollider, float segmentRadius, ref Vector3 point)
        {
            Terrain terrain = terrainCollider.GetComponent <Terrain>();

            Vector3 rayOrigin = point;

            rayOrigin.y = terrainCollider.transform.position.y + terrain.SampleHeight(point) + segmentRadius;

            Ray ray = new Ray(rayOrigin, Vector3.down);

            RaycastHit hit;

            if (terrainCollider.Raycast(ray, out hit, segmentRadius * 2f))
            {
                float hitToPointDist = (point - hit.point).magnitude;

                float underMul = 1f;
                if (hit.point.y > point.y + segmentRadius * 0.9f)
                {
                    underMul = 8f;
                }
                else
                if (hit.point.y > point.y)
                {
                    underMul = 4f;
                }

                if (hitToPointDist < segmentRadius * underMul)
                {
                    Vector3 toNormal = hit.point - point;
                    Vector3 pushNormal;

                    if (underMul > 1f)
                    {
                        pushNormal = toNormal + toNormal.normalized * segmentRadius;
                    }
                    else
                    {
                        pushNormal = toNormal - toNormal.normalized * segmentRadius;
                    }
                    point = point + pushNormal;
                }
            }
        }
        private void Update()
        {
            if (Input.GetKeyDown(KeyCode.C))
            {
                // Remove all projectors.
                while (m_DecalProjectors.Count > 0)
                {
                    m_DecalsMesh.ClearAll();
                    m_DecalProjectors.Clear();

                    // Clearing of the decals mesh means we need to initialize it again.
                    m_DecalsMesh.Initialize(m_DecalsInstance);
                }
                m_DecalsInstance.UpdateDecalsMeshes(m_DecalsMesh);
            }

            if (Input.GetButtonDown("Fire1"))
            {
                Ray        l_Ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.0f));
                RaycastHit l_RaycastHit;
                if (Physics.Raycast(l_Ray, out l_RaycastHit, Mathf.Infinity))
                {
                    // Collider hit.

                    // Make sure there are not too many projectors.
                    if (m_DecalProjectors.Count >= m_MaximumNumberOfProjectors)
                    {
                        // If there are more than the maximum number of projectors, we delete
                        // the oldest one.
                        DecalProjector l_DecalProjector = m_DecalProjectors [0];
                        m_DecalProjectors.RemoveAt(0);
                        m_DecalsMesh.RemoveProjector(l_DecalProjector);
                    }

                    // Calculate the position and rotation for the new decal projector.
                    Vector3    l_ProjectorPosition = l_RaycastHit.point - (m_DecalProjectorOffset * l_Ray.direction.normalized);
                    Quaternion l_ProjectorRotation = ProjectorRotationUtility.ProjectorRotation(Camera.main.transform.forward, Vector3.up);

                    // Randomize the rotation.
                    Quaternion l_RandomRotation = Quaternion.Euler(0.0f, Random.Range(0.0f, 360.0f), 0.0f);
                    l_ProjectorRotation = l_ProjectorRotation * l_RandomRotation;

                    TerrainCollider l_TerrainCollider = l_RaycastHit.collider as TerrainCollider;
                    if (l_TerrainCollider != null)
                    {
                        // Terrain collider hit.

                        Terrain l_Terrain = l_TerrainCollider.GetComponent <Terrain> ();
                        if (l_Terrain != null)
                        {
                            // Create the decal projector with all the required information.
                            DecalProjector l_DecalProjector = new DecalProjector(l_ProjectorPosition, l_ProjectorRotation, m_DecalProjectorScale, m_CullingAngle, m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex);

                            // Add the projector to our list and the decals mesh, such that both are
                            // synchronized. All the mesh data that is now added to the decals mesh
                            // will belong to this projector.
                            m_DecalProjectors.Add(l_DecalProjector);
                            m_DecalsMesh.AddProjector(l_DecalProjector);

                            // The terrain data has to be converted to the decals instance's space.
                            Matrix4x4 l_TerrainToDecalsMatrix = m_WorldToDecalsMatrix * Matrix4x4.TRS(l_Terrain.transform.position, Quaternion.identity, Vector3.one);

                            // Pass the terrain data with the corresponding conversion to the decals mesh.
                            m_DecalsMesh.Add(l_Terrain, l_TerrainToDecalsMatrix);

                            // Cut and offset the decals mesh.
                            m_DecalsMeshCutter.CutDecalsPlanes(m_DecalsMesh);
                            m_DecalsMesh.OffsetActiveProjectorVertices();

                            // The changes are only present in the decals mesh at the moment. We have
                            // to pass them to the decals instance to visualize them.
                            m_DecalsInstance.UpdateDecalsMeshes(m_DecalsMesh);

                            // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
                            // based on the surface you have hit.
                            NextUVRectangleIndex();
                        }
                        else
                        {
                            Debug.LogError("Terrain is null!");
                        }
                    }
                    else
                    {
                        // We hit a collider. Next we have to find the mesh that belongs to the collider.
                        // That step depends on how you set up your mesh filters and collider relative to
                        // each other in the game objects. It is important to have a consistent way in order
                        // to have a simpler implementation.

                        MeshCollider l_MeshCollider = l_RaycastHit.collider.GetComponent <MeshCollider> ();
                        MeshFilter   l_MeshFilter   = l_RaycastHit.collider.GetComponent <MeshFilter> ();

                        if (l_MeshCollider != null || l_MeshFilter != null)
                        {
                            Mesh l_Mesh = null;
                            if (l_MeshCollider != null)
                            {
                                // Mesh collider was hit. Just use the mesh data from that one.
                                l_Mesh = l_MeshCollider.sharedMesh;
                            }
                            else if (l_MeshFilter != null)
                            {
                                // Otherwise take the data from the shared mesh.
                                l_Mesh = l_MeshFilter.sharedMesh;
                            }

                            if (l_Mesh != null)
                            {
                                // Create the decal projector.
                                DecalProjector l_DecalProjector = new DecalProjector(l_ProjectorPosition, l_ProjectorRotation, m_DecalProjectorScale, m_CullingAngle, m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex);

                                // Add the projector to our list and the decals mesh, such that both are
                                // synchronized. All the mesh data that is now added to the decals mesh
                                // will belong to this projector.
                                m_DecalProjectors.Add(l_DecalProjector);
                                m_DecalsMesh.AddProjector(l_DecalProjector);

                                // Get the required matrices.
                                Matrix4x4 l_WorldToMeshMatrix = l_RaycastHit.collider.renderer.transform.worldToLocalMatrix;
                                Matrix4x4 l_MeshToWorldMatrix = l_RaycastHit.collider.renderer.transform.localToWorldMatrix;

                                // Add the mesh data to the decals mesh, cut and offset it.
                                m_DecalsMesh.Add(l_Mesh, l_WorldToMeshMatrix, l_MeshToWorldMatrix);
                                m_DecalsMeshCutter.CutDecalsPlanes(m_DecalsMesh);
                                m_DecalsMesh.OffsetActiveProjectorVertices();

                                // The changes are only present in the decals mesh at the moment. We have
                                // to pass them to the decals instance to visualize them.
                                m_DecalsInstance.UpdateDecalsMeshes(m_DecalsMesh);

                                // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
                                // based on the surface you have hit.
                                NextUVRectangleIndex();
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 4
0
    private void Update()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            Ray        l_Ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0.0f));
            RaycastHit l_RaycastHit;
            if (Physics.Raycast(l_Ray, out l_RaycastHit, Mathf.Infinity))
            {
                // Collider hit.

                // Make sure there are not too many projectors.
                if (m_DecalProjectors.Count >= 50)
                {
                    // If there are more than 50 projectors, we remove the first one from
                    // our list and certainly from the decals mesh (the intermediate mesh
                    // format). All the mesh data that belongs to this projector will
                    // be removed.
                    DecalProjector l_DecalProjector = m_DecalProjectors [0];

                    // The vertex color list has to be updated as well.
                    m_VertexColors.RemoveRange(0, l_DecalProjector.DecalsMeshUpperVertexIndex + 1);

                    m_DecalProjectors.RemoveAt(0);
                    m_DecalsMesh.RemoveProjector(l_DecalProjector);
                }

                // Calculate the position and rotation for the new decal projector.
                Vector3    l_ProjectorPosition = l_RaycastHit.point - (decalProjectorOffset * l_Ray.direction.normalized);
                Vector3    l_ForwardDirection  = Camera.main.transform.up;
                Vector3    l_UpDirection       = -Camera.main.transform.forward;
                Quaternion l_ProjectorRotation = Quaternion.LookRotation(l_ForwardDirection, l_UpDirection);

                // Randomize the rotation.
                Quaternion l_RandomRotation = Quaternion.Euler(0.0f, Random.Range(0.0f, 360.0f), 0.0f);
                l_ProjectorRotation = l_ProjectorRotation * l_RandomRotation;

                TerrainCollider l_TerrainCollider = l_RaycastHit.collider as TerrainCollider;
                if (l_TerrainCollider != null)
                {
                    // Terrain collider hit.

                    Terrain l_Terrain = l_TerrainCollider.GetComponent <Terrain> ();
                    if (l_Terrain != null)
                    {
                        // Create the decal projector with all the required information.
                        DecalProjector l_DecalProjector = new DecalProjector(l_ProjectorPosition, l_ProjectorRotation, decalProjectorScale, cullingAngle, meshOffset, m_UVRectangleIndex, m_UVRectangleIndex);

                        // Add the projector to our list and the decals mesh, such that both are
                        // synchronized. All the mesh data that is now added to the decals mesh
                        // will belong to this projector.
                        m_DecalProjectors.Add(l_DecalProjector);
                        m_DecalsMesh.AddProjector(l_DecalProjector);

                        // The terrain data has to be converted to the decals instance's space.
                        Matrix4x4 l_TerrainToDecalsMatrix = Matrix4x4.TRS(l_Terrain.transform.position, Quaternion.identity, Vector3.one) * m_WorldToDecalsMatrix;

                        // Pass the terrain data with the corresponding conversion to the decals mesh.
                        m_DecalsMesh.Add(l_Terrain, l_TerrainToDecalsMatrix);

                        // Cut the data in the decals mesh accoring to the size and position of the decal projector. Offset the
                        // vertices afterwards and pass the newly computed mesh to the decals instance, such that it becomes
                        // visible.
                        m_DecalsMeshCutter.CutDecalsPlanes(m_DecalsMesh);
                        m_DecalsMesh.OffsetActiveProjectorVertices();
                        m_Decals.UpdateDecalsMeshes(m_DecalsMesh);

                        // Update the vertex colors too.
                        Color l_VertexColor = CurrentColor;
                        int   l_VertexCount = l_DecalProjector.DecalsMeshUpperVertexIndex - l_DecalProjector.DecalsMeshLowerVertexIndex + 1;
                        for (int i = 0; i < l_VertexCount; i = i + 1)
                        {
                            m_VertexColors.Add(l_VertexColor);
                        }
                        m_Decals.DecalsMeshRenderers [0].MeshFilter.mesh.colors = m_VertexColors.ToArray();

                        // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
                        // based on the surface you have hit.
                        NextUVRectangleIndex();
                        NextColorIndex();
                    }
                    else
                    {
                        Debug.Log("Terrain is null!");
                    }
                }
                else
                {
                    // We hit a collider. Next we have to find the mesh that belongs to the collider.
                    // That step depends on how you set up your mesh filters and collider relative to
                    // each other in the game objects. It is important to have a consistent way in order
                    // to have a simpler implementation.

                    MeshCollider l_MeshCollider = l_RaycastHit.collider.GetComponent <MeshCollider> ();
                    MeshFilter   l_MeshFilter   = l_RaycastHit.collider.GetComponent <MeshFilter> ();

                    if (l_MeshCollider != null || l_MeshFilter != null)
                    {
                        Mesh l_Mesh = null;
                        if (l_MeshCollider != null)
                        {
                            // Mesh collider was hit. Just use the mesh data from that one.
                            l_Mesh = l_MeshCollider.sharedMesh;
                        }
                        else if (l_MeshFilter != null)
                        {
                            // Otherwise take the data from the shared mesh.
                            l_Mesh = l_MeshFilter.sharedMesh;
                        }

                        if (l_Mesh != null)
                        {
                            // Create the decal projector.
                            DecalProjector l_DecalProjector = new DecalProjector(l_ProjectorPosition, l_ProjectorRotation, decalProjectorScale, cullingAngle, meshOffset, m_UVRectangleIndex, m_UVRectangleIndex);

                            // Add the projector to our list and the decals mesh, such that both are
                            // synchronized. All the mesh data that is now added to the decals mesh
                            // will belong to this projector.
                            m_DecalProjectors.Add(l_DecalProjector);
                            m_DecalsMesh.AddProjector(l_DecalProjector);

                            // Get the required matrices.
                            Matrix4x4 l_WorldToMeshMatrix = l_RaycastHit.collider.renderer.transform.worldToLocalMatrix;
                            Matrix4x4 l_MeshToWorldMatrix = l_RaycastHit.collider.renderer.transform.localToWorldMatrix;

                            // Add the mesh data to the decals mesh, cut and offset it before we pass it
                            // to the decals instance to be displayed.
                            m_DecalsMesh.Add(l_Mesh, l_WorldToMeshMatrix, l_MeshToWorldMatrix);
                            m_DecalsMeshCutter.CutDecalsPlanes(m_DecalsMesh);
                            m_DecalsMesh.OffsetActiveProjectorVertices();
                            m_Decals.UpdateDecalsMeshes(m_DecalsMesh);

                            // Update the vertex colors too.
                            Color l_VertexColor = CurrentColor;
                            int   l_VertexCount = l_DecalProjector.DecalsMeshUpperVertexIndex - l_DecalProjector.DecalsMeshLowerVertexIndex + 1;
                            for (int i = 0; i < l_VertexCount; i = i + 1)
                            {
                                m_VertexColors.Add(l_VertexColor);
                            }
                            m_Decals.DecalsMeshRenderers [0].MeshFilter.mesh.colors = m_VertexColors.ToArray();

                            // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
                            // based on the surface you have hit.
                            NextUVRectangleIndex();
                            NextColorIndex();
                        }
                    }
                }
            }
        }
    }