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. SkinnedDecalProjector 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; // 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. SkinnedMeshRenderer l_SkinnedMeshRenderer = l_RaycastHit.collider.GetComponent <SkinnedMeshRenderer> (); if (l_SkinnedMeshRenderer != null) { Mesh l_Mesh = null; l_Mesh = l_SkinnedMeshRenderer.sharedMesh; if (l_Mesh != null) { // Create the decal projector. SkinnedDecalProjector l_DecalProjector = new SkinnedDecalProjector(l_ProjectorPosition, l_ProjectorRotation, m_DecalProjectorScale, m_CullingAngle, m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex, CurrentColor, 0.0f); // 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_SkinnedMeshRenderer.bones, l_SkinnedMeshRenderer.quality, 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(); NextColorIndex(); } } } } }
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. SkinnedDecalProjector 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; // 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. SkinnedMeshRenderer l_SkinnedMeshRenderer = l_RaycastHit.collider.GetComponent <SkinnedMeshRenderer> (); if (l_SkinnedMeshRenderer != null) { Mesh l_Mesh = null; l_Mesh = l_SkinnedMeshRenderer.sharedMesh; if (l_Mesh != null) { // Create the decal projector. SkinnedDecalProjector l_DecalProjector = new SkinnedDecalProjector (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_SkinnedMeshRenderer.bones, l_SkinnedMeshRenderer.quality, 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 (); } } } } }