Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Sculpting vertices in Procedural examples asset

Discussion in 'Scripting' started by carlharrison1, Feb 15, 2018.

  1. carlharrison1

    carlharrison1

    Joined:
    Feb 5, 2017
    Posts:
    17
    Hi all,

    I have been checking out Unity's procedural examples asset and I have a question on the sculpting vertices script. Basically what I want to do is INVERT instead of EXTRUDE, which is what this script does to a sphere. Is this as simple as setting one of these values to a minus? Of course, I have tried and guessing its not, but this is really the extent of my knowledge on the subject ... 'try and set one of the values to minus and see if it reverses the process'.. thanks for any help. Essentially what I want to do in my game is SCULPT something, in this case, clay... and I think I would be able to work with this asset after I can get it to invert

    Code (JavaScript):
    1. var radius = 1.0;
    2. var pull = 10.0;
    3. private var unappliedMesh : MeshFilter;
    4.  
    5. enum FallOff { Gauss, Linear, Needle }
    6. var fallOff = FallOff.Gauss;
    7.  
    8. static function LinearFalloff (distance : float , inRadius : float) {
    9.     return Mathf.Clamp01(1.0 - distance / inRadius);
    10. }
    11.  
    12. static function GaussFalloff (distance : float , inRadius : float) {
    13.     return Mathf.Clamp01 (Mathf.Pow (360.0, -Mathf.Pow (distance / inRadius, 2.5) - 0.01));
    14. }
    15.  
    16. function NeedleFalloff (dist : float, inRadius : float)
    17. {
    18.     return -(dist*dist) / (inRadius * inRadius) + 1.0;
    19. }
    20.  
    21. function DeformMesh (mesh : Mesh, position : Vector3, power : float, inRadius : float)
    22. {
    23.     var vertices = mesh.vertices;
    24.     var normals = mesh.normals;
    25.     var sqrRadius = inRadius * inRadius;
    26.    
    27.     // Calculate averaged normal of all surrounding vertices  
    28.     var averageNormal = Vector3.zero;
    29.     for (var i=0;i<vertices.length;i++)
    30.     {
    31.         var sqrMagnitude = (vertices[i] - position).sqrMagnitude;
    32.         // Early out if too far away
    33.         if (sqrMagnitude > sqrRadius)
    34.             continue;
    35.  
    36.         var distance = Mathf.Sqrt(sqrMagnitude);
    37.         var falloff = LinearFalloff(distance, inRadius);
    38.         averageNormal += falloff * normals[i];
    39.     }
    40.     averageNormal = averageNormal.normalized;
    41.    
    42.     // Deform vertices along averaged normal
    43.     for (i=0;i<vertices.length;i++)
    44.     {
    45.         sqrMagnitude = (vertices[i] - position).sqrMagnitude;
    46.         // Early out if too far away
    47.         if (sqrMagnitude > sqrRadius)
    48.             continue;
    49.  
    50.         distance = Mathf.Sqrt(sqrMagnitude);
    51.         switch (fallOff)
    52.         {
    53.             case FallOff.Gauss:
    54.                 falloff = GaussFalloff(distance, inRadius);
    55.                 break;
    56.             case FallOff.Needle:
    57.                 falloff = NeedleFalloff(distance, inRadius);
    58.                 break;
    59.             default:
    60.                 falloff = LinearFalloff(distance, inRadius);
    61.                 break;
    62.         }
    63.        
    64.         vertices[i] += averageNormal * falloff * power;
    65.     }
    66.    
    67.     mesh.vertices = vertices;
    68.     mesh.RecalculateNormals();
    69.     mesh.RecalculateBounds();
    70. }
    71.  
    72. function Update () {
    73.  
    74.     // When no button is pressed we update the mesh collider
    75.     if (!Input.GetMouseButton (0))
    76.     {
    77.         // Apply collision mesh when we let go of button
    78.         ApplyMeshCollider();
    79.         return;
    80.     }
    81.        
    82.        
    83.     // Did we hit the surface?
    84.     var hit : RaycastHit;
    85.     var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    86.     if (Physics.Raycast (ray, hit))
    87.     {
    88.         var filter : MeshFilter = hit.collider.GetComponent(MeshFilter);
    89.         if (filter)
    90.         {
    91.             // Don't update mesh collider every frame since physX
    92.             // does some heavy processing to optimize the collision mesh.
    93.             // So this is not fast enough for real time updating every frame
    94.             if (filter != unappliedMesh)
    95.             {
    96.                 ApplyMeshCollider();
    97.                 unappliedMesh = filter;
    98.             }
    99.            
    100.             // Deform mesh
    101.             var relativePoint = filter.transform.InverseTransformPoint(hit.point);
    102.             DeformMesh(filter.mesh, relativePoint, pull * Time.deltaTime, radius);
    103.         }
    104.     }
    105. }
    106.  
    107. function ApplyMeshCollider () {
    108.     if (unappliedMesh && unappliedMesh.GetComponent(MeshCollider)) {
    109.         unappliedMesh.GetComponent(MeshCollider).sharedMesh = unappliedMesh.sharedMesh;
    110.     }
    111.     unappliedMesh = null;
    112. }
     
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,859
    It really is just that. On line 64, we are adding the normal (times a couple of scaling factors) to the position of a vertex. The "normal" to a surface is a vector that points out, directly away from the surface at that point. So this code, as it is, causes the surface to bulge out.

    If you change += to -=, so you're subtracting the normal rather than adding it, then it will instead cause the surface to dent in.

    Of course this is a long way from having something that acts like clay... a sculpting program gets very complicated, and should probably be based on something like isosurfaces or metaballs instead. (Wow, that just brought to mind a simple metaball modeler I made for POV-Ray, called Jam, back in 1999! Good times.)