以下の内容はhttps://redhologerbera.hatenablog.com/entry/2024/09/17/232309より取得しました。


Unityでメッシュの任意の頂点を辺に沿って動かす

本日はUnity枠です。

〇環境

・Unity2022.3.26f1

・Windows11PC

〇任意の頂点をメッシュの辺に沿って動かす

BlenderやMayaでは頂点を選択して辺場を動かすことができます。

 これはメッシュの形状を崩さずにトポロジーを変化させるなど非常に強力なモデリングの手法です。

 今回はUnityでメッシュの中の任意の頂点を返上で動かしていきます。

〇Unity側の実装

 Unity側では頂点はmesh.verticesとして頂点ごとに対応したvector3型の配列で取得することができます。

頂点を動かすためには最初の頂点座標を取得し、一つ前の頂点(隣接頂点)の座標を求め移動量を計算できます。

        // 頂点の移動処理
        Vector3[] vertices = mesh.vertices;
        
        // 頂点の現在の位置を取得
        Vector3 originalPosition = originalVertices[vertexIndex];

        // 近隣の頂点(仮に一つ前の頂点と次の頂点)を取得して辺の方向を計算
        Vector3 direction = Vector3.zero;

        if (vertexIndex > 0)
        {
            // 隣の頂点を取得(例として、前の頂点を参照)
            Vector3 neighborPosition = originalVertices[vertexIndex - 1];
            direction = (neighborPosition - originalPosition).normalized;
        }

indexが0場合は1の頂点を隣の頂点座標として求めます。

else if (vertexIndex < mesh.vertexCount - 1)
        {
            // 隣の頂点を取得(例として、次の頂点を参照)
            Vector3 neighborPosition = originalVertices[vertexIndex + 1];
            direction = (neighborPosition - originalPosition).normalized;
        }

後はパラメータに応じて頂点座標を移動させ、メッシュを再構築します。

 vertices[vertexIndex] = originalPosition + direction * moveParameter;

        // メッシュに頂点を適用
        mesh.vertices = vertices;

これによってindexとパラメータを指定すればそのindexに対応する頂点がパラメータの量移動します。

〇コード一覧

using UnityEngine;

public class VertexMovement : MonoBehaviour
{
    public int vertexIndex = 0; // 移動させたい頂点のインデックス(インスペクターで設定)
    public float moveParameter = 0.0f; // 頂点を辺に沿って移動させるパラメータ(インスペクターで設定)
    private Mesh mesh; // メッシュデータ
    private Vector3[] originalVertices; // 初期の頂点位置
    private Vector3[] currentVertices; // 現在の頂点位置

    void Start()
    {
        // MeshFilter からメッシュデータを取得
        MeshFilter meshFilter = GetComponent<MeshFilter>();
        if (meshFilter != null)
        {
            mesh = meshFilter.mesh;
            originalVertices = mesh.vertices; // 初期の頂点位置を保存
            currentVertices = mesh.vertices; // 現在の頂点位置を初期化
        }
        else
        {
            Debug.LogError("MeshFilter not found!");
        }
    }

    void Update()
    {
        // インスペクターで設定されたインデックスの頂点を移動させる
        if (vertexIndex >= 0 && vertexIndex < mesh.vertexCount)
        {
            // 頂点を移動させる
            MoveVertex(vertexIndex, moveParameter);
        }
    }

    void MoveVertex(int vertexIndex, float moveParameter)
    {
        // 頂点の移動処理
        Vector3[] vertices = mesh.vertices;
        
        // 頂点の現在の位置を取得
        Vector3 originalPosition = originalVertices[vertexIndex];

        // 近隣の頂点(仮に一つ前の頂点と次の頂点)を取得して辺の方向を計算
        Vector3 direction = Vector3.zero;

        if (vertexIndex > 0)
        {
            // 隣の頂点を取得(例として、前の頂点を参照)
            Vector3 neighborPosition = originalVertices[vertexIndex - 1];
            direction = (neighborPosition - originalPosition).normalized;
        }
        else if (vertexIndex < mesh.vertexCount - 1)
        {
            // 隣の頂点を取得(例として、次の頂点を参照)
            Vector3 neighborPosition = originalVertices[vertexIndex + 1];
            direction = (neighborPosition - originalPosition).normalized;
        }

        // パラメータに応じて辺に沿って頂点を移動
        vertices[vertexIndex] = originalPosition + direction * moveParameter;

        // メッシュに頂点を適用
        mesh.vertices = vertices;
        mesh.RecalculateBounds(); // バウンディングボックスの再計算(オプション)

        // メッシュの更新を通知
        mesh.UploadMeshData(false);
    }

    public void ResetVertices()
    {
        // 頂点位置を初期化する(リセット)
        mesh.vertices = originalVertices;
        mesh.RecalculateBounds();
        mesh.UploadMeshData(false);
    }
}




以上の内容はhttps://redhologerbera.hatenablog.com/entry/2024/09/17/232309より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14