Skip to content

Instantly share code, notes, and snippets.

@GRGSIBERIA
Last active January 4, 2016 07:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GRGSIBERIA/8586645 to your computer and use it in GitHub Desktop.
Save GRGSIBERIA/8586645 to your computer and use it in GitHub Desktop.
擬似的なスキンメッシュアニメーションをやるスクリプト
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
using System.IO;
using System.Text;
public class SkinnedMeshConverter
{
// 頂点インデックスとウェイトのペア
class IndexWeight
{
public int Index { get; private set; }
public float Weight { get; private set; }
public IndexWeight(int index, float weight)
{
Index = index;
Weight = weight;
}
}
GameObject gameObject;
GameObject rootBone;
Transform[] boneList;
Vector3[] originalVertices;
Vector3[] copiedVertices;
BoneWeight[] boneWeights;
Transform[] breadthDepthTransforms;
Dictionary<Transform, List<IndexWeight>> boneToVertexAndWeight = new Dictionary<Transform, List<IndexWeight>>();
// 変数の初期化とか
void InitVariables()
{
var skinnedmesh = gameObject.GetComponent<SkinnedMeshRenderer>();
boneList = skinnedmesh.bones;
originalVertices = skinnedmesh.sharedMesh.vertices;
copiedVertices = (Vector3[])originalVertices.Clone();
boneWeights = skinnedmesh.sharedMesh.boneWeights;
CollectBoneWeight();
breadthDepthTransforms = ConstructBreadthDepthTransforms();
}
public SkinnedMeshConverter(GameObject gameObject, GameObject rootBone)
{
this.gameObject = gameObject;
this.rootBone = rootBone;
InitVariables();
foreach (var t in breadthDepthTransforms)
{
TransformVerticesFromBone(t);
}
}
public void ExportCSV(string filename_without_extension)
{
string path = "C:/" + filename_without_extension + ".csv";
using (StreamWriter sw = new StreamWriter(path, false, Encoding.GetEncoding("shift_jis")))
{
for (int i = 0; i < copiedVertices.Length; i++)
{
if (originalVertices[i] != copiedVertices[i])
{
var v = originalVertices[i] - copiedVertices[i];
sw.WriteLine(string.Format("{0},{1},{2},{3}", i, v.x, v.y, v.z));
}
}
}
}
Transform[] ConstructBreadthDepthTransforms()
{
// 最初のボーンを処理する
var transformList = new List<List<Transform>>();
var root = rootBone.transform;
transformList.Add(new List<Transform>());
transformList[0].Add(root);
// 再帰的に幅優先でボーンを取得する
ConstructBreadthDepthTransforms(1, root, transformList);
// 幅優先で取得したボーンをそのまま配列に展開する
List<Transform> buffer = new List<Transform>();
foreach (var list in transformList)
buffer.AddRange(list);
return buffer.ToArray();
}
void ConstructBreadthDepthTransforms(int depth, Transform target, List<List<Transform>> transformList)
{
// もっと深くなったらリストをnewする
if (transformList.Count <= depth)
transformList.Add(new List<Transform>());
// 幅優先でTransformを並べる
for (int i = 0; i < target.childCount; i++)
{
var child = target.GetChild(i);
transformList[depth].Add(child);
ConstructBreadthDepthTransforms(depth + 1, child, transformList);
}
}
void TransformVerticesFromBone(Transform target)
{
// ボーンごとにアサインされている頂点をブレンディングする
if (boneToVertexAndWeight.ContainsKey(target))
{
foreach (var bw in boneToVertexAndWeight[target])
{
var vertex = originalVertices[bw.Index];
var vector = vertex - target.position;
var rotate = Quaternion.Slerp(Quaternion.identity, target.localRotation, bw.Weight);
var new_vector = rotate * vector;
originalVertices[bw.Index] = new_vector + target.position;
}
}
}
void CollectBoneWeight()
{
for (int vi = 0; vi < boneWeights.Length; vi++)
{
// BoneWeightの中身を展開して一つ一つ頂点とTransformを対応付ける
int[] indices = { boneWeights[vi].boneIndex0, boneWeights[vi].boneIndex1, boneWeights[vi].boneIndex2, boneWeights[vi].boneIndex3 };
float[] weights = { boneWeights[vi].weight0, boneWeights[vi].weight1, boneWeights[vi].weight2, boneWeights[vi].weight3 };
CollectIndicesAndWeight(vi, indices, weights);
}
}
void CollectIndicesAndWeight(int vi, int[] indices, float[] weights)
{
for (int j = 0; j < 4; j++)
{
// ボーンごとにアサインされている頂点とウェイトを収集する
var t = boneList[indices[j]];
if (!boneToVertexAndWeight.ContainsKey(t))
boneToVertexAndWeight[t] = new List<IndexWeight>();
if (weights[j] > 0f)
boneToVertexAndWeight[t].Add(new IndexWeight(vi, weights[j]));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment