Search Unity

Decal System

Discussion in 'Assets and Asset Store' started by Dantus, Jun 29, 2012.

  1. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I don't know which version you are using. A reliable way is to have a look at the bullet example demos and check how the rotation is computed there.
     
  2. Alex_Kun90

    Alex_Kun90

    Joined:
    Mar 19, 2014
    Posts:
    10
    I'm the last version of decals , but i don't know how i made it for the collision of decals on the ground, There is the new code

     
  3. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    What's relevant for you is this line:
    Code (csharp):
    1. Quaternion l_ProjectorRotation = ProjectorRotationUtility.ProjectorRotation (Camera.main.transform.forward, Vector3.up);
    You can compare this to the Quaternion.LookRotation, but it does a correcting adjustment for the projector.

    If you use code tags, the code becomes much more readable and it becomes possible to refer to line numbers:
    http://forum.unity3d.com/threads/143875-Using-code-tags-properly
     
  4. Alex_Kun90

    Alex_Kun90

    Joined:
    Mar 19, 2014
    Posts:
    10
    There is my code , but I don't understand how to collide the raycast to down...

    Code (csharp):
    1.  
    2. public class BullettGround : MonoBehaviour
    3.     {
    4.         public GameObject player;
    5.         // The prefab with the ready to use DS_Decals. The material and uv rectangles are set up.
    6.         [SerializeField] private DS_Decals m_DecalsPrefab = null;
    7.        
    8.         // The reference to the instantiated prefab's DS_Decals instance.
    9.         private DS_Decals m_DecalsInstance;
    10.         private Matrix4x4 m_WorldToDecalsMatrix;
    11.        
    12.         // We keep track of the projectors that we are creating at runtime. If we have more than
    13.         // the maximum number of projectors, we remove the oldest ones.
    14.         private List <DecalProjector> m_DecalProjectors = new List <DecalProjector> ();
    15.         [SerializeField] private int m_MaximumNumberOfProjectors = 50;
    16.        
    17.         // We need a decals mesh and a cutter to create the decal projectors at runtime.
    18.         private DecalsMesh m_DecalsMesh;
    19.         private DecalsMeshCutter m_DecalsMeshCutter;
    20.        
    21.         // We can't place the projector exactly at the place where the raycast hits a collider. Instead,
    22.         // it needs to be moved back, such that the projection looks believable. This value indicates how
    23.         // many units the projector needs to be moved back.
    24.         [SerializeField] private float m_DecalProjectorOffset = 0.5f;
    25.        
    26.         // The size, culling angle and mesh offset for the decal projectors for the bullets we are about to
    27.         // create at runtime.
    28.         [SerializeField] private Vector3 m_DecalProjectorScale = new Vector3 (0.2f, 2.0f, 0.2f);
    29.         [SerializeField] private float m_CullingAngle = 80.0f;
    30.         [SerializeField] private float m_MeshOffset = 0.0f;
    31.        
    32.         // We iterate through all the defined uv rectangles. This one inicates which index we are using at
    33.         // the moment.
    34.         private int m_UVRectangleIndex = 0;
    35.        
    36.         // Move on to the next uv rectangle index. We call this method after each projection. In practice
    37.         // you certainly don't do that, but pick an appropriate one depending on the surface that was hit.
    38.         private void NextUVRectangleIndex ()
    39.         {
    40.             m_UVRectangleIndex = m_UVRectangleIndex + 1;
    41.             if (m_UVRectangleIndex >= m_DecalsInstance.CurrentUvRectangles.Length)
    42.             {
    43.                 m_UVRectangleIndex = 0;
    44.             }
    45.         }
    46.        
    47.         private void Start ()
    48.         {
    49.            
    50.             // Instantiate the prefab and get its decals instance.
    51.             m_DecalsInstance = Instantiate (m_DecalsPrefab) as DS_Decals;
    52.            
    53.             if (m_DecalsInstance == null)
    54.             {
    55.                 Debug.LogError ("The decals prefab does not contain a DS_Decals instance!");
    56.             }
    57.             else
    58.             {
    59.                
    60.                 // Create the decals mesh and the cutter that are needed to compute the projections.
    61.                 // We also cache the world to decals matrix.
    62.                 m_DecalsMesh = new DecalsMesh (m_DecalsInstance);
    63.                 m_DecalsMeshCutter = new DecalsMeshCutter ();
    64.                 m_WorldToDecalsMatrix = m_DecalsInstance.CachedTransform.worldToLocalMatrix;
    65.             }
    66.         }
    67.        
    68.         private void Update ()
    69.         {
    70.            
    71.         /*  if (Input.GetKeyDown (KeyCode.C))
    72.             {
    73.                
    74.                 // Remove all projectors.
    75.                 while (m_DecalProjectors.Count > 0)
    76.                 {
    77.                     m_DecalsMesh.ClearAll ();
    78.                     m_DecalProjectors.Clear ();
    79.                    
    80.                     // Clearing of the decals mesh means we need to initialize it again.
    81.                     m_DecalsMesh.Initialize (m_DecalsInstance);
    82.                 }
    83.                 m_DecalsInstance.UpdateDecalsMeshes (m_DecalsMesh);
    84.             }*/
    85.            
    86.             Vector3 posit = player.transform.position;
    87.  
    88.  
    89.             if (Input.GetButtonDown ("Fire1"))
    90.             {
    91.                 Ray l_Ray = Camera.main.ViewportPointToRay (new Vector3 (0.5f, 0.5f, 0.0f));
    92.                 RaycastHit l_RaycastHit;
    93.                
    94.                 if (Physics.Raycast (l_Ray, out l_RaycastHit, Mathf.Infinity))
    95.                 {
    96.                    
    97.                     // Collider hit.
    98.                    
    99.                     // Make sure there are not too many projectors.
    100.                     if (m_DecalProjectors.Count >= m_MaximumNumberOfProjectors)
    101.                     {
    102.                        
    103.                         // If there are more than the maximum number of projectors, we delete
    104.                         // the oldest one.
    105.                         DecalProjector l_DecalProjector = m_DecalProjectors [0];
    106.                         m_DecalProjectors.RemoveAt (0);
    107.                         m_DecalsMesh.RemoveProjector (l_DecalProjector);
    108.                     }
    109.                    
    110.                     // Calculate the position and rotation for the new decal projector.
    111.                     Vector3 l_ProjectorPosition = l_RaycastHit.point - (m_DecalProjectorOffset * l_Ray.direction.normalized);
    112.                     Quaternion l_ProjectorRotation = ProjectorRotationUtility.ProjectorRotation (Camera.main.transform.forward, Vector3.up);
    113.                    
    114.                     // Randomize the rotation.
    115.                     Quaternion l_RandomRotation = Quaternion.Euler (0.0f, Random.Range (0.0f, 360.0f), 0.0f);
    116.                     l_ProjectorRotation = l_ProjectorRotation * l_RandomRotation;
    117.                    
    118.                     TerrainCollider l_TerrainCollider = l_RaycastHit.collider as TerrainCollider;
    119.                     if (l_TerrainCollider != null)
    120.                     {
    121.                        
    122.                         // Terrain collider hit.
    123.                        
    124.                         Terrain l_Terrain = l_TerrainCollider.GetComponent <Terrain> ();
    125.                         if (l_Terrain != null)
    126.                         {
    127.                            
    128.                             // Create the decal projector with all the required information.
    129.                             DecalProjector l_DecalProjector = new DecalProjector (l_ProjectorPosition, l_ProjectorRotation, m_DecalProjectorScale, m_CullingAngle, m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex);
    130.                            
    131.                             // Add the projector to our list and the decals mesh, such that both are
    132.                             // synchronized. All the mesh data that is now added to the decals mesh
    133.                             // will belong to this projector.
    134.                             m_DecalProjectors.Add (l_DecalProjector);
    135.                             m_DecalsMesh.AddProjector (l_DecalProjector);
    136.                            
    137.                             // The terrain data has to be converted to the decals instance's space.
    138.                             Matrix4x4 l_TerrainToDecalsMatrix = m_WorldToDecalsMatrix * Matrix4x4.TRS (l_Terrain.transform.position, Quaternion.identity, Vector3.one);
    139.                            
    140.                             // Pass the terrain data with the corresponding conversion to the decals mesh.
    141.                             m_DecalsMesh.Add (l_Terrain, l_TerrainToDecalsMatrix);
    142.                            
    143.                             // Cut and offset the decals mesh.
    144.                             m_DecalsMeshCutter.CutDecalsPlanes (m_DecalsMesh);
    145.                             m_DecalsMesh.OffsetActiveProjectorVertices ();
    146.                            
    147.                             // The changes are only present in the decals mesh at the moment. We have
    148.                             // to pass them to the decals instance to visualize them.
    149.                             m_DecalsInstance.UpdateDecalsMeshes (m_DecalsMesh);
    150.                            
    151.                             // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
    152.                             // based on the surface you have hit.
    153.                             NextUVRectangleIndex ();
    154.                         }
    155.                         else
    156.                         {
    157.                             Debug.LogError ("Terrain is null!");
    158.                         }
    159.                        
    160.                     }
    161.                     else
    162.                     {
    163.                        
    164.                         // We hit a collider. Next we have to find the mesh that belongs to the collider.
    165.                         // That step depends on how you set up your mesh filters and collider relative to
    166.                         // each other in the game objects. It is important to have a consistent way in order
    167.                         // to have a simpler implementation.
    168.                        
    169.                         MeshCollider l_MeshCollider = l_RaycastHit.collider.GetComponent <MeshCollider> ();
    170.                         MeshFilter l_MeshFilter = l_RaycastHit.collider.GetComponent <MeshFilter> ();
    171.                        
    172.                         if (l_MeshCollider != null || l_MeshFilter != null)
    173.                         {
    174.                             Mesh l_Mesh = null;
    175.                             if (l_MeshCollider != null)
    176.                             {
    177.                                
    178.                                 // Mesh collider was hit. Just use the mesh data from that one.
    179.                                 l_Mesh = l_MeshCollider.sharedMesh;
    180.                             } else if (l_MeshFilter != null)
    181.                             {
    182.                                
    183.                                 // Otherwise take the data from the shared mesh.
    184.                                 l_Mesh = l_MeshFilter.sharedMesh;
    185.                             }
    186.                            
    187.                             if (l_Mesh != null)
    188.                             {
    189.                                
    190.                                 // Create the decal projector.
    191.                                 DecalProjector l_DecalProjector = new DecalProjector (l_ProjectorPosition, l_ProjectorRotation, m_DecalProjectorScale, m_CullingAngle, m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex);
    192.                                
    193.                                 // Add the projector to our list and the decals mesh, such that both are
    194.                                 // synchronized. All the mesh data that is now added to the decals mesh
    195.                                 // will belong to this projector.
    196.                                 m_DecalProjectors.Add (l_DecalProjector);
    197.                                 m_DecalsMesh.AddProjector (l_DecalProjector);
    198.                                
    199.                                 // Get the required matrices.
    200.                                 Matrix4x4 l_WorldToMeshMatrix = l_RaycastHit.collider.renderer.transform.worldToLocalMatrix;
    201.                                 Matrix4x4 l_MeshToWorldMatrix = l_RaycastHit.collider.renderer.transform.localToWorldMatrix;
    202.                                
    203.                                 // Add the mesh data to the decals mesh, cut and offset it.
    204.                                 m_DecalsMesh.Add (l_Mesh, l_WorldToMeshMatrix, l_MeshToWorldMatrix);                       
    205.                                 m_DecalsMeshCutter.CutDecalsPlanes (m_DecalsMesh);
    206.                                 m_DecalsMesh.OffsetActiveProjectorVertices ();
    207.                                
    208.                                 // The changes are only present in the decals mesh at the moment. We have
    209.                                 // to pass them to the decals instance to visualize them.
    210.                                 m_DecalsInstance.UpdateDecalsMeshes (m_DecalsMesh);
    211.                                
    212.                                 // For the next hit, use a new uv rectangle. Usually, you would select the uv rectangle
    213.                                 // based on the surface you have hit.
    214.                                 NextUVRectangleIndex ();
    215.                             }
    216.                         }
    217.                     }
    218.                 }
    219.             }
    220.  
     
  5. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Could you explain me the overall logic? You have shown that the result is not what you want, but I don't understand what your actual idea is.
    How do you compute the position of the decal projectors? How do you find out how the rotation should be?

    The bullet example assumes the the player is shooting forward along the camera. That's the basis of the ray. Then it is checked whether something was hit. If yes, this hit point is used to place the decal projector (with a small offset to make sure it is visible). The get the rotation we simply use the direction along which the bullet was flying, which is the same as the camera forward direction. Optionally we could also use the the negative normal of the raycast hit. That means the direction of the camera is ignored, but the bullet hole has to be projected straight onto the ground, independent of the direction it came from. This alternative is implemented in the unstretched bullet example script.
     
  6. Alex_Kun90

    Alex_Kun90

    Joined:
    Mar 19, 2014
    Posts:
    10
    My goal is to print the blood like this immage , but only on the ground and not in on the wall
    $BloodEpic.JPG

    The problem that the result when i sett the raycast down is this

    $Immagine22.JPG

    there is the part of code that i must modify

    Code (csharp):
    1.  
    2.  //Ray che inizia dall'empty come position e che mira in basso
    3.                 Ray l_Ray = new Ray(cameraz.transform.position, Vector3.down );
    4.                
    5.                 RaycastHit l_RaycastHit;
    6.                
    7.                 if (Physics.Raycast (l_Ray, out l_RaycastHit,Mathf.Infinity))
    8.                 {
    9.                     // Collider hit.
    10.                    
    11.                     // Make sure there are not too many projectors.
    12.                     if (m_DecalProjectors.Count >= m_MaximumNumberOfProjectors)
    13.                     {
    14.                        
    15.                         // If there are more than the maximum number of projectors, we delete
    16.                         // the oldest one.
    17.                         DecalProjector l_DecalProjector = m_DecalProjectors [0];
    18.                         m_DecalProjectors.RemoveAt (0);
    19.                         m_DecalsMesh.RemoveProjector (l_DecalProjector);
    20.                     }
    21.                    
    22.                     // Calculate the position and rotation for the new decal projector.
    23.                     Vector3 l_ProjectorPosition = l_RaycastHit.point - (m_DecalProjectorOffset * l_Ray.direction.normalized);
    24.                     Quaternion l_ProjectorRotation = ProjectorRotationUtility.ProjectorRotation (Camera.main.transform.forward, Vector3.left);
    25.  
    26.         // Randomize the rotation.
    27.                 Quaternion l_RandomRotation = Quaternion.Euler (0.0f, Random.Range (0.0f, 360.0f), 0.0f);
    28.                     l_ProjectorRotation = l_ProjectorRotation * l_RandomRotation;
    29.  
    30.  
    31.  
    32.  
    I must find a way to draw my decals correctly on the ground , but I'm not know how to modify the projector rotation
     
  7. Alex_Kun90

    Alex_Kun90

    Joined:
    Mar 19, 2014
    Posts:
    10
    I do it!!!! *_* I use the Quaternion l_ProjectorRotation = Quaternion.FromToRotation(Vector3.up, cameraz.transform.up);

    for correct the rotation of my projector
     
  8. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    That's dangerous, you should use something like that:
    Code (csharp):
    1. Vector3 l_ProjectorPosition = l_RaycastHit.point - (m_DecalProjectorOffset * l_Ray.direction.normalized);
    2. Quaternion l_ProjectorRotation = ProjectorRotationUtility.ProjectorRotation (l_Ray.direction, Vector3.right);
    The first value you are passing to ProjectorRotationUtility.ProjectorRotation is for the direction of the projection. The other one is not allowed to point in the same direction or in the opposite direction. That's why I randomly picked the right hand side. Just pick anything except up or down.
     
  9. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    Hi, I exciting now because I found this asset!

    But current using free version, I have a trouble that this decal wasn't applied on Human model mesh...
    Is there a Pro include system?

    $1groundunity.png $1humanunity.png
     
  10. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Skinned decals are also available in the free version. You create them with GameObject -> Create Other -> Skinned Decals.

    In the documentation you find the following description:
    One important trick to minimize unwanted imprecisions is to place the game object with the DS_SkinnedDecals script as close as possible to the character or even better, make it a child of the character.
     
  11. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    Thanks for reply!

    I would tried it. broken problem is strange...
    $decalssystem.png
     
  12. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    You have to follow all the advices from my previous post. What you clearly didn't do is:
    It is also possible of offset the projector slightly to minimize the effect. And make sure you are using one of the provided decal shaders.
     
  13. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    Oops.
    Thank you very much! I try to use one of the provided decal shaders(Decal/Transparent Diffuse). Very nice decal!

    $1.png
     
  14. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    You got the result you were looking for?
     
  15. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    Yes! I had wanted to get the state that human was painted out by painting. I had worried about the chest but it is no problem! I buy the pro soon after I more get usage.
     
  16. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    Hi.
    I have a question about Skinned Bullet Example in Bootcamp Simple Skinning scene.
    I tried example using a soldier model http://u3d.as/1E7
    while I'm walking, Fire a painting decal.
    then the screen freeze for a moment...
    Would you help me?

    Freeze point is the following code.

    139 line on SkinnedBulletExample.cs (namespace Edelweiss.DecalSystem.Example).
    Code (csharp):
    1.  
    2. m_DecalsMesh.Add (l_Mesh, l_SkinnedMeshRenderer.bones, l_SkinnedMeshRenderer.quality, l_WorldToMeshMatrix, l_MeshToWorldMatrix);
    3.  
    $s.png

    $soldeir.png
     
  17. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I assume you have no error messages or warnings in the console.
    Could you try to shoot several bullets, than clear them and shoot again? Is it still freezing?
     
  18. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    of course, I have no error messages or warnings in the console.
    Yes freezing yet, I tried your advice (shoot bullets -> press c button clear -> shoot again).
     
  19. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    I expected that, but it often turned out to be the cause for performance issues :) .

    I was able to nail it down. The example that comes with the Decal System consists of 3k vertices, while the one you are using has 10k vertices.
    To give you an idea what happens internally. First, all the vertices are the ones from the default pose. Using the bones, another set of vertices is created that are brought to the actual position the character has. On those vertices the actual cutting is performed, but in parallel also on the original vertices in the same way as it is made on the animated ones. Now the original vertices which are now cut can be visualized.
    This is the simplified version of what is happening. And you can imagine that this operation takes time. 10k is simply too much.

    I am trying to find a better implementation since quite some time that takes shape keys into account and preferably one that allows the newly introduced optimizations for skinned meshes and is hopefully faster. Unfortunately, you can't expect anything in the near future.
     
  20. arcdragon1

    arcdragon1

    Joined:
    Oct 15, 2012
    Posts:
    116
    OK I understood it is difficult and complex progression that unity attach a decals to Skinned mesh.
    In an ongoing way, I will decrease the 10k vertex as reduce as possible.
    But I think current version system is excellent at decal maker.
    Thank you very much!
     
  21. LeoTS

    LeoTS

    Joined:
    Jan 1, 2013
    Posts:
    18
    Hello again Dantus :D
    So, about the adding the decal system to different threads, I did my own decal system for that purpose, and its working pretty well, although i'm using it only for dynamic projection at the moment, and since i don't have time to make editor tools, i'm still using your decal system for baked decals.

    I didn't have to use unity's functions or classes to make the core calculation of the decals, so it wasn't hard to make it in thread. I'm calculating all AABB/triangle collision and triangle cutting with custom vector classes. Initially i used unity's co-routines to run it, but it was not fast enough.

    Even tho my decal system is working, your decal system is very practical and well optimized, so if you added some way to avoid frame rate drop in calculations i'd use your system :)
     
  22. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    There are a few calls and some reference comparisons in the Decal System that prevent it from being used in a multi-threaded context. Getting rid of those will take a little time, but it is on my todo list.
     
  23. NTDC-DEV

    NTDC-DEV

    Joined:
    Jul 22, 2010
    Posts:
    593
    Hello Dantus,

    Let me start by saying that I really like your decal system and the level of support you have on these forums. Really appreciate that you have a free version for people to try it out and even use.

    I'm hoping you could answer a few questions;
    1) Does the plugin supports moving the sources of the free version in other folders within the same root? Ex; Instead of /Plugins/Decal System -> /Plugins/External/Decal System?

    2) Do you foresee any problems with the following workflow:
    - Normally create all static decals in scene with projectors ...
    - Before bundling the scene in an asset bundle, run a pre-process script that removes all the decal system components and projectors but keeps the MeshRenderer GO untouched.

    The decals should be static, at most, I will be adding a collider to detect OnMouse triggers and enabling/disabling the renderer for culling.

    There could be up to a thousand decals in multiple scenes... the intend is to limit the file size, memory footprint and component-logic as much as possible.

    Thanks!
     
  24. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Thanks!

    This should work. It is self explanatory that you have to be careful when you want to update to a newer version.
    Take care that the editor files are in /Plugins/Editor/... . I wanted to have them in /Plugins/Decal System/Editor which doesn't work on all platforms unfortunately. So, take care of that.
    To be sure that it really works, create a decal and place it. If all the decal icons in the inspector are correct and if you can place projectors as usual, everything should be fine.

    This should theoretically work. Of course you have to be careful and test whether it works with your scene setup and that there aren't special cases and so on. But for runtime purposes, only the mesh renderer game object is needed and it should be possible to remove all the Decal System related components.

    It would be interesting to hear whether those approaches work.
     
  25. sathya

    sathya

    Joined:
    Jul 30, 2012
    Posts:
    297
    Unity throws lots of error message when converting project to windows phone 8. Does this System support Windows phone 8 yet !

    $ErrorReport.PNG
     
  26. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
  27. sathya

    sathya

    Joined:
    Jul 30, 2012
    Posts:
    297
  28. JohnRossitter

    JohnRossitter

    Joined:
    Dec 18, 2013
    Posts:
    1,027
    Hi Dantus,

    I thought I would bring this question onto the forum instead.

    First of all, you are amazing for making this asset, I can tell that you have put a lot of hard work into it!

    I'm working on making an Editor Extension which uses the free version of Decal System.
    With that in mind, I have a slightly different situation than that of attaching a DS_Decals object to a prefab. I need to create the the container GameObject in code at "Edit Time". I think that I have it mostly working, in that I am able to:

    a) create an empty game object
    b) add a DS_Decals component to the game object
    c) set the Current Material of the DS_Decals object
    d) Set a new UVRectangle around my texture atlas

    Here is where Im having trouble.

    I used the code in the Bullet Example as a guid to creating Projectors on the fly and adding them.
    From what I can see, I am successfully adding Projectors to my m_DecalProjectors List, but those updates are not making it back to the GameObject instance that now lives in my scene.

    Here is an image of my scene after creating everything:
    $dant1.png

    Here you can see that there are no Projectors:
    $dant2.png

    This is a condensed version of the code Im using, again keep in mind that this is not being used at Runtime, but in design time from an Editor Extension.

    usingUnityEngine;
    usingUnityEditor;
    usingSystem.Collections;
    usingSystem.Collections.Generic;
    usingSystem.Xml;
    usingSystem.Xml.Serialization;
    usingSystem.Text;
    usingSystem.Reflection;
    usingEdelweiss.DecalSystem;
    usingSystem.IO;



    #regionDecalSystem
    publicGameObjectDecalHolder;
    publicDS_Decalsm_DecalsPrefab;

    //privateDS_Decalsm_DecalsInstance;
    publicMatrix4x4m_WorldToDecalsMatrix;
    publicList <DecalProjector> m_DecalProjectors = newList <DecalProjector> ();
    publicintm_MaximumNumberOfProjectors = 50;

    publicDecalsMeshm_DecalsMesh;
    publicDecalsMeshCutterm_DecalsMeshCutter;

    publicfloatm_DecalProjectorOffset = 0.5f;


    publicVector3m_DecalProjectorScale = newVector3 (0.2f, 2.0f, 0.2f);
    publicfloatm_CullingAngle = 80.0f;
    publicfloatm_MeshOffset = 0.0f;

    publicintm_UVRectangleIndex = 0;

    publicvoidinitDecals()
    {
    DecalHolder = newGameObject("DecalHolder") asGameObject;
    m_DecalsPrefab = DecalHolder.AddComponent("DS_Decals") asDS_Decals;
    Debug.Log(m_DecalsPrefab);
    isFirstLoad = false;
    m_DecalsPrefab = m_DecalsPrefab;//Instantiate (m_DecalsPrefab) asDS_Decals;


    if (m_DecalsPrefab == null) {
    Debug.LogError ("The decals prefab does not contain a DS_Decals instance!");
    } else {

    //Createthedecalsmeshandthecutterthatareneededtocomputetheprojections.
    //Wealsocachetheworldtodecalsmatrix.
    m_DecalsMesh = newDecalsMesh (m_DecalsPrefab);
    m_DecalsMeshCutter = newDecalsMeshCutter ();
    m_WorldToDecalsMatrix = m_DecalsPrefab.CachedTransform.worldToLocalMatrix;
    }
    //Materialmat = Resources.Load("Materials/Utopia9_base", typeof(Material)) asMaterial;
    Materialmat = (Material)AssetDatabase.LoadAssetAtPath("Assets/Decals/Grunge/" + "Rust" + ".mat",typeof(Material));
    m_DecalsPrefab.CurrentMaterial = mat;
    m_DecalsPrefab.ApplyMaterialToMeshRenderers();
    UVRectanglemyUVR = newUVRectangle();

    m_DecalsPrefab.uvRectangles = newUVRectangle[1];
    m_DecalsPrefab.uvRectangles[0] = myUVR;
    }

    privatevoidNextUVRectangleIndex () {
    m_UVRectangleIndex = m_UVRectangleIndex + 1;
    if (m_UVRectangleIndex >= m_DecalsPrefab.CurrentUvRectangles.Length) {
    m_UVRectangleIndex = 0;
    }
    }

    #endregion

    voidOnGUI()
    {
    if (GUI.Button(new Rect(240, 370, 50, 50), new GUIContent(imgZero, "Random Decals")))
    {

    Rayl_Ray = Camera.main.ViewportPointToRay (newVector3 (0.5f, 0.5f, 0.0f));
    RaycastHitl_RaycastHit;
    Physics.Raycast (l_Ray, outl_RaycastHit, Mathf.Infinity);
    MeshColliderl_MeshCollider = l_RaycastHit.collider.GetComponent <MeshCollider> ();
    MeshFilterl_MeshFilter = l_RaycastHit.collider.GetComponent <MeshFilter> ();

    if (l_MeshCollider != null || l_MeshFilter != null) {
    Meshl_Mesh = null;
    if (l_MeshCollider != null) {

    //Meshcolliderwashit. Justusethemeshdatafromthatone.
    l_Mesh = l_MeshCollider.sharedMesh;
    } elseif (l_MeshFilter != null) {

    //Otherwisetakethedatafromthesharedmesh.
    l_Mesh = l_MeshFilter.sharedMesh;
    }
    DecalProjectorl_DecalProjector = newDecalProjector(Vector3.zero,newQuaternion(1,0,0,0),Vector3.zero,m_CullingAngle,m_MeshOffset, m_UVRectangleIndex, m_UVRectangleIndex);


    m_DecalProjectors.Add (l_DecalProjector);
    m_DecalsMesh.AddProjector (l_DecalProjector);
    Matrix4x4l_WorldToMeshMatrix = l_RaycastHit.collider.renderer.transform.worldToLocalMatrix;
    Matrix4x4l_MeshToWorldMatrix = l_RaycastHit.collider.renderer.transform.localToWorldMatrix;
    m_DecalsMesh.Add (l_Mesh, l_WorldToMeshMatrix, l_MeshToWorldMatrix);
    m_DecalsMeshCutter.CutDecalsPlanes (m_DecalsMesh);
    m_DecalsMesh.OffsetActiveProjectorVertices ();
    m_DecalsPrefab.UpdateDecalsMeshes (m_DecalsMesh);
    NextUVRectangleIndex ();

    }
    }

    So , just to wrap up.

    I am able to create the Decal System and add it to my Scene.
    I can modify the properties of the Decal System
    I am able to run the code (without exception) to create and attach the new Projectors
    I am Unable to get the updates from adding projectors in my scene. So after I create a new projector, nothing happens in the scene. No child objects get created on the Decal System. No Projectors get added.

    I hope this makes sense.

    Thanks,


     
    Last edited: Apr 5, 2014
  29. sathya

    sathya

    Joined:
    Jul 30, 2012
    Posts:
    297
    Is it possible to access the existing DecalMesh in DS_Decals !. I dont want to create a new DecalMesh. I have placed the Decal in editor and i want to change its m_UVRectangleIndex at runtime and update the same. There should be one Deal Object, One Projector and Multiple UVRects. Is this possible. Basically i am trying to change car decals at runtime. Thanks.
     
  30. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @JohnRossitter, if you are working in the editor you should not use the bullet example scripts as they are for runtime purposes only. You need to place the decal projectors (DS_DecalProjector) into game objects that are children of the game object with the DS_Decals instance. Make sure that you create the game objects and components as you would if you were using the Decal System though the inspector.
    Now, the updates need to be made using the EditorDecalsCreator class from the Edelweiss.DecalSystemEditor namespace.

    Let me know if you have further questions!
     
  31. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    The Decal System was made to have a minimal memory footprint. Because of that you have to create the DecalsMesh at runtime on your own. To make the situation a little bit easier there is the RuntimeDecalsUpdater script that helps you to update projectors if the meshes onto which they perform a projection stay unchanged:
    http://forum.unity3d.com/threads/141792-Decal-System/page28?p=1247584&viewfull=1#post1247584

    In the case that you have the Decal System Pro, there are optimized methods to update the rectangle indices. That is demonstrated in some examples. You could enhance the RuntimeDecalsUpdater to use them if needed.

    Hope this helps
     
  32. JohnRossitter

    JohnRossitter

    Joined:
    Dec 18, 2013
    Posts:
    1,027
    I will work with it today and let you know.

    Thanks!
     
  33. JohnRossitter

    JohnRossitter

    Joined:
    Dec 18, 2013
    Posts:
    1,027
    Thanks Dantus!

    For anyone looking for a starting point for adding Decals at Design/Edit time with an editor extension script, this should get you started:


    if (GUI.Button(new Rect(240, 370, 50, 50), new GUIContent(imgZero, "Random Decals")))
    {
    GameObject DecalHolder;
    DS_Decals m_DecalsPrefab;

    DecalHolder = new GameObject("DecalHolder") as GameObject;
    m_DecalsPrefab = DecalHolder.AddComponent("DS_Decals") as DS_Decals;
    Material mat = (Material)AssetDatabase.LoadAssetAtPath("Assets/Decals/Grunge/" + "Rust" + ".mat",typeof(Material));
    m_DecalsPrefab.CurrentMaterial = mat;
    m_DecalsPrefab.ApplyMaterialToMeshRenderers();
    UVRectangle myUVR = new UVRectangle();

    m_DecalsPrefab.uvRectangles = new UVRectangle[1];
    m_DecalsPrefab.uvRectangles[0] = myUVR;
    Debug.Log(m_DecalsPrefab);
    isFirstLoad = false;

    for(int i =0; i<5;i++)
    {
    GameObject ProjectorHolder = new GameObject("DecalProjector") as GameObject;
    DS_DecalProjector l_DecalProjector = new DS_DecalProjector();
    l_DecalProjector = ProjectorHolder.AddComponent("DS_DecalProjector") as DS_DecalProjector;
    l_DecalProjector.uv1RectangleIndex=0;
    ProjectorHolder.transform.position = new Vector3(0,1,i*2);
    ProjectorHolder.transform.parent = DecalHolder.transform;
    }


    }
     
  34. JohnRossitter

    JohnRossitter

    Joined:
    Dec 18, 2013
    Posts:
    1,027
    In the Decal System Editor Extension, what is happening when you call Update All Projectors?
    How can Im achieve the same via code like I'm using with my Editor Extension?

    Thanks,
     
  35. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    Keep in mind: You asked for it :)
    Those are just the most relevant parts of the code.

    Code (csharp):
    1. public static void UpdateAllProjectors (Decals a_Decals, bool a_MinimizeDecalsMesh) {
    2.     s_MinimizeDecalsMesh = a_MinimizeDecalsMesh;
    3.  
    4.     if (IsUpdateValid (a_Decals)) {
    5.         s_DecalsMesh.Initialize (a_Decals);
    6.         s_DecalProjectorLookup.Clear ();
    7.                
    8.         DecalProjectorComponent[] l_Projectors = a_Decals.GetComponentsInChildren <DecalProjectorComponent> ();
    9.         AddProjectors (a_Decals, l_Projectors);
    10.                
    11.         ApplyDecalsMesh (a_Decals);
    12.     }
    13. }
    14.  
    15. private static void AddProjectors (Decals a_Decals, DecalProjectorComponent[] a_Projectors) {
    16.     foreach (DecalProjectorComponent l_Projector in a_Projectors) {
    17.  
    18.         if (HasProjectorValidUvIndices (a_Decals, l_Projector)) {
    19.             WrappedDecalProjector l_WrappedProjector = new WrappedDecalProjector (l_Projector);
    20.             if (s_DecalProjectorLookup.ContainsKey (l_Projector)) {
    21.                 Debug.Log (l_Projector.name + " should not be here!");
    22.             }
    23.             s_DecalProjectorLookup.Add (l_Projector, l_WrappedProjector);
    24.             s_DecalsMesh.AddProjector (l_WrappedProjector);
    25.  
    26.             if (l_Projector.affectMeshes) {
    27.                 List <MeshRenderer> l_AffectedMeshRenderers = AffectedMeshRenderers (a_Decals, l_Projector);
    28.                 foreach (MeshRenderer l_AffectedMeshRenderer in l_AffectedMeshRenderers) {
    29.                     MeshFilter l_AffectedMeshFilter = l_AffectedMeshRenderer.GetComponent <MeshFilter> ();
    30.                     if (l_AffectedMeshFilter != null) {
    31.                         Mesh l_AffectedMesh = l_AffectedMeshFilter.sharedMesh;
    32.                                
    33.                         if (l_AffectedMesh != null  !l_AffectedMesh.isReadable) {
    34.                             if (!l_Projector.skipUnreadableMeshes) {
    35.                                 Debug.LogWarning ("A mesh onto which a decal should be projected is not readable!");
    36.                             }
    37.                         } else {
    38.                                
    39.                                 // If the uv, uv2 or tangents of the target mesh are needed, they have to exist.
    40.                                 // Otherwise we simply ignore them. The normals can easily be computed and thus
    41.                                 // we don't need them.
    42.                                 //
    43.                                 // Remark: Implications (A => B) are logically equivalent to !(A) || (B).
    44.                             if
    45.                                 ((l_AffectedMesh != null)
    46.                                  (!(a_Decals.CurrentUVMode == UVMode.TargetUV) || (l_AffectedMesh.uv != null  l_AffectedMesh.uv.Length == l_AffectedMesh.vertexCount))
    47.                                  (!(a_Decals.CurrentUVMode == UVMode.TargetUV2) || (l_AffectedMesh.uv2 != null  l_AffectedMesh.uv2.Length == l_AffectedMesh.vertexCount))
    48.                                  (!(a_Decals.CurrentUV2Mode == UV2Mode.TargetUV) || (l_AffectedMesh.uv != null  l_AffectedMesh.uv.Length == l_AffectedMesh.vertexCount))
    49.                                  (!(a_Decals.CurrentUV2Mode == UV2Mode.TargetUV2) || (l_AffectedMesh.uv2 != null  l_AffectedMesh.uv2.Length == l_AffectedMesh.vertexCount))
    50.                                  (!(a_Decals.CurrentTangentsMode == TangentsMode.Target) || (l_AffectedMesh.tangents != null)))
    51.                             {
    52.                                 s_DecalsMesh.Add (l_AffectedMesh, l_AffectedMeshRenderer.transform.worldToLocalMatrix, l_AffectedMeshRenderer.transform.localToWorldMatrix);
    53.                             }
    54.                         }
    55.                     }
    56.                 }
    57.             }
    58.                    
    59.             if (l_Projector.affectTerrains) {
    60.                 List <Terrain> l_AffectedTerrains = AffectedTerrains (a_Decals, l_Projector);
    61.                 foreach (Terrain l_AffectedTerrain in l_AffectedTerrains) {                    
    62.                     Matrix4x4 l_AffectedTerrainToDecalsMatrix = a_Decals.transform.worldToLocalMatrix * Matrix4x4.TRS (l_AffectedTerrain.transform.position, Quaternion.identity, Vector3.one);
    63.                            
    64.                         // The target uv, uv2 and tangents can not be used.
    65.                     if
    66.                         (a_Decals.CurrentUVMode != UVMode.TargetUV
    67.                          a_Decals.CurrentUVMode != UVMode.TargetUV2
    68.                          a_Decals.CurrentUV2Mode != UV2Mode.TargetUV
    69.                          a_Decals.CurrentUV2Mode != UV2Mode.TargetUV2
    70.                          a_Decals.CurrentTangentsMode != TangentsMode.Target)
    71.                     {
    72.                         if (!Edition.IsDecalSystemFree  l_Projector.useTerrainDensity) {
    73.                             s_DecalsMesh.Add (l_AffectedTerrain, l_Projector.terrainDensity, l_AffectedTerrainToDecalsMatrix);
    74.                         } else {
    75.                             s_DecalsMesh.Add (l_AffectedTerrain, l_AffectedTerrainToDecalsMatrix);
    76.                         }
    77.                     }
    78.                 }
    79.             }
    80.                    
    81.  
    82.             if (l_WrappedProjector.DecalsMeshUpperVertexIndex - l_WrappedProjector.DecalsMeshLowerVertexIndex > 0) {
    83.                 s_DecalsMeshCutter.CutDecalsPlanes (s_DecalsMesh);
    84.  
    85.                 if (!Edition.IsDecalSystemFree) {
    86.                     if
    87.                         ((s_DecalsMesh.Decals.CurrentMeshMinimizerMode == MeshMinimizerMode.OnOptimize
    88.                           s_MinimizeDecalsMesh
    89.                           !l_Projector.ignoreMeshMinimizer) ||
    90.                          (s_DecalsMesh.Decals.CurrentMeshMinimizerMode == MeshMinimizerMode.Always
    91.                          !l_Projector.ignoreMeshMinimizer))
    92.                     {
    93.                         float l_MaximumAbsoluteError = s_DecalsMesh.Decals.MeshMinimizerMaximumAbsoluteError;
    94.                         float l_MaximumRelativeError = s_DecalsMesh.Decals.MeshMinimizerMaximumRelativeError;
    95.                         if (l_Projector.useCustomMeshMinimizerMaximumErrors) {
    96.                             l_MaximumAbsoluteError = l_Projector.MeshMinimizerMaximumAbsoluteError;
    97.                             l_MaximumRelativeError = l_Projector.MeshMinimizerMaximumRelativeError;
    98.                         }
    99.  
    100.                         s_DecalsMeshMinimizer.MinimizeActiveProjectorOfDecalsMesh (s_DecalsMesh, l_MaximumAbsoluteError, l_MaximumRelativeError);
    101.                     }
    102.                 }
    103.  
    104.                 if
    105.                     (s_DecalsMesh.Decals.CurrentUVMode == UVMode.Project ||
    106.                      s_DecalsMesh.Decals.CurrentUVMode == UVMode.ProjectWrapped)
    107.                 {
    108.                     s_DecalsMesh.CalculateProjectedUV1ForActiveProjector ();
    109.                 }
    110.                 if
    111.                     (s_DecalsMesh.Decals.CurrentUV2Mode == UV2Mode.Project ||
    112.                      s_DecalsMesh.Decals.CurrentUV2Mode == UV2Mode.ProjectWrapped)
    113.                 {
    114.                     s_DecalsMesh.CalculateProjectedUV2ForActiveProjector ();
    115.                 }
    116.  
    117.                     // It seems more reasonable to first move the vertices away from the target surface and the
    118.                     // smooth the vertices.
    119.  
    120.                 s_DecalsMesh.OffsetActiveProjectorVertices ();
    121.  
    122.                 if (l_Projector.normalsSmoothing > 0.0f) {
    123.                     s_DecalsMesh.SmoothActiveProjectorNormals (l_Projector.normalsSmoothing);
    124.                 }
    125.  
    126.                 if (!Edition.IsDecalSystemFree  l_Projector.projectAfterOffset) {
    127.                     if
    128.                         (a_Decals.CurrentUVMode == UVMode.Project ||
    129.                          a_Decals.CurrentUVMode == UVMode.ProjectWrapped)
    130.                     {
    131.                         s_DecalsMesh.UpdateProjectedUV (l_WrappedProjector);
    132.                     }
    133.                     if
    134.                         (a_Decals.CurrentUV2Mode == UV2Mode.Project ||
    135.                          a_Decals.CurrentUV2Mode == UV2Mode.ProjectWrapped)
    136.                     {
    137.                         s_DecalsMesh.UpdateProjectedUV2 (l_WrappedProjector);
    138.                     }
    139.                 }
    140.             }
    141.         }
    142.     }
    143. }
    144.  
    145. private static List <MeshRenderer> AffectedMeshRenderers (Decals a_Decals, DecalProjectorComponent a_Projector) {
    146.  
    147.     List <MeshRenderer> l_Result = new List <MeshRenderer> ();
    148.     List <MeshRenderer> l_MeshRenderers = new List <MeshRenderer> ();
    149.     List <MeshRenderer> l_DetailRenderers = new List <MeshRenderer> ();
    150.     Bounds l_WorldBounds = a_Projector.WorldBounds ();
    151.  
    152.  
    153.         // Get the renderers
    154.  
    155.     if (a_Decals.AffectSameLODOnly) {
    156.        
    157.             // Check only the renderers of the same LOD
    158.        
    159.         LODGroup l_LODGroup = LODUtility.GetLODGroup (a_Decals);
    160.         int l_LODIndex = -1;
    161.         if (l_LODGroup != null) {
    162.             l_LODIndex = LODUtility.LODIndexOfDecalsInLODGroup (a_Decals, l_LODGroup);
    163.         }
    164.         if (l_LODIndex != -1) {
    165.             List <Renderer> l_LODRenderers = LODUtility.RenderersAtLOD (l_LODGroup, l_LODIndex);
    166.             foreach (Renderer l_Renderer in l_LODRenderers) {
    167.                 MeshRenderer l_MeshRenderer = l_Renderer as MeshRenderer;
    168.                 if (l_MeshRenderer != null) {
    169.                     l_MeshRenderers.Add (l_MeshRenderer);
    170.                 }
    171.             }
    172.         }
    173.        
    174.     } else {
    175.        
    176.             // Check all mesh renderers
    177.        
    178.         MeshRenderer[] l_FoundMeshRenderers = (MeshRenderer[]) Object.FindObjectsOfType (typeof (MeshRenderer));
    179.         l_MeshRenderers.AddRange (l_FoundMeshRenderers);
    180.     }
    181.  
    182.  
    183. #if DECAL_SYSTEM_FREE
    184.         // Dummy to avoid warnings
    185.     if (l_DetailRenderers == null) {
    186.     }
    187. #else
    188.         // Details
    189.  
    190.     if (a_Projector.detailsMode != DetailsMode.Disabled) {
    191.         foreach (AffectedDetail l_AffectedDetail in a_Projector.affectedDetails) {
    192.             Transform l_AffectedDetailTransform = l_AffectedDetail.transform;
    193.             if (l_AffectedDetailTransform != null) {
    194.                 if (l_AffectedDetail.rendererInclusion == RendererInclusion.Current) {
    195.                     MeshRenderer l_Renderer = l_AffectedDetailTransform.GetComponent <MeshRenderer> ();
    196.                     if (l_Renderer != null) {
    197.                         l_DetailRenderers.Add (l_Renderer);
    198.                     }
    199.                 } else if (l_AffectedDetail.rendererInclusion == RendererInclusion.CurrentAndChildren) {
    200.                     MeshRenderer[] l_Renderers = l_AffectedDetailTransform.GetComponentsInChildren <MeshRenderer> ();
    201.                     l_DetailRenderers.AddRange (l_Renderers);
    202.                 }
    203.             }
    204.         }
    205.     }
    206. #endif
    207.  
    208.  
    209.         // Filter the renderers
    210.  
    211.     foreach (MeshRenderer l_MeshRenderer in l_MeshRenderers) {
    212.         if
    213.             ((!a_Decals.IsDecalsMeshRenderer (l_MeshRenderer))
    214.              (!(l_MeshRenderer.GetComponent <DecalsMeshRenderer> () != null) || a_Projector.affectOtherDecals)
    215.              (l_MeshRenderer.enabled || a_Projector.affectInactiveRenderers)
    216.              (((1 << l_MeshRenderer.gameObject.layer)  a_Projector.affectedLayers.value) != 0)
    217.              (l_MeshRenderer.bounds.Intersects (l_WorldBounds)))
    218.         {
    219. #if DECAL_SYSTEM_FREE
    220.             l_Result.Add (l_MeshRenderer);
    221. #else
    222.             if (a_Projector.detailsMode == DetailsMode.Disabled) {
    223.                 l_Result.Add (l_MeshRenderer);
    224.             } else if (a_Projector.detailsMode == DetailsMode.AffectRenderers) {
    225.                 if (l_DetailRenderers.Contains (l_MeshRenderer)) {
    226.                     l_Result.Add (l_MeshRenderer);
    227.                 }
    228.             } else if (a_Projector.detailsMode == DetailsMode.ExcludeRenderers) {
    229.                 if (!l_DetailRenderers.Contains (l_MeshRenderer)) {
    230.                     l_Result.Add (l_MeshRenderer);
    231.                 }
    232.             }
    233. #endif
    234.         }
    235.     }
    236.    
    237.     return (l_Result);
    238. }
    Edit: Sent too early.
    You don't want to do that yourself hopefully. That all happens in EditorDecalsCreator which is in the Edelweiss.DecalSystemEditor namespace.
    Code (csharp):
    1. EditorDecalsCreator.UpdateAllProjectors (yourDecalsInstance)
     
    Last edited: Apr 5, 2014
  36. NTDC-DEV

    NTDC-DEV

    Joined:
    Jul 22, 2010
    Posts:
    593
    Dantus,

    I've placed the
    - /Plugins/Editor/Decal System -> /Editor/External/Decal System
    - /Plugins/Decal System -> /Plugins/External/Decal System

    I've created multiple decals without a hinge so far, I'm guessing it works properly.

    Also;

    I hope you don't mind, while using your system I thought of a couple of suggestions that could help with the productivity when building an atlas.

    We are using 2048x2048 atlases with over 60 UV selections per atlas.
    - Make the "Edit UV Rectangle" view auto-center onto the UV selection. This will especially helps when trying to find the selection in an atlas with alpha + zoom; its hard to see where it is on the dark grey background in Pro.

    We lay our atlases on a grid so we can replace / add / remove easily without breaking previous decals.
    - Add a "Copy" button to the UV list with + / - / up / down. The process will be much faster if we could copy an existing UV selection.

    Projector groups are really useful if you want to move the decals around on the same parent GO.
    - Make the DecalProjectGroup GO appear on 0,0,0 of the decal GO. Right now it gets created somewhere in the middle of the scene... making it unpractical.

    Thank you for your work.
     
    Last edited: Apr 7, 2014
  37. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @PolishRenegade, thanks a lot for the useful feedback.
    I need to have a look at the uv editor. The proposed changes make a lot of sense. Though, my preferred change here would be not to rely on the custom editor anymore, but instead make use of Unity's sprite editor. Unfortunately, the api for it is still pretty closed and it is not possible to have good enough workflows for all situations. E.g. it is almost impossible to work with bump and diffuse textures at once.
    The DecalProjectorGroup makes a lot of sense too. I am going to implement that one.

    Thanks
     
  38. hudy

    hudy

    Joined:
    Oct 8, 2013
    Posts:
    4
    Hi Dantus,

    what is the maximum size of the texture used for the decals? Right now I'm trying to test it out with a texture atlas of 4096x4096px but the actual decals look blurry and compressed. Seems the texture is scaled down to 1024x1024px. Can you explain about this, please?

    Cheers
     
  39. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    You can use the same texture sizes as for any other meshes. The Decal System itself doesn't scale any textures as it directly uses the ones you provided. Did you try to modify the import setting of the texture?
    http://docs.unity3d.com/Documentation/Manual/Textures.html

    Make sure that the size is big enough, maybe try it without compression and try to increase the Aniso Level.
     
  40. Paniku

    Paniku

    Joined:
    Apr 11, 2013
    Posts:
    24
    Hi,

    I don't know if this is possible, but I'd like to be able to use the meshes generated by the Decal System in my particle system to emit particles from. Out of the box, this works absolutely fine if the decal is rectangular, but any other shapes will not work because the mesh created is rectangular in shape which would make particles appear outside of the visual decal. Is there any way to have differently shaped meshes?

    For example, for this decal, I would want the mesh to match the shape (or very closely resemble) it. As you can see, since the mesh does not match the shape you can see white particles appearing outside of the red decal.
    $ps.png
     
    Last edited: Apr 18, 2014
  41. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @Paniku, the Decal System only allows rectangles, because it would be almost impossible to support arbitrary shapes in general. There are many restrictions. It is e.g. required that the shape is convex and in order to achieve something like a circle, lots of cutting operations would be needed. The internal decal computations just take a the mesh data and cuts through it. As far as I can see right now, you would need to have Decal System Pro in order to perform the required operations.
    If you are a coder or if you have someone who could do that for you, I would gladly guide you through the code.

    There may be better approaches to reach the same result. In the case that the particles stay on the mesh, you may think of using a shader to achieve this effect. As I don't know how exactly you plan to use it, there may be other alternatives.

    Hope this helps
     
  42. sathya

    sathya

    Joined:
    Jul 30, 2012
    Posts:
    297
    Hi Dantus,
    I tried re positioning and updating the projectors at runtime for car decals, and it works just fine with your decal updater. But i am not sure how optimized this is. I am calling updateProjector while translating the projector which runs in update function and projector also gets updated everyframe. Is this the right way to do it.

    Code (csharp):
    1. public void UpdateProjector(DS_DecalProjector a_Projector)
    2.     {
    3.  
    4.         RemoveProjectorInternal(a_Projector);
    5.  
    6.  
    7.  
    8.         WrappedDecalProjector l_WrappedDecalProjector = new WrappedDecalProjector(a_Projector);
    9.  
    10.         m_UsedDecalProjectors.Add(a_Projector);
    11.  
    12.         m_UsedWrappedDecalProjectors.Add(l_WrappedDecalProjector);
    13.  
    14.  
    15.  
    16.         m_DecalsMesh.AddProjector(l_WrappedDecalProjector);
    17.  
    18.  
    19.  
    20.         foreach (MeshFilter l_MeshFilter in m_AffectedMeshFilters)
    21.         {
    22.  
    23.             Mesh l_Mesh = l_MeshFilter.sharedMesh;
    24.  
    25.             Transform l_Transform = l_MeshFilter.transform;
    26.  
    27.             Matrix4x4 l_WorldToMesh = l_Transform.worldToLocalMatrix;
    28.  
    29.             Matrix4x4 l_MeshToWorld = l_Transform.localToWorldMatrix;
    30.  
    31.             m_DecalsMesh.Add(l_Mesh, l_WorldToMesh, l_MeshToWorld);
    32.  
    33.         }
    34.  
    35.  
    36.  
    37.         m_DecalsMeshCutter.CutDecalsPlanes(m_DecalsMesh);
    38.  
    39.         m_DecalsMesh.OffsetActiveProjectorVertices();
    40.  
    41.         m_Decals.UpdateDecalsMeshes(m_DecalsMesh);
    42.  
    43.  
    44.     }
    Above method gets called while updating the projector transform.
     
    Last edited: Apr 21, 2014
  43. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @sathya, please use code tags when pasting code, as it makes it a lot more readable:
    http://forum.unity3d.com/threads/143875-Using-code-tags-properly

    Updating decals is computationally expensive. There is not way around it. You are doing it correctly! Though there may be tricks to further improve the performance.
    While a decal projector is being actively edited and you expect it to be modified in each frame, you may remove it and replace it with a Unity projector. As soon as the editing is done, you need to go the other way and replace the Unity projector with the decal projector. Of course you need to be careful with the setup that the switching is not visible, but technically you can get the best of both worlds like that.

    Hope this helps.
     
  44. hudy

    hudy

    Joined:
    Oct 8, 2013
    Posts:
    4
    Hi Dantus,

    I'm seriously thinking going Pro, since the system is awesome. However you'd really accelerate my decision if you could take a look at this.

    Using the Transparent Diffuse Coloured Shadow Decal shader, the lighting/shadows are not always applied on the decal depending on the viewing angle. See the images below; tilting/moving/turning the cam a little in some direction demonstrates the issue of disappearing lighting/shadow.

    $decal_shadow_issue.jpg
    $decal_shadow.jpg

    Is there a way (shader?) to fix this?

    Cheers
     
  45. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @hudy, I tried to reproduce the issue but wasn't able so far. Would it be possible to send me a reproduction? Otherwise you may contact me through Skype and I will have a look at it.
     
  46. hudy

    hudy

    Joined:
    Oct 8, 2013
    Posts:
    4
    I found out what the cause of the problem is. Happens if more than 5 lights affect the decal or any decal from the same material. So if you have a big level with decals from a single material all over the level and in total the decals are affected by more than 5 lights anywhere in the level, the decals will be rendered incorrectly. That us unless you cull the lights dynamically or bake static lights.

    Any idea why this is? I checked and this is not the case for the builtin Transparent Diffuse shader. Only the Transparent Diffuse Coloured Shadow Decal shader that comes with the decal system.

    Thanks
     
  47. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
    @hudy, the only solution I can think of is to create more DS_Decals instances and not to spread the projectors over too big areas. That's not only to reduce the number of lights to get it working. Technically decals are just meshes, and no game artist would batch e.g. buildings together that are very far away from each other. That's why I would try to avoid it.
    Regarding the shader itself, there is not too much I can do about it. It is not very different from the other provided shaders, but uses a few trick to get the shadows. You can hardly compare the Transparent Diffuse Coloured Shadow Decal shader with the builtin Transparent Diffuse shader, because this shader doesn't react to shadows at all. I am almost certain that if you would add the shadow receiving functionality to it, you would end up with the same restrictions.

    There is unfortunately nothing I can do on the shader side. I hope the workaround to not spread projectors that far away from each other works for you.
     
  48. hudy

    hudy

    Joined:
    Oct 8, 2013
    Posts:
    4
    Yep, you are right. I ended up moving them close together as you suggested and grouping them in different layers which are selectively affected by the lights, so it is easier to reduce the number of lights affecting each decal group.

    Thanks for your kind assistance.
     
  49. Dantus

    Dantus

    Joined:
    Oct 21, 2009
    Posts:
    5,667
  50. JohnRossitter

    JohnRossitter

    Joined:
    Dec 18, 2013
    Posts:
    1,027
    Thanks Dantus!

    We worked out butt off on making this asset pack, you were a tremendous help with it!