// 仮想メッシュ頂点ごと 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; 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="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); }
/// <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); }
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 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; } } } }