/// 頂点を追加します。 public void Push(Vertex a, TSOSubMesh sub) { int x = GetX(a.position.X); int y = GetY(a.position.Y); int z = GetZ(a.position.Z); UniqueCell cell = GetCell(x, y, z); cell.Push(a, sub); }
private Matrix[] ClipBoneMatrices(TSOSubMesh sub_mesh, TMOFile tmo) { Matrix[] clipped_boneMatrices = new Matrix[sub_mesh.maxPalettes]; for (int numPalettes = 0; numPalettes < sub_mesh.maxPalettes; numPalettes++) { TSONode tso_node = sub_mesh.GetBone(numPalettes); TMONode tmo_node = tmo.FindNodeByName(tso_node.Name); clipped_boneMatrices[numPalettes] = tso_node.OffsetMatrix * tmo_node.combined_matrix; } return(clipped_boneMatrices); }
/// 警告 'ボーン参照が見つかりませんでした' を出力します。 public void WarnBoneIndexNotFound(Vertex a, TSOSubMesh sub) { Console.WriteLine("### 警告: ボーン参照が見つかりませんでした。修正は諦めます。"); Dump(); for (int i = 0; i < 4; i++) { SkinWeight sw = skin_weights[i]; SkinWeight a_sw = a.skin_weights[i]; Console.WriteLine("{0} sw({1} {2}) a sw({3} {4})", i, sw.bone_index, sw.weight, sub.bone_indices[a_sw.bone_index], a_sw.weight); } Console.WriteLine(); }
/// <summary> /// 同一視頂点を生成します。 /// </summary> /// <param name="a">頂点</param> /// <param name="sub">頂点を含むサブメッシュ</param> public UniqueVertex(Vertex a, TSOSubMesh sub) { this.vertices = new Dictionary <Vertex, TSOSubMesh>(); vertices[a] = sub; this.position = a.position; this.skin_weights = new SkinWeight[4]; for (int i = 0; i < 4; i++) { SkinWeight sw = a.skin_weights[i]; skin_weights[i] = new SkinWeight(sub.bone_indices[sw.bone_index], sw.weight); } opposite_vertex = null; }
/// 対称位置にある同一視頂点のスキンウェイトを複写します。 public void CopyOppositeWeights() { if (opposite_vertex == null) { return; } if (opposite_vertex == this) { return; } //ウェイト値がずれている場合は警告する。 bool weights_gap_found = false; for (int i = 0; i < 4; i++) { SkinWeight sw = skin_weights[i]; SkinWeight opp_sw = opposite_vertex.skin_weights[i]; if (Math.Abs(sw.weight - opp_sw.weight) >= 1.0e-2f) { weights_gap_found = true; break; } } if (weights_gap_found) { WarnOppositeWeights(); } for (int i = 0; i < 4; i++) { SkinWeight sw = skin_weights[i]; SkinWeight opp_sw = opposite_vertex.skin_weights[i]; sw.bone_index = GetOppositeBoneIndex(opp_sw.bone_index); sw.weight = opp_sw.weight; } foreach (KeyValuePair <Vertex, TSOSubMesh> pair in vertices) { Vertex a = pair.Key; TSOSubMesh sub = pair.Value; CopyWeights(a, sub); } }
/// 頂点を追加します。 public void Push(Vertex a, TSOSubMesh sub) { bool found = false; foreach (UniqueVertex v in vertices) { if (LengthSq(a.position, v.position) < float.Epsilon) { v.Push(a, sub); found = true; break; } } if (!found) { vertices.Add(new UniqueVertex(a, sub)); } }
/// 同じ位置にある頂点を追加します。 public void Push(Vertex a, TSOSubMesh sub) { vertices[a] = sub; //頂点のボーン参照が最初の頂点と異なる場合は警告する。 for (int i = 0; i < 4; i++) { SkinWeight sw = skin_weights[i]; SkinWeight a_sw = a.skin_weights[i]; if (sw.weight != 0.0f) { if (sw.bone_index != sub.bone_indices[a_sw.bone_index]) { Console.WriteLine("### 警告: ボーン参照が最初の頂点と異なります。"); Dump(); Console.WriteLine("{0} sw({1} {2}) a sw({3} {4})", i, sw.bone_index, sw.weight, sub.bone_indices[a_sw.bone_index], a_sw.weight); } } } }
void CopyWeights(Vertex a, TSOSubMesh sub) { //ボーン参照が見つからない場合は警告する。 bool bone_index_not_found = false; for (int i = 0; i < 4; i++) { SkinWeight sw = skin_weights[i]; SkinWeight a_sw = a.skin_weights[i]; int a_bone_idx = Array.IndexOf(sub.bone_indices, sw.bone_index); if (a_bone_idx == -1) { a_bone_idx = sub.AddBone(GetBone(sw.bone_index)); } if (a_bone_idx == -1) { if (sw.weight == 0.0f) { a_sw.bone_index = 0; a_sw.weight = 0.0f; } else { bone_index_not_found = true; } } else { a_sw.bone_index = a_bone_idx; a_sw.weight = sw.weight; } } if (bone_index_not_found) { WarnBoneIndexNotFound(a, sub); } }
public static List <TSOSubMesh> CreateSubMeshes(List <TSOFace> faces, int max_palettes) { List <TSOFace> faces_1 = faces; List <TSOFace> faces_2 = new List <TSOFace>(); Heap <int> bh = new Heap <int>(); Heap <UnifiedPositionTexcoordVertex> vh = new Heap <UnifiedPositionTexcoordVertex>(); List <ushort> vert_indices = new List <ushort>(); Dictionary <int, bool> adding_bone_indices = new Dictionary <int, bool>(); List <TSOSubMesh> sub_meshes = new List <TSOSubMesh>(); Console.WriteLine(" vertices bone_indices"); Console.WriteLine(" -------- ------------"); while (faces_1.Count != 0) { int spec = faces_1[0].spec; bh.Clear(); vh.Clear(); vert_indices.Clear(); foreach (TSOFace f in faces_1) { if (f.spec != spec) { faces_2.Add(f); continue; } adding_bone_indices.Clear(); foreach (UnifiedPositionVertex v in f.vertices) { foreach (SkinWeight sw in v.skin_weights) { if (sw.weight < WeightEpsilon) { continue; } if (bh.ContainsKey(sw.bone_index)) { continue; } adding_bone_indices[sw.bone_index] = true; } } if (bh.Count + adding_bone_indices.Count > max_palettes) { faces_2.Add(f); continue; } foreach (int bone_index in adding_bone_indices.Keys) { bh.Add(bone_index); } foreach (UnifiedPositionVertex v in f.vertices) { UnifiedPositionTexcoordVertex a = new UnifiedPositionTexcoordVertex(v, bh.map); if (!vh.ContainsKey(a)) { vh.Add(a); } vert_indices.Add(vh[a]); } } //Console.WriteLine("#vert_indices:{0}", vert_indices.Count); ushort[] optimized_indices = NvTriStrip.Optimize(vert_indices.ToArray()); //Console.WriteLine("#optimized_indices:{0}", optimized_indices.Length); TSOSubMesh sub = new TSOSubMesh(); sub.spec = spec; //Console.WriteLine("#bone_indices:{0}", bh.Count); sub.bone_indices = bh.ary.ToArray(); UnifiedPositionTexcoordVertex[] vertices = new UnifiedPositionTexcoordVertex[optimized_indices.Length]; for (int i = 0; i < optimized_indices.Length; i++) { vertices[i] = vh.ary[optimized_indices[i]]; } sub.vertices = vertices; Console.WriteLine(" {0,8} {1,12}", sub.vertices.Length, sub.bone_indices.Length); sub_meshes.Add(sub); List <TSOFace> faces_tmp = faces_1; faces_1 = faces_2; faces_2 = faces_tmp; faces_tmp.Clear(); } return(sub_meshes); }