本日は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);
}
}