unity 拖拽 uv

保存一些代码

 

 

 

using UnityEngine;

public static class Matrix4x4Helper
{
    public static Matrix4x4 Rotate2D(this Matrix4x4 mat, float angle)
    {
        //角度转弧度
        angle = angle * Mathf.Deg2Rad;
        mat.m00 = Mathf.Cos(angle);
        mat.m01 = Mathf.Sin(angle);
        mat.m10 = -Mathf.Sin(angle);
        mat.m11 = Mathf.Cos(angle);
        return mat;
    }
}
public static class MeshHelper
{
    public static Mesh Rotate2DUV(this Mesh mesh,float angle)
    {
        List<Vector2> uvs = new List<Vector2>(mesh.uv);
        
        var mat = new Matrix4x4().Rotate2D(angle);
        Vector2 uvCenter = new Vector2(0.5f,0.5f);
        for(var i=0;i<uvs.Count;i++)
        {
            var uv = uvs[i]- uvCenter;
            uv = (mat * uv);
            uvs[i] = uv+ uvCenter;
        }

        mesh.SetUVs(0, uvs);

        return mesh;
    }
}

 

using System;
using UnityEngine;

public class PanelDrag:MonoBehaviour
{
    const string mainText = "_MainTex";

    [SerializeField] Texture texture;
    public Action onMouseDown;
    public Action onMouseUp;

    Material material;
    Vector2Int textureSize;
    Vector4 offset;
    Vector3 mousePos;
    Vector2 size;
    Matrix4x4 uvRotate;
    float angle;
    Matrix4x4 matRotate;
    Vector4 actualOffset;
    Vector4 textureOffset;
    Vector2 textureScale;
    Mesh mesh;
    Ray ray;
    public Texture CurTexture
    {
        get { return texture; }
        set
        {
            if (value == texture)
                return;
            UpdateTexture(value);
        }
    }

    private void Start()
    {
        mesh = GetComponent<MeshFilter>().mesh;
        material = GetComponent<MeshRenderer>().material;
        UpdateTexture(texture == null ? material.GetTexture(mainText) : texture);
        UpdateScale();
    }

    void UpdateTexture(Texture texture)
    {
        this.texture = texture;
        material.SetTexture(mainText, texture);
        textureScale = material.GetTextureScale(mainText);
        textureSize = new Vector2Int(texture.width, texture.height);
    }

    /// <summary>
    /// 计算Plane实际大小
    /// </summary>
    void UpdateScale()
    {
        var boundsSize = mesh.bounds.size;
        size = new Vector2(boundsSize.x, boundsSize.z);
        size.Scale(new Vector2(transform.localScale.x, transform.localScale.z));
        //mousePos = Vector3.zero;
    }

    public void RotateUV(float angle)
    {
        this.angle += angle;
        mesh = mesh.Rotate2DUV(angle);
        UpdateScale();
        UpdateRotateMatrix();
        UpdateTextureOffset(Vector3.zero);

        //mousePos = Vector3.zero;
    }

    private void OnMouseDown()
    {
        onMouseDown();
        UpdateScale();
        mousePos = GetPanelPos();
        UpdateRotateMatrix();
    }
    private void OnMouseDrag()
    {
        var pos = GetPanelPos();
        UpdateTextureOffset(pos);
        mousePos = pos;
    }

    private void OnMouseUp()
    {
        onMouseUp();
    }

    /// <summary>
    /// 更新旋转矩阵
    /// </summary>
    void UpdateRotateMatrix()
    {
        //获取当前缩放的转置矩阵,逆旋转
        matRotate = Matrix4x4.Rotate(transform.localRotation).transpose;
        //获取UV旋转矩阵
        uvRotate = uvRotate.Rotate2D(angle);
    }

    void UpdateTextureOffset(Vector3 pos)
    {
        //获得欧拉角偏移
        offset += matRotate * (pos - mousePos);
        //设置偏移
        actualOffset.Set(offset.x, offset.z, 1, 1);
        //旋转UV
        actualOffset = uvRotate * actualOffset;
        //平移
        textureOffset.Set(actualOffset.x * textureScale.x / this.size.x, actualOffset.y * textureScale.y / this.size.y, 1, 1);
        //设置图像偏移
        material.SetTextureOffset(mainText, textureOffset);
    }
    
    /// <summary>
    /// 获取从摄像机出发的射线到平面上的点
    /// </summary>
    /// <returns></returns>
    Vector3 GetPanelPos()
    {
        ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        return GetIntersectWithLineAndPlane(ray.origin, ray.direction, transform.up, transform.position);
    }

    /// <summary>
    /// 获取向量到平面的投影
    /// </summary>
    /// <param name="point"></param>
    /// <param name="direct"></param>
    /// <param name="planeNormal"></param>
    /// <param name="planePoint"></param>
    /// <returns></returns>
    private Vector3 GetIntersectWithLineAndPlane(Vector3 point, Vector3 direct, Vector3 planeNormal, Vector3 planePoint)
    {
        float d = Vector3.Dot(planePoint - point, planeNormal) / Vector3.Dot(direct.normalized, planeNormal);

        return d * direct.normalized + point;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱼游戏开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值