Search Unity

UV reset problem

Discussion in 'Scripting' started by vladk, Nov 29, 2015.

  1. vladk

    vladk

    Joined:
    Jul 10, 2008
    Posts:
    167
    Hi.

    I have a problem resetting the UV on a textured SKINNED mesh. Here is the setup:

    I've got mesh, it gets changed (vertices) and the texture on it deforms and changes accordingly.

    After deformations are done I need to "reset" the UV so the texture stays unchanged while the mesh keeps changes.

    What I do is I save the original vertex and UV coordinates and after changes are done I add the difference between new and original vertices to original UVs. But it works only on a plane object when I don't change Z axis, if I create something more sophisticated (like a sphere) or try to change vertices location on Z axis it completely fails.

    Here is the script:

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class UVTest : MonoBehaviour
    6. {
    7.     public Mesh mesh;
    8.  
    9.     public SkinnedMeshRenderer meshRenderer;
    10.  
    11.     public float deformDelta = .1f;
    12.  
    13.     private Mesh workingMesh;
    14.  
    15.     private Vector3[] originalVerts;
    16.     private Vector2[] originalUV;
    17.  
    18.     void Start()
    19.     {
    20.         workingMesh = Instantiate<Mesh>(mesh);
    21.  
    22.         meshRenderer.sharedMesh = workingMesh;
    23.  
    24.         originalVerts = workingMesh.vertices;
    25.         originalUV = workingMesh.uv;
    26.  
    27.         StartCoroutine(UpdateSkinnedMesh());
    28.     }
    29.  
    30.     void Update()
    31.     {
    32.         //RealTimeUpdateSkinnedMesh();
    33.         if (Input.GetKeyDown(KeyCode.Return))
    34.             AdjustUV();
    35.     }
    36.  
    37.     private IEnumerator UpdateSkinnedMesh()
    38.     {
    39.         float timer = 3f;
    40.  
    41.         while (timer > 0)
    42.         {
    43.             float delta = Time.deltaTime;
    44.  
    45.             Vector3[] verts = workingMesh.vertices;
    46.             for (int i = 0; i < verts.Length; i++)
    47.             {
    48.                 float newX = Random.Range(-deformDelta, deformDelta);
    49.                 float newY = Random.Range(-deformDelta, deformDelta);
    50.                 float newZ = Random.Range(-deformDelta, deformDelta);
    51.  
    52.                 verts[i] += new Vector3(newX, newY, newZ) * delta;
    53.             }
    54.             workingMesh.vertices = verts;
    55.  
    56.             workingMesh.RecalculateNormals();
    57.  
    58.             timer -= delta;
    59.  
    60.             yield return new WaitForEndOfFrame();
    61.         }
    62.     }
    63.  
    64.     private void AdjustUV()
    65.     {
    66.         for (int i = 0; i < workingMesh.vertexCount; i++)
    67.         {
    68.             Vector3 delta = workingMesh.vertices[i] - originalVerts[i];
    69.             originalUV[i] += new Vector2(delta.x, delta.y);
    70.         }
    71.  
    72.         workingMesh.uv = originalUV;
    73.  
    74.         workingMesh.RecalculateNormals();
    75.     }
    76. }
    77.  
    78.  
     
    Last edited: Dec 1, 2015
  2. vladk

    vladk

    Joined:
    Jul 10, 2008
    Posts:
    167
    So anyone? Any ideas?
     
  3. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    This is not a trivial problem. Most modeling suites have a very limited functionality for this, breaking as soon as you move elements too far away from their original projection. You are unlikely to find a generic solution that give perfect results on any kind of object.
    You'd need some way of retrieving the projection used to generate the uv in the first place, or at least something similar, and then reapply it after you've done your transformations.
    I don't have the mathematical expertise to help you any further with this.