Created
May 11, 2017 13:50
-
-
Save onotchi/97078dd96293657dea5e7cb3efd72a67 to your computer and use it in GitHub Desktop.
メッシュの頂点を動かして、プロ生ちゃんの舌を操作する
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Linq; | |
using UnityEngine; | |
namespace PronamaChan | |
{ | |
public class TongueMorph : MonoBehaviour | |
{ | |
private class DefaultVertex | |
{ | |
public int Index { get; set; } | |
public Vector3 Vertex { get; set; } | |
} | |
public SkinnedMeshRenderer SkinnedMeshRenderer; | |
public float Width = 1; | |
//前後移動 | |
[Range(0, 4)] | |
public float MoveForward = 0; | |
//上下移動 | |
[Range(0, 2)] | |
public float MoveUp = 0; | |
//縦回転中心 | |
[Range(0, 1)] | |
public float VerticalRotationCenter = 0.5f; | |
//縦回転 | |
[Range(-90, 90)] | |
public float VerticalRotation = 0; | |
//横回転 | |
[Range(-90, 90)] | |
public float HorizontalRotation = 0; | |
//傾き | |
[Range(-90, 90)] | |
public float Inclination = 0; | |
public int TongueIndex; | |
private Vector3 _rotationCenter; | |
private float _verticalRotationCenterZero; | |
private float _verticalRotationCenterVolume; | |
private Mesh _mesh; | |
private DefaultVertex[] _defaultTongueVertices; | |
// Use this for initialization | |
private void Start() | |
{ | |
//SkinnedMeshRendererの取得 | |
if (this.SkinnedMeshRenderer == null) | |
{ | |
this.SkinnedMeshRenderer = this.GetComponentInChildren<SkinnedMeshRenderer>(); | |
} | |
//メッシュのクローンをSkinnedMeshRendererにセット | |
this._mesh = this.SkinnedMeshRenderer.sharedMesh; | |
this._mesh = GameObject.Instantiate(this._mesh); | |
this._mesh.MarkDynamic(); | |
this.SkinnedMeshRenderer.sharedMesh = this._mesh; | |
//舌のサブメッシュのインデックスリスト取得 | |
var triangles = this._mesh.GetTriangles(this.TongueIndex); | |
var trianglesUnique = triangles.Distinct().ToArray(); | |
//舌の頂点位置保存 | |
this._defaultTongueVertices = trianglesUnique.Select(x => new DefaultVertex { Index = x, Vertex = this._mesh.vertices[x] }).ToArray(); | |
//回転中心の決定 | |
var minMax = _defaultTongueVertices.Select(x => new { MinY = x.Vertex.y, MaxY = x.Vertex.y, MinZ = x.Vertex.z, MaxZ = x.Vertex.z }) | |
.Aggregate((x, y) => new { MinY = Mathf.Min(x.MinY, y.MinY), MaxY = Mathf.Max(x.MaxY, y.MaxY), MinZ = Mathf.Min(x.MinZ, y.MinZ), MaxZ = Mathf.Max(x.MaxZ, y.MaxZ) }); | |
this._rotationCenter = new Vector3(0, 0, (minMax.MinZ + minMax.MaxZ) / 2f); | |
this._verticalRotationCenterZero = minMax.MaxY; | |
this._verticalRotationCenterVolume = minMax.MaxY - minMax.MinY; | |
} | |
// Update is called once per frame | |
private void Update() | |
{ | |
} | |
public void OnValidate() | |
{ | |
if (this._defaultTongueVertices == null) | |
{ | |
return; | |
} | |
//現在の頂点取得 | |
var vertices = this._mesh.vertices; | |
foreach (var defaultVertex in this._defaultTongueVertices) | |
{ | |
var newVertex = defaultVertex.Vertex; | |
//舌の幅の変更 | |
newVertex.x *= this.Width; | |
//縦方向回転 | |
{ | |
//回転の中心を舌の根元から任意の位置に移動 | |
var rotationCenterVertical = this._rotationCenter; | |
rotationCenterVertical.y = this._verticalRotationCenterZero - this._verticalRotationCenterVolume * this.VerticalRotationCenter; | |
//任意の位置から先だけを回転 | |
if (defaultVertex.Vertex.y < rotationCenterVertical.y) | |
{ | |
newVertex = Quaternion.Euler(this.VerticalRotation, 0, 0) * (newVertex - rotationCenterVertical) + rotationCenterVertical; | |
} | |
} | |
//横方向回転・傾き | |
newVertex = Quaternion.Euler(0, this.Inclination, this.HorizontalRotation) * (newVertex - this._rotationCenter) + this._rotationCenter; | |
//前後上下移動 | |
newVertex.y += -this.MoveForward / 100.0f; | |
newVertex.z += this.MoveUp / 100.0f; | |
vertices[defaultVertex.Index] = newVertex; | |
} | |
this._mesh.vertices = vertices; | |
this._mesh.RecalculateNormals(); | |
this._mesh.RecalculateBounds(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment