/// <summary> /// メッシュデータから頂点/法線/接線をワールド座標変換して返す /// </summary> /// <param name="meshData"></param> /// <param name="boneList"></param> /// <param name="wposList"></param> /// <param name="wnorList"></param> /// <param name="wtanList"></param> /// <returns></returns> public static bool CalcMeshWorldPositionNormalTangent( MeshData meshData, List <Transform> boneList, out List <Vector3> wposList, out List <Vector3> wnorList, out List <Vector3> wtanList ) { wposList = new List <Vector3>(); wnorList = new List <Vector3>(); wtanList = new List <Vector3>(); if (meshData == null || boneList == null) { return(false); } if (meshData.isSkinning == false) { // 通常メッシュ Transform t = boneList[0]; for (int i = 0; i < meshData.VertexCount; i++) { // 頂点スキニング var vw = meshData.vertexWeightList[i]; Vector3 wpos = t.TransformPoint(vw.localPos); Vector3 wnor = t.TransformDirection(vw.localNor); Vector3 wtan = t.TransformDirection(vw.localTan); wposList.Add(wpos); wnorList.Add(wnor); wtanList.Add(wtan); } } else { // スキンメッシュ float[] weights = new float[4]; int[] boneIndexs = new int[4]; for (int i = 0; i < meshData.VertexCount; i++) { Vector3 wpos = Vector3.zero; Vector3 wnor = Vector3.zero; Vector3 wtan = Vector3.zero; // 頂点スキニング uint pack = meshData.vertexInfoList[i]; int wcnt = DataUtility.Unpack4_28Hi(pack); int sindex = DataUtility.Unpack4_28Low(pack); for (int j = 0; j < wcnt; j++) { var vw = meshData.vertexWeightList[sindex + j]; Transform t = boneList[vw.parentIndex]; wpos += t.TransformPoint(vw.localPos) * vw.weight; wnor += t.TransformDirection(vw.localNor) * vw.weight; wtan += t.TransformDirection(vw.localTan) * vw.weight; } wposList.Add(wpos); wnorList.Add(wnor); wtanList.Add(wtan); } } return(true); }
/// <summary> /// メッシュデータ作成 /// </summary> void CreateMeshData(MagicaBoneSpring scr) { // 共有データオブジェクト作成 string dataname = "BoneSpringMeshData_" + scr.name; MeshData mdata = ShareDataObject.CreateShareData <MeshData>(dataname); // トランスフォームリスト作成 var transformList = scr.GetTransformList(); if (transformList.Count == 0) { return; } // 頂点作成 List <Vector3> wposList = new List <Vector3>(); List <Vector3> lposList = new List <Vector3>(); List <Vector3> lnorList = new List <Vector3>(); List <Vector3> ltanList = new List <Vector3>(); Transform myt = scr.transform; for (int i = 0; i < transformList.Count; i++) { var t = transformList[i]; // 頂点追加 var pos = t.position; var lpos = myt.InverseTransformDirection(pos - myt.position); var lnor = myt.InverseTransformDirection(t.forward); var ltan = myt.InverseTransformDirection(t.up); wposList.Add(pos); lposList.Add(lpos); lnorList.Add(lnor); ltanList.Add(ltan); } var vertexInfoList = new List <uint>(); var vertexWeightList = new List <MeshData.VertexWeight>(); for (int i = 0; i < lposList.Count; i++) { // 1ウエイトで追加 uint vinfo = DataUtility.Pack4_28(1, i); vertexInfoList.Add(vinfo); var vw = new MeshData.VertexWeight(); vw.parentIndex = i; vw.weight = 1.0f; vw.localPos = lposList[i]; vw.localNor = lnorList[i]; vw.localTan = ltanList[i]; } mdata.vertexInfoList = vertexInfoList.ToArray(); mdata.vertexWeightList = vertexWeightList.ToArray(); mdata.vertexCount = lposList.Count; // ライン作成 HashSet <uint> lineSet = new HashSet <uint>(); // 構造ライン for (int i = 0; i < transformList.Count; i++) { var t = transformList[i]; var pt = t.parent; if (pt != null && transformList.Contains(pt)) { int v0 = i; int v1 = transformList.IndexOf(pt); uint pair = DataUtility.PackPair(v0, v1); lineSet.Add(pair); } } // ライン格納 List <int> lineList = new List <int>(); foreach (var pair in lineSet) { int v0, v1; DataUtility.UnpackPair(pair, out v0, out v1); lineList.Add(v0); lineList.Add(v1); } mdata.lineList = lineList.ToArray(); mdata.lineCount = lineList.Count / 2; serializedObject.FindProperty("meshData").objectReferenceValue = mdata; serializedObject.ApplyModifiedProperties(); // 使用トランスフォームシリアライズ var property = serializedObject.FindProperty("useTransformList"); var propertyPos = serializedObject.FindProperty("useTransformPositionList"); var propertyRot = serializedObject.FindProperty("useTransformRotationList"); var propertyScl = serializedObject.FindProperty("useTransformScaleList"); property.arraySize = transformList.Count; propertyPos.arraySize = transformList.Count; propertyRot.arraySize = transformList.Count; propertyScl.arraySize = transformList.Count; for (int i = 0; i < transformList.Count; i++) { property.GetArrayElementAtIndex(i).objectReferenceValue = transformList[i]; propertyPos.GetArrayElementAtIndex(i).vector3Value = transformList[i].localPosition; propertyRot.GetArrayElementAtIndex(i).quaternionValue = transformList[i].localRotation; propertyScl.GetArrayElementAtIndex(i).vector3Value = transformList[i].localScale; } serializedObject.ApplyModifiedProperties(); // データ検証とハッシュ mdata.CreateVerifyData(); serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(mdata); }
public ulong GetTetraHash() { return(DataUtility.PackQuater(vertexList[0].index, vertexList[1].index, vertexList[2].index, vertexList[3].index)); }
/// <summary> /// 頂点ウエイト情報の作成 /// </summary> void CreateVertexWeightList( int vcnt, List <Vector3> vertices, List <Vector3> normals, List <Vector4> tangents, List <BoneWeight> boneWeights, List <Matrix4x4> bindPoses, out List <uint> vlist, out List <MeshData.VertexWeight> wlist ) { vlist = new List <uint>(); wlist = new List <MeshData.VertexWeight>(); for (int j = 0; j < vcnt; j++) { var bw = boneWeights[j]; int wcnt = 0; int wstart = wlist.Count; // ローカル座標を事前計算する(バインドポーズ方式よりメモリは食うが実行が速い) if (bw.weight0 > 0.0f) { wcnt++; var vw = new MeshData.VertexWeight(); vw.weight = bw.weight0; vw.parentIndex = bw.boneIndex0; vw.localPos = bindPoses[bw.boneIndex0].MultiplyPoint(vertices[j]); vw.localNor = bindPoses[bw.boneIndex0].MultiplyVector(normals[j]).normalized; vw.localTan = bindPoses[bw.boneIndex0].MultiplyVector(tangents[j]).normalized; wlist.Add(vw); } if (bw.weight1 > 0.0f) { wcnt++; var vw = new MeshData.VertexWeight(); vw.weight = bw.weight1; vw.parentIndex = bw.boneIndex1; vw.localPos = bindPoses[bw.boneIndex1].MultiplyPoint(vertices[j]); vw.localNor = bindPoses[bw.boneIndex1].MultiplyVector(normals[j]).normalized; vw.localTan = bindPoses[bw.boneIndex1].MultiplyVector(tangents[j]).normalized; wlist.Add(vw); } if (bw.weight2 > 0.0f) { wcnt++; var vw = new MeshData.VertexWeight(); vw.weight = bw.weight2; vw.parentIndex = bw.boneIndex2; vw.localPos = bindPoses[bw.boneIndex2].MultiplyPoint(vertices[j]); vw.localNor = bindPoses[bw.boneIndex2].MultiplyVector(normals[j]).normalized; vw.localTan = bindPoses[bw.boneIndex2].MultiplyVector(tangents[j]).normalized; wlist.Add(vw); } if (bw.weight3 > 0.0f) { wcnt++; var vw = new MeshData.VertexWeight(); vw.weight = bw.weight3; vw.parentIndex = bw.boneIndex3; vw.localPos = bindPoses[bw.boneIndex3].MultiplyPoint(vertices[j]); vw.localNor = bindPoses[bw.boneIndex3].MultiplyVector(normals[j]).normalized; vw.localTan = bindPoses[bw.boneIndex3].MultiplyVector(tangents[j]).normalized; wlist.Add(vw); } // 頂点のウエイト情報 uint pack = DataUtility.Pack4_28(wcnt, wstart); vlist.Add(pack); } }
// 仮想メッシュ頂点ごと public void Execute(int vindex) { // 計算フラグクリア virtualVertexFlagList[vindex] = 0; //uint info = virtualVertexInfoList[vindex]; // 使用頂点のみ //if ((info & 0xffff) == 0) if (virtualVertexUseList[vindex] == 0) { return; } // このメッシュの使用をチェック //int mindex = DataUtility.Unpack16Hi(info); int mindex = virtualVertexMeshIndexList[vindex]; var m_minfo = virtualMeshInfoList[mindex - 1]; // (-1)するので注意! if (m_minfo.IsUse() == false) { return; } var s_minfo = sharedVirtualMeshInfoList[m_minfo.sharedVirtualMeshIndex]; int i = vindex - m_minfo.vertexChunk.startIndex; int s_vindex = s_minfo.vertexChunk.startIndex + i; int s_wstart = s_minfo.weightChunk.startIndex; int m_bstart = m_minfo.boneChunk.startIndex; // スキニング処理(仮想メッシュはスキニングのみ) float3 spos = 0; float3 snor = 0; float3 stan = 0; uint pack = sharedVirtualVertexInfoList[s_vindex]; int wcnt = DataUtility.Unpack4_28Hi(pack); int wstart = DataUtility.Unpack4_28Low(pack); for (int j = 0; j < wcnt; j++) { var vw = sharedVirtualWeightList[s_wstart + wstart + j]; // ボーン int tindex = virtualTransformIndexList[m_bstart + vw.parentIndex]; var tpos = transformPosList[tindex]; var trot = transformRotList[tindex]; var tscl = transformSclList[tindex]; // ウエイト0はありえない spos += (tpos + math.mul(trot, vw.localPos * tscl)) * vw.weight; // 法線/接線 if (tscl.x < 0 || tscl.y < 0 || tscl.z < 0) { // マイナススケール対応 // 法線/接線は一旦クォータニオンに変換してフリップスケールを乗算して計算する var q = quaternion.LookRotation(vw.localNor, vw.localTan); q = new quaternion(q.value * new float4(-math.sign(tscl), 1)); snor += math.mul(trot, math.mul(q, new float3(0, 0, 1))) * vw.weight; stan += math.mul(trot, math.mul(q, new float3(0, 1, 0))) * vw.weight; } else { snor += math.mul(trot, vw.localNor) * vw.weight; stan += math.mul(trot, vw.localTan) * vw.weight; } } virtualPosList[vindex] = spos; virtualRotList[vindex] = quaternion.LookRotation(snor, stan); }
/// <summary> /// メッシュ頂点の選択データを設定する /// </summary> /// <param name="meshData"></param> /// <param name="selects"></param> public void SetSelectionData(MeshData meshData, List <int> selects, List <MeshData> childMeshDataList) { // 選択データ初期化 selectionList.Clear(); if (meshData != null && meshData.ChildCount > 0) { for (int i = 0; i < meshData.ChildCount; i++) { var dsel = new DeformerSelection(); int cvcnt = meshData.childDataList[i].VertexCount; for (int j = 0; j < cvcnt; j++) { dsel.selectData.Add(Invalid); dsel.vertexHashList.Add(0); // ハッシュ0=無効 } selectionList.Add(dsel); } } else { // そのまま var dsel = new DeformerSelection(); int cvcnt = selects.Count; for (int j = 0; j < cvcnt; j++) { dsel.selectData.Add(Invalid); dsel.vertexHashList.Add(0); // ハッシュ0=無効 } selectionList.Add(dsel); } // 選択データに追加 for (int i = 0; i < selects.Count; i++) { int data = selects[i]; if (meshData != null && meshData.ChildCount > 0) { // 親頂点に影響する子頂点情報 Dictionary <int, List <uint> > dict = meshData.GetVirtualToChildVertexDict(); // 親頂点に影響する子頂点に記録 if (dict.ContainsKey(i)) { foreach (var pack in dict[i]) { int cmindex = DataUtility.Unpack16Hi(pack); int cvindex = DataUtility.Unpack16Low(pack); selectionList[cmindex].selectData[cvindex] = data; // 頂点ハッシュも記録 if (cmindex < childMeshDataList.Count) { var cmdata = childMeshDataList[cmindex]; if (cmdata != null && cvindex < cmdata.VertexHashCount) { selectionList[cmindex].vertexHashList[cvindex] = cmdata.vertexHashList[cvindex]; } } } } } else { // そのまま selectionList[0].selectData[i] = data; } } // データハッシュ設定 CreateVerifyData(); }
//========================================================================================= /// <summary> /// 事前データ作成 /// </summary> /// <param name="scr"></param> private void CreateData(MagicaVirtualDeformer scr) { Debug.Log("Started creating. [" + scr.name + "]"); // 子メッシュの検証 if (VerifyChildData(scr.Deformer) == false) { // error Debug.LogError("Setup failed. Invalid RenderDeformer data."); return; } serializedObject.FindProperty("deformer.targetObject").objectReferenceValue = scr.gameObject; // 新規メッシュデータ var meshData = ShareDataObject.CreateShareData <MeshData>("VirtualMeshData_" + scr.name); // 設計時スケール meshData.baseScale = scr.transform.lossyScale; // 仮想メッシュ作成 var reductionMesh = new MagicaReductionMesh.ReductionMesh(); //reductionMesh.WeightMode = MagicaReductionMesh.ReductionMesh.ReductionWeightMode.Average; // 平均法(v1.5.2) reductionMesh.WeightMode = MagicaReductionMesh.ReductionMesh.ReductionWeightMode.DistanceAverage; // 距離比重改良(v1.8.6) reductionMesh.MeshData.MaxWeightCount = scr.Deformer.MaxWeightCount; reductionMesh.MeshData.WeightPow = scr.Deformer.WeightPow; reductionMesh.MeshData.SameSurfaceAngle = scr.Deformer.SameSurfaceAngle; for (int i = 0; i < scr.Deformer.RenderDeformerCount; i++) { var deformer = scr.Deformer.GetRenderDeformer(i).Deformer; if (deformer != null) { var sren = deformer.TargetObject.GetComponent <SkinnedMeshRenderer>(); List <Transform> boneList = new List <Transform>(); if (sren) { boneList = new List <Transform>(sren.bones); } else { boneList.Add(deformer.TargetObject.transform); } reductionMesh.AddMesh( deformer.MeshData.isSkinning, deformer.SharedMesh, boneList, deformer.SharedMesh.bindposes, deformer.SharedMesh.boneWeights ); } } //reductionMesh.DebugData.DispMeshInfo("リダクション前"); // リダクション reductionMesh.Reduction( scr.Deformer.MergeVertexDistance > 0.0f ? 0.0001f : 0.0f, scr.Deformer.MergeVertexDistance, scr.Deformer.MergeTriangleDistance, false ); // (1)ゼロ距離リダクション //if (scr.Deformer.MergeVertexDistance > 0.0f) // reductionMesh.ReductionZeroDistance(); //// (2)頂点距離マージ //if (scr.Deformer.MergeVertexDistance > 0.0001f) // reductionMesh.ReductionRadius(scr.Deformer.MergeVertexDistance); //// (3)トライアングル接続マージ //if (scr.Deformer.MergeTriangleDistance > 0.0f) // reductionMesh.ReductionPolygonLink(scr.Deformer.MergeTriangleDistance); //// (4)未使用ボーンの削除 //reductionMesh.ReductionBone(); // (5)頂点の最大接続トライアングル数制限 //reductionMesh.ReductionTriangleConnect(6); //reductionMesh.DebugData.DispMeshInfo("リダクション後"); // 最終メッシュデータ取得 var final = reductionMesh.GetFinalData(scr.gameObject.transform); // メッシュデータシリアライズ meshData.isSkinning = final.IsSkinning; meshData.vertexCount = final.VertexCount; List <uint> vlist; List <MeshData.VertexWeight> wlist; CreateVertexWeightList( final.VertexCount, final.vertices, final.normals, final.tangents, final.boneWeights, final.bindPoses, out vlist, out wlist ); meshData.vertexInfoList = vlist.ToArray(); meshData.vertexWeightList = wlist.ToArray(); meshData.boneCount = final.BoneCount; meshData.uvList = final.uvs.ToArray(); meshData.lineCount = final.LineCount; meshData.lineList = final.lines.ToArray(); meshData.triangleCount = final.TriangleCount; meshData.triangleList = final.triangles.ToArray(); List <uint> vertexToTriangleInfoList = new List <uint>(); for (int i = 0; i < final.VertexCount; i++) { int tcnt = final.vertexToTriangleCountList[i]; int tstart = final.vertexToTriangleStartList[i]; vertexToTriangleInfoList.Add(DataUtility.Pack8_24(tcnt, tstart)); } meshData.vertexToTriangleInfoList = vertexToTriangleInfoList.ToArray(); meshData.vertexToTriangleIndexList = final.vertexToTriangleIndexList.ToArray(); // 子メッシュ情報 for (int i = 0; i < final.MeshCount; i++) { var minfo = final.meshList[i]; var rdeformer = scr.Deformer.GetRenderDeformer(i).Deformer; var mdata = new MeshData.ChildData(); mdata.childDataHash = rdeformer.GetDataHash(); mdata.vertexCount = minfo.VertexCount; // 頂点ウエイト情報作成 CreateVertexWeightList( minfo.VertexCount, minfo.vertices, minfo.normals, minfo.tangents, minfo.boneWeights, final.vertexBindPoses, out vlist, out wlist ); mdata.vertexInfoList = vlist.ToArray(); mdata.vertexWeightList = wlist.ToArray(); mdata.parentIndexList = minfo.parents.ToArray(); meshData.childDataList.Add(mdata); } // レイヤー情報 //for (int i = 0; i < final.LayerCount; i++) //{ // var linfo = new MeshData.LayerInfo(); // linfo.triangleList = new List<int>(final.layerList[i].triangleList); // meshData.layerInfoList.Add(linfo); //} // 検証 meshData.CreateVerifyData(); serializedObject.FindProperty("deformer.meshData").objectReferenceValue = meshData; // ボーン var property = serializedObject.FindProperty("deformer.boneList"); property.arraySize = final.bones.Count; for (int i = 0; i < final.bones.Count; i++) { property.GetArrayElementAtIndex(i).objectReferenceValue = final.bones[i]; } serializedObject.ApplyModifiedProperties(); // デフォーマーデータの検証とハッシュ scr.Deformer.CreateVerifyData(); serializedObject.ApplyModifiedProperties(); // コアコンポーネントの検証とハッシュ scr.CreateVerifyData(); serializedObject.ApplyModifiedProperties(); EditorUtility.SetDirty(meshData); Debug.Log("Setup completed. [" + scr.name + "]"); }
private static void CollectionVertex( ref PhysicsManagerMeshData.RenderMeshInfo r_minfo, ref NativeArray <uint> sharedChildVertexInfoList, ref NativeArray <MeshData.VertexWeight> sharedChildVertexWeightList, ref NativeArray <float3> virtualPosList, ref NativeArray <quaternion> virtualRotList, ref float3 tpos, ref quaternion trot, ref float3 tscl, ref quaternion itrot, float scaleRatio, ref float3 scaleDirection, bool calcNormal, bool calcTangent, int vindex, int i, uint flag, ref NativeArray <float3> renderPosList, ref NativeArray <float3> renderNormalList, ref NativeArray <float4> renderTangentList ) { // レンダーメッシュは複数の仮想メッシュに接続される場合がある int4 data; float3 sum_pos = 0; float3 sum_nor = 0; float3 sum_tan = 0; float4 sum_tan4 = 0; sum_tan4.w = -1; int cnt = 0; uint bit = PhysicsManagerMeshData.RenderVertexFlag_Use; for (int l = 0; l < PhysicsManagerMeshData.MaxRenderMeshLinkCount; l++) { if (r_minfo.IsLinkMesh(l)) { // data.x = 子共有メッシュの頂点スタートインデックス // data.y = 子共有メッシュのウエイトスタートインデック // data.z = 仮想メッシュの頂点スタートインデックス // data.w = 仮想共有メッシュの頂点スタートインデックス data.x = r_minfo.childMeshVertexStartIndex[l]; data.y = r_minfo.childMeshWeightStartIndex[l]; data.z = r_minfo.virtualMeshVertexStartIndex[l]; data.w = r_minfo.sharedVirtualMeshVertexStartIndex[l]; if ((flag & bit) == 0) { bit = bit << 1; continue; } float3 pos = 0; float3 nor = 0; float3 tan = 0; int sc_vindex = data.x + i; int sc_wstart = data.y; int m_vstart = data.z; // スキニング uint pack = sharedChildVertexInfoList[sc_vindex]; int wcnt = DataUtility.Unpack4_28Hi(pack); int wstart = DataUtility.Unpack4_28Low(pack); if (calcTangent) { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position //pos += (mpos + math.mul(mrot, vw.localPos * renderScale)) * vw.weight; pos += (mpos + math.mul(mrot, vw.localPos * scaleDirection * scaleRatio)) * vw.weight; // normal //nor += math.mul(mrot, vw.localNor) * vw.weight; nor += math.mul(mrot, vw.localNor * scaleDirection) * vw.weight; // tangent //tan += math.mul(mrot, vw.localTan) * vw.weight; tan += math.mul(mrot, vw.localTan * scaleDirection) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; nor = math.mul(itrot, nor); tan = math.mul(itrot, tan); // マイナススケール対応 nor *= scaleDirection; tan *= scaleDirection; sum_pos += pos; sum_nor += nor; sum_tan += tan; } else if (calcNormal) { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position //pos += (mpos + math.mul(mrot, vw.localPos * renderScale)) * vw.weight; pos += (mpos + math.mul(mrot, vw.localPos * scaleDirection * scaleRatio)) * vw.weight; // normal //nor += math.mul(mrot, vw.localNor) * vw.weight; nor += math.mul(mrot, vw.localNor * scaleDirection) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; nor = math.mul(itrot, nor); // マイナススケール対応 nor *= scaleDirection; sum_pos += pos; sum_nor += nor; } else { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position //pos += (mpos + math.mul(mrot, vw.localPos * renderScale)) * vw.weight; pos += (mpos + math.mul(mrot, vw.localPos * scaleDirection * scaleRatio)) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; sum_pos += pos; } cnt++; } bit = bit << 1; } if (cnt > 0) { renderPosList[vindex] = sum_pos / cnt; if (calcTangent) { //renderPosList[vindex] = sum_pos / cnt; renderNormalList[vindex] = sum_nor / cnt; sum_tan4.xyz = sum_tan / cnt; renderTangentList[vindex] = sum_tan4; } else if (calcNormal) { //renderPosList[vindex] = sum_pos / cnt; renderNormalList[vindex] = sum_nor / cnt; } } }
// レンダーメッシュごと public void Execute(int rmindex) { var r_minfo = renderMeshInfoList[rmindex]; if (r_minfo.InUse() == false) { return; } // 更新の必要があるメッシュのみ実行する if (r_minfo.IsFlag(updateFlag) == false) { return; } var sr_minfo = sharedRenderMeshInfoList[r_minfo.renderSharedMeshIndex]; for (int i = 0; i < r_minfo.vertexChunk.dataLength; i++) { int index = r_minfo.vertexChunk.startIndex + i; uint flag = renderVertexFlagList[index]; // 頂点使用フラグをリセット flag &= 0xffff; int4 data; uint bit = PhysicsManagerMeshData.RenderVertexFlag_Use; for (int l = 0; l < PhysicsManagerMeshData.MaxRenderMeshLinkCount; l++) { if (r_minfo.IsLinkMesh(l)) { // data.x = 子共有メッシュの頂点スタートインデックス // data.y = 子共有メッシュのウエイトスタートインデック // data.z = 仮想メッシュの頂点スタートインデックス // data.w = 仮想共有メッシュの頂点スタートインデックス data.x = r_minfo.childMeshVertexStartIndex[l]; data.y = r_minfo.childMeshWeightStartIndex[l]; data.z = r_minfo.virtualMeshVertexStartIndex[l]; data.w = r_minfo.sharedVirtualMeshVertexStartIndex[l]; int sc_wstart = data.y; int m_vstart = data.z; int sc_vindex = data.x + i; // ウエイト参照するすべての仮想頂点が利用頂点ならばこのレンダーメッシュ頂点を利用する //int usecnt = 0; //uint pack = sharedChildVertexInfoList[sc_vindex]; //int wcnt = DataUtility.Unpack4_28Hi(pack); //int wstart = DataUtility.Unpack4_28Low(pack); //for (int j = 0; j < wcnt; j++) //{ // // ウエイト0はありえない // var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // //if ((virtualVertexInfoList[m_vstart + vw.parentIndex] & 0xffff) > 0) // // usecnt++; // if (virtualVertexUseList[m_vstart + vw.parentIndex] > 0) // usecnt++; //} //if (wcnt > 0 && wcnt == usecnt) //{ // // 利用する // flag |= bit; //} // ウエイト参照するすべての仮想頂点が利用頂点ならばこのレンダーメッシュ頂点を利用する uint pack = sharedChildVertexInfoList[sc_vindex]; int wcnt = DataUtility.Unpack4_28Hi(pack); int wstart = DataUtility.Unpack4_28Low(pack); int fixcnt = 0; int maxfix = wcnt * 75 / 100; // 許容する固定頂点数(75%まで) int j = 0; for (; j < wcnt; j++) { // ウエイト0はありえない var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; int vindex = m_vstart + vw.parentIndex; // 仮想頂点が1つでも未使用ならば、この頂点は利用しない if (virtualVertexUseList[vindex] == 0) { break; } // 仮想頂点の固定数をカウント if (virtualVertexFixList[vindex] > 0) { fixcnt++; if (fixcnt > maxfix) { break; // 固定頂点数がしきい値を越えたので、この頂点は使用しない } } } if (wcnt == j) { // 利用する flag |= bit; } } bit = bit << 1; } // 頂点フラグを再設定 renderVertexFlagList[index] = flag; // 頂点セット int si = r_minfo.sharedRenderMeshVertexStartIndex + i; if ((flag & 0xffff0000) == 0) { // 未使用頂点 renderPosList[index] = sharedRenderVertices[si]; renderNormalList[index] = sharedRenderNormals[si]; renderTangentList[index] = sharedRenderTangents[si]; } // ボーンウエイト if (sr_minfo.IsSkinning()) { #if UNITY_2018 int bwindex = r_minfo.boneWeightsChunk.startIndex + i; if ((flag & 0xffff0000) == 0) { // 未使用頂点 int bwsi = sr_minfo.boneWeightsChunk.startIndex + i; renderBoneWeightList[bwindex] = sharedBoneWeightList[bwsi]; } else { // 使用頂点 int renderBoneIndex = sr_minfo.rendererBoneIndex; BoneWeight bw = new BoneWeight(); bw.boneIndex0 = renderBoneIndex; bw.weight0 = 1; renderBoneWeightList[bwindex] = bw; } #else int svindex = sr_minfo.bonePerVertexChunk.startIndex + i; int wstart = sharedBonesPerVertexStartList[svindex]; int windex = r_minfo.boneWeightsChunk.startIndex + wstart; int swindex = sr_minfo.boneWeightsChunk.startIndex + wstart; int renderBoneIndex = sr_minfo.rendererBoneIndex; int cnt = sharedBonesPerVertexList[svindex]; if ((flag & 0xffff0000) == 0) { // 未使用頂点 for (int j = 0; j < cnt; j++) { renderBoneWeightList[windex + j] = sharedBoneWeightList[swindex + j]; } } else { // 使用頂点 for (int j = 0; j < cnt; j++) { BoneWeight1 bw = sharedBoneWeightList[swindex + j]; bw.boneIndex = renderBoneIndex; renderBoneWeightList[windex + j] = bw; } } #endif } } // 情報書き戻し r_minfo.SetFlag(updateFlag, false); renderMeshInfoList[rmindex] = r_minfo; }
public void AddLockPair(int id1, int id2) { uint pair = DataUtility.PackPair(id1, id2); lockPairSet.Add(pair); }
/// <summary> /// クロスメッシュ用に頂点セレクションデータを拡張する /// </summary> /// <param name="originalSelection"></param> /// <param name="extendNext">無効頂点の隣接が移動/固定頂点なら拡張に変更する</param> /// <param name="extendWeight">移動/固定頂点に影響する子頂点に接続する無効頂点は拡張に変更する</param> /// <returns></returns> public List <int> ExtendSelection(List <int> originalSelection, bool extendNext, bool extendWeight) { var selection = new List <int>(originalSelection); // (1)無効頂点の隣接が移動/固定頂点なら拡張に変更する if (extendNext) { // ライン/トライアングル情報を分解して各頂点ごとの接続頂点をリスト化 List <HashSet <int> > vlink = MeshUtility.GetTriangleToVertexLinkList(vertexCount, new List <int>(lineList), new List <int>(triangleList)); // 無効頂点の隣接が移動/固定頂点なら拡張に変更する List <int> changeIndexList = new List <int>(); for (int i = 0; i < vertexCount; i++) { if (selection[i] == SelectionData.Invalid) { // 隣接を調べる var vset = vlink[i]; foreach (var vindex in vset) { if (selection[vindex] == SelectionData.Move || selection[vindex] == SelectionData.Fixed) { // 拡張に変更する selection[i] = SelectionData.Extend; } } } } } // (2)移動/固定頂点に影響する子頂点に接続する無効頂点は拡張に変更する if (extendWeight) { var extendSet = new HashSet <int>(); foreach (var cdata in childDataList) { for (int i = 0; i < cdata.VertexCount; i++) { // 頂点のウエイト数とウエイト開始インデックス uint pack = cdata.vertexInfoList[i]; int wcnt = DataUtility.Unpack4_28Hi(pack); int wstart = DataUtility.Unpack4_28Low(pack); bool link = false; for (int j = 0; j < wcnt; j++) { int sindex = wstart + j; var vw = cdata.vertexWeightList[sindex]; // この子頂点が移動/固定頂点に接続しているか判定する if (vw.weight > 0.0f && (selection[vw.parentIndex] == SelectionData.Move || selection[vw.parentIndex] == SelectionData.Fixed)) { link = true; } } if (link) { for (int j = 0; j < wcnt; j++) { int sindex = wstart + j; var vw = cdata.vertexWeightList[sindex]; // この子頂点が接続する頂点がInvalidの場合はExtendに変更する if (vw.weight > 0.0f && selection[vw.parentIndex] == SelectionData.Invalid) { extendSet.Add(vw.parentIndex); } } } } } foreach (var vindex in extendSet) { selection[vindex] = SelectionData.Extend; } } return(selection); }
// レンダーメッシュごと public void Execute(int rmindex) { var r_minfo = renderMeshInfoList[rmindex]; if (r_minfo.InUse() == false) { return; } // レンダラーのローカル座標系に変換する int tindex = r_minfo.transformIndex; var tpos = transformPosList[tindex]; var trot = transformRotList[tindex]; var tscl = transformSclList[tindex]; quaternion itrot = math.inverse(trot); int vcnt = r_minfo.vertexChunk.dataLength; int r_vstart = r_minfo.vertexChunk.startIndex; bool calcNormal = r_minfo.IsFlag(PhysicsManagerMeshData.Meshflag_CalcNormal); bool calcTangent = r_minfo.IsFlag(PhysicsManagerMeshData.Meshflag_CalcTangent); // 頂点ごと for (int i = 0; i < r_minfo.vertexChunk.dataLength; i++) { int vindex = r_minfo.vertexChunk.startIndex + i; uint flag = renderVertexFlagList[vindex]; // 使用頂点のみ if ((flag & 0xffff0000) == 0) { continue; } // レンダーメッシュは複数の仮想メッシュに接続される場合がある int4 data; float3 sum_pos = 0; float3 sum_nor = 0; float3 sum_tan = 0; float4 sum_tan4 = 0; sum_tan4.w = -1; int cnt = 0; uint bit = PhysicsManagerMeshData.RenderVertexFlag_Use; for (int l = 0; l < PhysicsManagerMeshData.MaxRenderMeshLinkCount; l++) { if (r_minfo.IsLinkMesh(l)) { // data.x = 子共有メッシュの頂点スタートインデックス // data.y = 子共有メッシュのウエイトスタートインデック // data.z = 仮想メッシュの頂点スタートインデックス // data.w = 仮想共有メッシュの頂点スタートインデックス data.x = r_minfo.childMeshVertexStartIndex[l]; data.y = r_minfo.childMeshWeightStartIndex[l]; data.z = r_minfo.virtualMeshVertexStartIndex[l]; data.w = r_minfo.sharedVirtualMeshVertexStartIndex[l]; if ((flag & bit) == 0) { bit = bit << 1; continue; } float3 pos = 0; float3 nor = 0; float3 tan = 0; int sc_vindex = data.x + i; int sc_wstart = data.y; int m_vstart = data.z; // スキニング uint pack = sharedChildVertexInfoList[sc_vindex]; int wcnt = DataUtility.Unpack4_28Hi(pack); int wstart = DataUtility.Unpack4_28Low(pack); if (calcTangent) { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position pos += (mpos + math.mul(mrot, vw.localPos)) * vw.weight; // normal nor += math.mul(mrot, vw.localNor) * vw.weight; // tangent tan += math.mul(mrot, vw.localTan) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; nor = math.mul(itrot, nor); tan = math.mul(itrot, tan); sum_pos += pos; sum_nor += nor; sum_tan += tan; } else if (calcNormal) { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position pos += (mpos + math.mul(mrot, vw.localPos)) * vw.weight; // normal nor += math.mul(mrot, vw.localNor) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; nor = math.mul(itrot, nor); sum_pos += pos; sum_nor += nor; } else { for (int j = 0; j < wcnt; j++) { var vw = sharedChildVertexWeightList[sc_wstart + wstart + j]; // ウエイト0はありえない var mpos = virtualPosList[m_vstart + vw.parentIndex]; var mrot = virtualRotList[m_vstart + vw.parentIndex]; // position pos += (mpos + math.mul(mrot, vw.localPos)) * vw.weight; } // レンダラーのローカル座標系に変換する pos = math.mul(itrot, (pos - tpos)) / tscl; sum_pos += pos; } cnt++; } bit = bit << 1; } if (cnt > 0) { if (calcTangent) { renderPosList[vindex] = sum_pos / cnt; renderNormalList[vindex] = sum_nor / cnt; sum_tan4.xyz = sum_tan / cnt; renderTangentList[vindex] = sum_tan4; } else if (calcNormal) { renderPosList[vindex] = sum_pos / cnt; renderNormalList[vindex] = sum_nor / cnt; } else { renderPosList[vindex] = sum_pos / cnt; } } } }