private void UpdatePart(GameObject o, DrawSurfaceTask t)
    {
        o.GetComponent <MeshFilter>().mesh = (t.mesh as VtsMesh).Get();
        if (shiftingOriginMap)
        {
            VtsUtil.GetOrAddComponent <VtsObjectShiftingOrigin>(o).map = shiftingOriginMap;
        }
        Material mat = o.GetComponent <MeshRenderer>().material;

        UpdateMaterial(mat);
        bool monochromatic = false;

        if (t.texColor != null)
        {
            var tt = t.texColor as VtsTexture;
            mat.SetTexture(shaderPropertyMainTex, tt.Get());
            monochromatic = tt.monochromatic;
        }
        if (t.texMask != null)
        {
            var tt = t.texMask as VtsTexture;
            mat.SetTexture(shaderPropertyMaskTex, tt.Get());
        }
        mat.SetMatrix(shaderPropertyUvMat, VtsUtil.V2U33(t.data.uvm));
        mat.SetVector(shaderPropertyUvClip, VtsUtil.V2U4(t.data.uvClip));
        mat.SetVector(shaderPropertyColor, VtsUtil.V2U4(t.data.color));
        // flags: mask, monochromatic, flat shading, uv source
        mat.SetVector(shaderPropertyFlags, new Vector4(t.texMask == null ? 0 : 1, monochromatic ? 1 : 0, 0, t.data.externalUv ? 1 : 0));
        VtsUtil.Matrix2Transform(o.transform, VtsUtil.V2U44(Math.Mul44x44(conv, System.Array.ConvertAll(t.data.mv, System.Convert.ToDouble))));
    }
    private void UpdateParts()
    {
        if (originHasShifted)
        {
            originHasShifted = false;
            foreach (var p in partsCache)
            {
                Destroy(p.Value);
            }
            partsCache.Clear();
        }

        VtsMapShiftingOrigin shiftingOriginMap = mapObject.GetComponent <VtsMapShiftingOrigin>();

        double[] conv = Math.Mul44x44(Math.Mul44x44(VtsUtil.U2V44(mapTrans.localToWorldMatrix), VtsUtil.U2V44(VtsUtil.SwapYZ)), Math.Inverse44(draws.camera.view));

        Dictionary <VtsMesh, DrawSimpleTask> tasksByMesh = new Dictionary <VtsMesh, DrawSimpleTask>();

        foreach (DrawSimpleTask t in draws.colliders)
        {
            VtsMesh k = t.mesh as VtsMesh;
            if (!tasksByMesh.ContainsKey(k))
            {
                tasksByMesh.Add(k, t);
            }
        }

        HashSet <VtsMesh> partsToRemove = new HashSet <VtsMesh>(partsCache.Keys);

        foreach (KeyValuePair <VtsMesh, DrawSimpleTask> tbm in tasksByMesh)
        {
            if (!partsCache.ContainsKey(tbm.Key))
            {
                GameObject o = Instantiate(colliderPrefab, partsGroup);
                partsCache.Add(tbm.Key, o);
                UnityEngine.Mesh msh = (tbm.Value.mesh as VtsMesh).Get();
                o.GetComponent <MeshCollider>().sharedMesh = msh;
                if (shiftingOriginMap)
                {
                    VtsUtil.GetOrAddComponent <VtsObjectShiftingOrigin>(o).map = shiftingOriginMap;
                }
                VtsUtil.Matrix2Transform(o.transform, VtsUtil.V2U44(Math.Mul44x44(conv, System.Array.ConvertAll(tbm.Value.data.mv, System.Convert.ToDouble))));
            }
            partsToRemove.Remove(tbm.Key);
        }

        foreach (VtsMesh m in partsToRemove)
        {
            Destroy(partsCache[m]);
            partsCache.Remove(m);
        }
    }