static void _getWallsByMaxArea(List <MeshCollider> getReconColliderList, out List <MeshSizeData> meshSizeDataList, out List <MeshCollider> ignoreList)
        {
            //SRWorkControl.Instance.GetReconstructStaticConvexCollider(out getReconColliderList);
            //SRWorkControl.Instance.GetReconstructStaticQuadCollider();
            ignoreList       = new List <MeshCollider>();
            meshSizeDataList = new List <MeshSizeData>();
            List <MeshCollider> .Enumerator itr = getReconColliderList.GetEnumerator();
            while (itr.MoveNext())
            {
                Vector3[] triNormal;
                //Ignore normal dot with up is near 0 (near 1 is wall, near 0 is ground)
                Vector3 normalLocal    = _getAVGNormalLocal(itr.Current.sharedMesh, itr.Current.transform, out triNormal);
                Vector3 AVGNormalWorld = (normalLocal);

                //float dot = Vector3.Dot(Vector3.up, AVGNormalWorld);
                //if (-0.3f < dot && dot < 0.3f)
                float angle = Vector3.Angle(Vector3.up, AVGNormalWorld);
                //ignore not vertical with floor
                if (90 - 30 > angle || angle > 90 + 30)
                {
                    ignoreList.Add(itr.Current);
                    continue;
                }

                //ignore not face to player
                Vector3 meshCenter   = itr.Current.transform.TransformPoint(_getMeshCenter(itr.Current.sharedMesh));
                Vector3 faceToNormal = GameManager.Instance.GetFaceToPlayerNormal(meshCenter, AVGNormalWorld);
                Vector3 dir2Player   = ARRender.Instance.VRCamera.transform.position - meshCenter;
                angle = Vector3.Angle(dir2Player, faceToNormal);
                if (angle > 70)
                {
                    ignoreList.Add(itr.Current);
                    continue;
                }

#if UNITY_EDITOR
                Debug.DrawLine(meshCenter, meshCenter + AVGNormalWorld * 2, Color.red);
#endif

                MeshSizeData data = new MeshSizeData();
                data.area            = GetMeshArea(itr.Current.sharedMesh);
                data.meshCenterWorld = meshCenter;
                data.colliderMesh    = itr.Current;
                data.avgNormalWorld  = AVGNormalWorld;
                data.triNormal       = triNormal;
                meshSizeDataList.Add(data);
            }
            meshSizeDataList.Sort();
        }
        static void _getPlanesByMaxArea(List <MeshCollider> getReconColliderList, out List <MeshSizeData> meshSizeDataList, out List <MeshCollider> ignoreList)
        {
            ignoreList       = new List <MeshCollider>();
            meshSizeDataList = new List <MeshSizeData>();
            List <MeshCollider> .Enumerator itr = getReconColliderList.GetEnumerator();
            while (itr.MoveNext())
            {
                /*
                 * Vector3[] triNormal;
                 * //Ignore normal dot with up is near 0 (near 1 is wall, near 0 is ground)
                 * Vector3 normalLocal = _getAVGNormalLocal(itr.Current.sharedMesh, itr.Current.transform, out triNormal);
                 * Vector3 AVGNormalWorld = (normalLocal);
                 * //float dot = Vector3.Dot(Vector3.up, AVGNormalWorld);
                 * //if (-0.3f < dot && dot < 0.3f)
                 * float angle = Vector3.Angle(Vector3.up, AVGNormalWorld);
                 * //ignore not correspond with floor
                 * if (-20 > angle || angle > 20)
                 * {
                 *  ignoreList.Add(itr.Current);
                 *  continue;
                 * }
                 */
                ////ignore not face to player
                Vector3 meshCenter = itr.Current.transform.TransformPoint(_getMeshCenter(itr.Current.sharedMesh));
                //Vector3 dir2Player = VRCamera.transform.position - meshCenter;
                //angle = Vector3.Angle(dir2Player, AVGNormalWorld);
                //if (Vector3.Dot(dir2Player, AVGNormalWorld) < 0)
                ////if(angle > 40)
                //{
                //    ignoreList.Add(itr.Current);
                //    continue;
                //}

                MeshSizeData data = new MeshSizeData();
                data.area            = GetMeshArea(itr.Current.sharedMesh);
                data.meshCenterWorld = meshCenter;
                data.colliderMesh    = itr.Current;
                data.avgNormalWorld  = Vector3.zero; //AVGNormalWorld;
                data.triNormal       = null;         //triNormal;
                meshSizeDataList.Add(data);
            }
            meshSizeDataList.Sort();
        }
        public void AutoPickFloor()
        {
            List <MeshSizeData> meshSizeDataList;
            List <MeshCollider> ignoreList;

            _getPlanesByMaxArea(reconstructConvexCollidersHorizontal, out meshSizeDataList, out ignoreList);

            //if (recontructTable != null)
            //    Destroy(recontructTable);
            //recontructTable = new GameObject("RecontructTable");

            if (recontructFloor != null)
            {
                Destroy(recontructFloor);
            }
            recontructFloor = new GameObject("RecontructFloor");

            if (floorPlaneObj != null)
            {
                Destroy(floorPlaneObj);
            }
            if (floorPlaneObjCollider != null)
            {
                Destroy(floorPlaneObjCollider);
            }

            //Get the lowest is the floor and y must -0.5~0.5
            MeshSizeData lowestMesh = null;
            float        lowestD    = 9999f;

            for (int a = 0; a < meshSizeDataList.Count; a++)
            {
                if (a >= 3)
                {
                    break;
                }
                MeshSizeData current = meshSizeDataList[a];

                if (current.meshCenterWorld.y < lowestD)
                {
                    //if (-0.6f < current.meshCenterWorld.y && current.meshCenterWorld.y < 0.6f)
                    {
                        lowestD    = current.meshCenterWorld.y;
                        lowestMesh = current;
                    }
                }
            }
            if (lowestMesh != null)
            {
                GameObject floorConvexObj = SetPivotInMeshCenter(
                    lowestMesh.colliderMesh.transform,
                    lowestMesh.colliderMesh.sharedMesh,
                    recontructFloor.transform,
                    null,
                    lowestMesh.colliderMesh.name + "_convex : " + lowestMesh.area,
                    lowestMesh.avgNormalWorld,
                    lowestMesh.meshCenterWorld);
                meshSizeDataList.Remove(lowestMesh);

                //Add floor quad for shadow rendering
                foreach (MeshCollider mc in reconstructQuadCollidersHorizontal)
                {
                    string namesQuad   = mc.name.Remove(0, mc.name.IndexOf('_') + 1);
                    string namesConvex = lowestMesh.colliderMesh.name.Remove(0, lowestMesh.colliderMesh.name.IndexOf('_') + 1);
                    if (namesQuad == namesConvex)
                    {
                        //Vector3[] planeTriNormal;
                        //Vector3 AVGNormalWorld = -_getAVGNormalLocal(mc.sharedMesh, mc.transform, out planeTriNormal);
                        Vector3 center = mc.transform.TransformPoint(_getMeshCenter(mc.sharedMesh));
                        //GameObject floorPlaneObj = SetPivotInMeshCenter(mc.transform, mc.sharedMesh,
                        //                                              floorConvexObj.transform, floorColliderMaterial,
                        //                                              lowestMesh.colliderMesh.name + "_quadFloor",
                        //                                              AVGNormalWorld, center);
                        floorPlaneObj                      = GameObject.CreatePrimitive(PrimitiveType.Plane);
                        floorPlaneObj.name                 = lowestMesh.colliderMesh.name + "_quadFloor";
                        floorPlaneObj.transform.parent     = floorConvexObj.transform;
                        floorPlaneObj.transform.position   = center;
                        floorPlaneObj.transform.rotation   = Quaternion.identity;
                        floorPlaneObj.transform.localScale = Vector3.one * 2;

                        //SRWork 0.7.5.0 use scan mesh collider
                        floorPlaneObj.isStatic = true;

                        floorPlaneObj.layer = AdvanceRender.ScanLiveMeshLayer;
                        if (ARRender.ADVANCE_RENDER)
                        {
                            //In advance render floorPlaneObj is for render, so, we clone a new one for collision
                            floorPlaneObjCollider       = GameObject.Instantiate(floorPlaneObj);
                            floorPlaneObjCollider.layer = AdvanceRender.MRCollisionFloorLayer;
                            floorPlaneObjCollider.transform.position = floorPlaneObj.transform.position;
                            floorPlaneObjCollider.transform.rotation = floorPlaneObj.transform.rotation;
                            ARRender.Instance.VRCamera.cullingMask   = MyHelpLayer.RemoveMaskLayer(ARRender.Instance.VRCamera.cullingMask, AdvanceRender.MRCollisionFloorLayer);
                        }
                        else
                        {
                            floorPlaneObj.GetComponent <MeshRenderer>().sharedMaterial = new Material(Shader.Find("ViveSR/MeshCuller, Shadowed, Stencil"));
                            //floorPlaneObj.GetComponent<MeshRenderer>().enabled = false;
                        }
                        break;
                    }
                }

                //SRWork0.7.5.0 ConvexColliders default is turn off
                //turn off the original convex mesh's collider
                //foreach (MeshCollider mc in reconstructConvexCollidersHorizontal)
                //{
                //    string namesA = mc.name.Remove(0, mc.name.IndexOf('_') + 1);
                //    string namesB = lowestMesh.colliderMesh.name.Remove(0, lowestMesh.colliderMesh.name.IndexOf('_') + 1);
                //    //namesA = namesA.Remove(0, namesA.IndexOf('_'));//srwork 0.7 without '_' again
                //    //namesB = namesB.Remove(0, namesB.IndexOf('_'));
                //    if (namesA == namesB)
                //    {
                //        mc.transform.gameObject.SetActive(false);
                //    }
                //}
            }
            else
            {
                Debug.LogWarning("[reconstructPickFloor] there are no reconstruct floor picked...");
            }

            /*
             *      //Get the highest is the table
             *      MeshSizeData highestMesh = null;
             *      float highestD = -9999f;
             *      for (int a = 0; a < meshSizeDataList.Count; a++)
             *      {
             *          if (a >= 10)
             *              break;
             *          MeshSizeData current = meshSizeDataList[a];
             *          if (current.meshCenterWorld.y > highestD &&
             *              current.meshCenterWorld.y < VRCamera.transform.position.y//must not higher then player's head
             *              )
             *          {
             *              highestD = current.meshCenterWorld.y;
             *              highestMesh = current;
             *          }
             *      }
             *      if (highestMesh != null)
             *      {
             *          SetPivotInMeshCenter(highestMesh.colliderMesh.transform, highestMesh.colliderMesh.sharedMesh,
             *              recontructTable.transform, tableColliderMaterial,
             *              highestMesh.colliderMesh.name + "_convex : " + highestMesh.area,
             *              highestMesh.avgNormalWorld,
             *              highestMesh.meshCenterWorld);
             *          meshSizeDataList.Remove(highestMesh);
             *      }
             *      else
             *          Debug.LogWarning("[reconstructPickFloor] there are no reconstruct table picked...");
             */
        }