Example #1
0
            // 仮想メッシュ頂点ごと
            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);
            }
Example #2
0
        /// <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);
        }
Example #3
0
        /// <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;
            }
Example #6
0
            // レンダーメッシュごと
            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;
                        }
                    }
                }
            }