public MMDModel(Vert[] vertex, IEnumerable <Material> material, string path) { DirPath = path; Vertice = vertex; OrigVertice = new Vert[Vertice.Length]; Vertice.ArrayFullCopy(OrigVertice); Materials = material.ToList(); GpuData = new GPUData( ); GpuData.Alpha = 1; Cast = new SphereCast(Matrix.Zero); }
public MMDModel(string path) { DirPath = Directory.GetParent(path).FullName; string[] lines = File.ReadAllLines(path); //;Face,親材質名,面Index,頂点Index1,頂点Index2,頂点Index3 //Face,"スカート腕ヘドフォン",0,858,840,855 // のように最初の文字列がVertexだと頂点 Faceだと面になる ;が最初に来るものは説明用のものなので弾く var gr = lines.GroupBy(l => l.Split(',')[0]); var gs = gr.Where(g => !g.Key.Contains(";")).ToDictionary(s => s.Key, g => g.ToList( )); Vertice = ParseCSV(gs["Vertex"]).ToArray( ); OrigVertice = new Vert[Vertice.Length]; Vertice.ArrayFullCopy(OrigVertice); // 次の文字列は材質名になるので、材質名のグループを作る var faceGr = gs["Face"].GroupBy(s => s.Split(',')[1]).ToDictionary(s => s.Key, g => g.ToList( )); Materials = Material.MakeFromCSV(gs["Material"], faceGr, Vertice).ToList(); GpuData = new GPUData( ); GpuData.Alpha = 1; Cast = new SphereCast(Matrix.Zero); }
//頂点グループ以外done 呼んでいない void lattice_deform_verts(int count, int id) { //頂点グループは未対応 //vgroup && vgroup[0] && use_vgroups int len = verts.Length; var nverts = new Vertex[len]; verts.CopyTo(nverts, 0); int s = len / count; for (int i = id * len; i < id * len + s; i++) { if (i >= len) { break; } //var pos = verts[i]; //Debug.DrawLine(pos, pos + n[i]*0.1f); calc_latt_deform(ref nverts[i], factor, i); } mesh.Vertice = nverts; //mesh.RecalculateNormals(); }
//リサイズ部分以外終わり // latice割数を増やす void BKE_lattice_resize(int uNew, int vNew, int wNew) //, Object *ltOb) { //頂点ウェイトグループはすべて開放される if (dvert.Length != 0) { //BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); //lt->dvert = NULL; } while (uNew * vNew * wNew > 32000) { if (uNew >= vNew && uNew >= wNew) { uNew--; } else if (vNew >= uNew && vNew >= wNew) { vNew--; } else { wNew--; } } var vertexCos = new Vertex[uNew * vNew * wNew]; //tmp_vcos var fudu = calc_lat_fudu(gridFlag, uNew); var fvdv = calc_lat_fudu(gridFlag, vNew); var fwdw = calc_lat_fudu(gridFlag, wNew); if (alreadyCreate) { //1分割まで減らされたり、元から1分割でないなら if (uNew != 1 && UVW[0] != 1) { du = (UVW[0] - 1) * du / (uNew - 1); } if (vNew != 1 && UVW[1] != 1) { dv = (UVW[1] - 1) * dv / (vNew - 1); } if (wNew != 1 && UVW[2] != 1) { dw = (UVW[2] - 1) * dw / (wNew - 1); } } var co = vertexCos; fu = fudu[0]; du = fudu[1]; fv = fvdv[0]; dv = fvdv[1]; fw = fwdw[0]; dw = fwdw[1]; float wc = fw; float vc = fv; float uc = fu; int coi = 0; for (int w = 0; w < wNew; w++, wc += dw) { vc = fv; for (int v = 0; v < vNew; v++, vc += dv) { uc = fu; for (int u = 0; u < uNew; u++, coi++, uc += du) { var cv = new Vector3(-uc, -vc, -wc); // todo 同じかどうかよく調べる co[coi].Position = (cv); } } } if (alreadyCreate) { //var mat = new float[4, 4]; var typeu = keytype; //lt->typeu, typev = lt->typev, typew = lt->typew; //endpointsがマッチするので強制的にlinに変える //lt->typeu = lt->typev = lt->typew keytype = KEYType.KEY_LINEAR; //変更された座標を使わないように //BKE_displist_free(<Ob->curve_cache->disp); //オブジェクトの行列を退避、デフォームさせてから戻す //copy_m4_m4(mat, ltOb->obmat); //unit_m4(ltOb->obmat); #if false var mat = transform.localToWorldMatrix; #endif //transform.localToWorldMatrix = Matrix4x4.identity; lattice_deform_vertsFull( ); //copy_m4_m4(ltOb->obmat, mat); keytype = typeu; //lt->typeu = typeu; //lt->typev = typev; //lt->typew = typew; } alreadyCreate = true; // pntsu UVW[0] = uNew; UVW[1] = vNew; UVW[2] = wNew; actbp = LT_ACTBP_NONE; //bpの処理をしていないが、これでいいはず LatticeString = co.Select(x => new ReactiveProperty <string>(x.ToString( ))).ToList( ); LatticeData = LatticeString.Select(reactiveProperty).ToArray( ); RelativeLattice = new LatticeType[LatticeData.Length]; }
//頂点数だけculcする,done void calc_latt_deform(ref Vertex co, float weight, int ind) { //obは対象オブジェクト int defgrp_index = -1; var co_pre = co; Vector3 co_prev;// = sv( 0 ); float weight_blend = 0; if (EnableVertexGroup) { co_prev = co.Position; } //coはモデルのローカル頂点、ラティスの座標系に移動する var vec = latma.TransByMat(co.Position); float u, v, w; int ui, vi, wi; if (UVW[0] > 1) { u = (vec[0] - fu) / du; ui = Util.FloorToInt(u); u -= ui; key_curve_position_weights(u, tu, keytype); } else { tu[0] = tu[2] = tu[3] = 0.0f; tu[1] = 1.0f; ui = 0; } if (UVW[1] > 1) { v = (vec[1] - fv) / dv; vi = Util.FloorToInt(v); v -= vi; key_curve_position_weights(v, tv, keytype); } else { tv[0] = tv[2] = tv[3] = 0.0f; tv[1] = 1.0f; vi = 0; } if (UVW[2] > 1) { w = (vec[2] - fw) / dw; wi = Util.FloorToInt(w); w -= wi; key_curve_position_weights(w, tw, keytype); } else { tw[0] = tw[2] = tw[3] = 0.0f; tw[1] = 1.0f; wi = 0; } int idx_w = 0, idx_v, idx_u; int uu, vv, ww; for (ww = wi - 1; ww <= wi + 2; ww++) { //tw[0~3] w = tw[ww - wi + 1]; if (w != 0.0f) { if (ww > 0) { //idx_wをwi-1 * uの分割 *vの分割 if (ww < UVW[2]) { idx_w = ww * UVW[0] * UVW[1]; } else { idx_w = (UVW[2] - 1) * UVW[0] * UVW[1]; } } else { idx_w = 0; } for (vv = vi - 1; vv <= vi + 2; vv++) { v = w * tv[vv - vi + 1]; if (v != 0.0f) { if (vv > 0) { if (vv < UVW[1]) { idx_v = idx_w + vv * UVW[0]; } else { idx_v = idx_w + (UVW[1] - 1) * UVW[0]; } } else { idx_v = idx_w; } for (uu = ui - 1; uu <= ui + 2; uu++) { u = weight * v * tu[uu - ui + 1]; if (u != 0.0f) { if (uu > 0) { if (uu < UVW[0]) { idx_u = idx_v + uu; } else { idx_u = idx_v + (UVW[0] - 1); } } else { idx_u = idx_v; } int v1 = LatticeData.Length - idx_u - 1; var ldata = LatticeData[v1]; Vector3 vector3 = (ldata.Value.Position * u); co.Position += vector3; //co += transform.localPosition; //頂点グループが設定されているならウェイトをもらってきて計算に入れる if (defgrp_index != -1) //恐らくdvert[idx_u] { weight_blend += (u); //* defvert_find_weight(dvert + idx_u, defgrp_index)); } } } } } } } // 異様にuが小さくなってしまう co.Position += co_pre.Position; //if (defgrp_index != -1) //math_vector.c weight_blendで線形補完 // interp_v3_v3v3(co, co_prev, co, weight_blend); }
//lattice_deform_vertsから呼ばれる,notested done void init_latt_deform() { MMDModel ob = null; Matrix4x4 latmat; Matrix4x4 imat; if (ob == null) { //デフォームスペースの行列 latmat = latma.Inverted(); //デフォーム配列に戻す imat = latmat.Inverted(); } //今のところここに入るパターンが無い else { imat = latma.Inverted( ); //latmat = imat * myself; latmat = Matrix4x4.Identity; //imat = latmat.inverse; } //BPoint bp;//頂点だけ参照している、lattice int id = 0; var ffu = fu; var ffv = fv; var ffw = fw; List <Vertex> vertices = new List <Vertex>( ); for (int w = 0; w < UVW[2]; w++, fw += dw) { for (int v = 0; v < UVW[1]; v++, fv += dv) { for (int u = 0; u < UVW[0]; u++, //bp++, co += 3, fp += 3, fu += du) { //coはlattice座標 fpは初期fu,fv,fwで引かれて0になる Vertex value = LatticeData[id].Value; #if true value.Position = (mul_mat3_m4_v3(imat, value.Position)); vertices.Add(value); #else Vector3 pos = value.Position - new Vector3(fu, fv, fw); //latmatをかけて行列を戻す value.Position = (mul_mat3_m4_v3(imat, pos)); vertices.Add(value); // ちゃんと変更 RelativeLattice[id] = new LatticeType(value); // 常に相対になりたい // 0 0 0 -> -1 -1 -1 //RelativeLattice[ id ].ToReactivePropertyAsSynchronized( x => x.Value , // convert :x => x + value ,convertBack: x => x - value ); #endif id++; } fu = ffu; } fv = ffv; } fw = ffw; RelativeLattice = LatticeData.Select( (lat, i) => lat.Select( // x => x.Value , convert: x => LatticeData[i].Value - vertices[i] //, convertBack: x => vertices[ i ] - LatticeData[i].Value) ).ToReactiveProperty()).ToArray(); latma = latmat; }