Skip to content

Instantly share code, notes, and snippets.

@tracebox55
Last active August 29, 2015 13:56
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 tracebox55/8881942 to your computer and use it in GitHub Desktop.
Save tracebox55/8881942 to your computer and use it in GitHub Desktop.
//
// ボーンに手動ベイク用のガイドオブジェクトをくっつける
// [簡易形式]AddGuideObject.cx
// ここにガイドオブジェクトをつけたいボーンを記述する
string[] targetlist = new string[]{
"首",
"頭",
"左腕",
"左ひじ",
"右腕",
"右ひじ",
};
// 材質色リスト(X,Y,Z順)
V4[] colorlist = new V4[]{
new V4(1f,0f,0f,1f),
new V4(0f,1f,0f,1f),
new V4(0f,0f,1f,1f)
};
// 材質作成
IPXMaterial[] mlist = new IPXMaterial[3];
for (int i = 0; i < 3; i++)
{
string s = string.Format("_guide_{0}", "XYZ"[i]);
foreach (IPXMaterial m in material)
{
if (m.Name == s) // 作成済みなら流用(二重実行対策)
{
mlist[i] = m;
break;
}
}
if (mlist[i] == null)
{
mlist[i] = bdx.Material();
mlist[i].Name = s;
mlist[i].Ambient = colorlist[i].ToV3();
mlist[i].Diffuse = colorlist[i];
mlist[i].Power = 6f;
material.Add(mlist[i]);
}
}
StringBuilder sb = new StringBuilder();
// ガイドオブジェクトの頂点座標と法線
sb.Append("0.05,0.15,-5,1,0,0|0.05,-0.05,-5,1,0,0|0.05,-0.05,-5.299999,1,0,0|-0.05,0.15,-5,0,0,1|-0.05,-0.05,-5,0,0,1|");
sb.Append("0.05,-0.05,-5,0,0,1|0.05,0.15,-5,0,0,1|0.05,-0.05,-5.299999,0,-1,0|-0.05,-0.05,-5,0,-1,0|");
sb.Append("-0.05,-0.05,-5.299999,0,-1,0|-0.05,-0.05,-5.299999,-1,0,0|-0.05,0.15,-5,-1,0,0|0.05,-0.05,-5.299999,0,0.7071067,-0.7071067|");
sb.Append("0.05,-0.05,-5,0,0,1|0.05,0.05,-5,0,0,-1|0.05,-0.05,-5,0,0,-1|-0.05,-0.05,-5,0,0,-1|");
sb.Append("-0.05,0.05,-5,0,0,-1|0.05,0.05,5,1,0,0|0.05,-0.05,5,1,0,0|0.05,-0.05,-5,1,0,0|");
sb.Append("0.05,0.05,-5,1,0,0|-0.05,0.05,5,0,0,1|-0.05,-0.05,5,0,0,1|0.05,-0.05,5,0,0,1|0.05,0.05,5,0,0,1|");
sb.Append("-0.05,0.05,-5,-1,0,0|-0.05,-0.05,-5,-1,0,0|-0.05,-0.05,5,-1,0,0|-0.05,0.05,5,-1,0,0|0.05,0.05,-5,0,1,0|");
sb.Append("-0.05,0.05,-5,0,1,0|0.05,-0.05,-5,0,-1,0|-0.05,-0.05,-5,0,-1,0|0.05,-0.05,-5,0,-1,0|-0.05,-0.05,-5,-1,0,0|");
sb.Append("-0.05,0.15,-5,0,0.7071067,-0.7071067|-0.05,-0.05,-5.299999,0,0.7071067,-0.7071067|-0.05,0.15,-5,0,0,1|");
sb.Append("0.05,0.15,-5,0,0.7071067,-0.7071067|0.05,0.05,5,0,1,0|-0.05,0.05,5,0,1,0|0.05,-0.05,5,0,-1,0|-0.05,-0.05,5,0,-1,0");
string[] vertexlist = sb.ToString().Split(new char[]{',', '|'},StringSplitOptions.RemoveEmptyEntries);
// ガイドオブジェクトの面構成(参照する頂点の定義)
sb.Clear();
sb.Append("0,1,2|3,4,5|3,5,6|7,34,8|7,8,9|10,35,11|36,12,37|38,13,6|36,39,12|14,15,16|14,16,17|18,19,20|18,20,21|22,23,24|22,24,25|");
sb.Append("26,27,28|26,28,29|40,30,31|40,31,41|32,42,43|32,43,33");
string[] facelist = sb.ToString().Split(new char[]{',', '|'}, StringSplitOptions.RemoveEmptyEntries);
// ガイドオブジェクトの各軸拡大縮小率
V3[] scalelist = new V3[]{
new V3(0.5f, 0.5f, 0.5f), // X軸
new V3(0.5f, 0.5f, 0.5f), // Y軸
new V3(0.5f, 0.5f, 0.5f), // Z軸
};
// 指定されたボーンにガイドオブジェクトをくっつけていく
foreach(string target in targetlist)
{
// 対象ボーン検索
IPXBone b = null;
foreach (IPXBone bb in bone)
{
if (bb.Name == target)
{
b = bb;
break;
}
}
if (b == null)
{
//throw new Exception(string.Format("ボーン {0} がみつかりませんでした。", target));
continue; // 見つからなかったら無視して次へ
}
// XYZ軸作成
IList<IPXVertex> vlist = new List<IPXVertex>();
for (int i = 0; i < 3; i++)
{
vlist.Clear();
Matrix scallmatrix = (Matrix.Scaling(scalelist[i])); // 拡大縮小行列
Matrix transmatrix = Matrix.Translation(b.Position); // ボーン位置へ移動する行列
// 軸を構成する頂点を作成
for (int j = 0; j < vertexlist.Length; j += 6)
{
// 頂点リストから位置と法線を取得
V3 vpos = new V3(float.Parse(vertexlist[j + 0]), float.Parse(vertexlist[j + 1]), float.Parse(vertexlist[j + 2]));
V3 vnor = new V3(float.Parse(vertexlist[j + 3]), float.Parse(vertexlist[j + 4]), float.Parse(vertexlist[j + 5]));
IPXVertex vtemp = bdx.Vertex();
// 取得した頂点はZ方向なので各軸用に回転する
switch(i)
{
case 0:
vpos = Vector3.TransformCoordinate(vpos, Matrix.RotationY((float)(90f * Math.PI / 180)) * scallmatrix);
break;
case 1:
vpos = Vector3.TransformCoordinate(vpos, Matrix.RotationX((float)(90f * Math.PI / 180)) * scallmatrix);
break;
case 2:
vpos = Vector3.TransformCoordinate(vpos, scallmatrix);
break;
}
vtemp.Position = Vector3.TransformCoordinate(vpos, transmatrix );
vtemp.Normal = Vector3.TransformCoordinate(vnor, transmatrix);
vtemp.Bone1 = b;
vtemp.Weight1 = 1.0f;
vertex.Add(vtemp);
vlist.Add(vtemp); // 面に登録するために一時記憶
}
// 作成した頂点を面に登録
for (int j = 0; j < facelist.Length; j += 3)
{
IPXFace ftemp = bdx.Face();
ftemp.Vertex1 = vlist[int.Parse(facelist[j + 0])];
ftemp.Vertex2 = vlist[int.Parse(facelist[j + 1])];
ftemp.Vertex3 = vlist[int.Parse(facelist[j + 2])];
mlist[i].Faces.Add(ftemp); // 材質に面を登録
}
}
}
// 結果を反映
connect.Pmx.Update(pmx);
// 各種更新
connect.Form.UpdateList(UpdateObject.All);
connect.View.PMDView.UpdateModel();
connect.View.PMDView.UpdateView();
//
// 材質を透明にするモーフを作成して登録する
// [簡易形式]CreateInvisibleMorph.cx
string MORPH_NAME = "透明";
// 重複チェック
foreach(IPXMorph m in morph)
{
if( m.Name == MORPH_NAME )
{
throw new Exception(string.Format("モーフ {0} は既に存在します。", MORPH_NAME));
}
}
// モーフ作成
IPXMorph invmorph = bdx.Morph();
invmorph.Kind = MorphKind.Material; // 材質モーフ
invmorph.Name = MORPH_NAME;
invmorph.Panel = 4; // その他パネル
morph.Add(invmorph); // 登録
// 全ての材質(ただし _ 始まりは除く)を透明モーフに登録する
foreach (IPXMaterial mat in material)
{
if (!mat.Name.StartsWith("_"))
{
IPXMaterialMorphOffset mo = bdx.MaterialMorphOffset(); // 材質モーフオフセット作成
mo.Diffuse = new V4(0f, 0f, 0f, 0f);
mo.EdgeSize = 0f;
mo.EdgeColor = new V4(0f, 0f, 0f, 0f);
mo.Op = 0; // 乗算
mo.Material = mat;
invmorph.Offsets.Add(mo);
}
}
// 表示枠にも追加
IPXMorphNodeItem item = bdx.MorphNodeItem();
item.Morph = invmorph;
pmx.ExpressionNode.Items.Add(item);
// 更新
connect.Pmx.Update(pmx);
connect.Form.UpdateList(UpdateObject.Node);
//
// ボーンを可視化する
// [簡易形式]DrawBone.cx
// ここに描画するボーンを記述する
string[] targetlist = new string[]{
"首",
"頭",
"上半身2",
"上半身",
"左肩",
"左腕",
"左ひじ",
"左手首",
"右肩",
"右腕",
"右ひじ",
"右手首",
"下半身",
"左足",
"左ひざ",
"左足首",
"右足",
"右ひざ",
"右足首",
};
float BONE_BASE_SIZE = 0.1f; // 描画ボーンの底辺の長さ
// 材質作成
IPXMaterial boneMaterial = null;
foreach (IPXMaterial m in material)
{
if (m.Name == "_bone")
{
boneMaterial = m; // 作成済みなら流用
break;
}
}
if (boneMaterial == null) // 存在しなければ作成
{
boneMaterial = bdx.Material();
boneMaterial.Name = "_bone";
boneMaterial.Diffuse = new V4(1f, 0.5f, 0f, 1f);
boneMaterial.Ambient = new V3(1f, 0.5f, 0f);
boneMaterial.Power = 6f;
boneMaterial.Edge = true;
boneMaterial.EdgeSize = 1f;
boneMaterial.EdgeColor = new V4(0f, 0f, 0f,1f);
boneMaterial.BothDraw = true;
material.Add(boneMaterial);
}
// 指定されたボーンを描く
foreach (string target in targetlist)
{
// ボーンの位置取得
V3 srcPos;
V3 dstOffset;
IPXBone targetBone = null;
foreach(IPXBone b in bone)
{
if( b.Name == target)
{
targetBone = b;
break;
}
}
if( targetBone == null)
{
continue; // 見つからなければスルーして次
}
srcPos = targetBone.Position;
// ボーン描画ベクトルを取得
if( targetBone.ToBone != null)
{
dstOffset = targetBone.ToBone.Position - targetBone.Position; // 表示先ボーンから計算
}else{
dstOffset = targetBone.ToOffset; // オフセットをそのまま使用
}
V3 dstVector = new V3(dstOffset);
dstVector.Normalize(); // 単位ベクトル取得
// 頂点を作成する
IPXVertex[] vlist = new IPXVertex[3]; // 3頂点で表現する
for (int i = 0; i < vlist.Length; i++)
{
vlist[i] = bdx.Vertex();
vlist[i].Bone1 = targetBone;
vlist[i].Weight1 = 1f;
vertex.Add(vlist[i]);
}
vlist[0].Position = srcPos + new V3(dstVector.Y, dstVector.X * -1f, dstVector.Z) * BONE_BASE_SIZE * 0.5f;
vlist[2].Position = srcPos + new V3(dstVector.Y * -1f, dstVector.X, dstVector.Z) * BONE_BASE_SIZE * 0.5f;
vlist[1].Position = srcPos + dstOffset;
// 頂点を面に登録する
IPXFace boneFace = bdx.Face();
boneFace.Vertex1 = vlist[0];
boneFace.Vertex2 = vlist[2];
boneFace.Vertex3 = vlist[1];
// 面を材質に登録する
boneMaterial.Faces.Add(boneFace);
}
// 結果を反映
connect.Pmx.Update(pmx);
// 各種更新
connect.Form.UpdateList(UpdateObject.All);
connect.View.PMDView.UpdateModel();
connect.View.PMDView.UpdateView();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment