Exemplo n.º 1
0
        public void EnterFoldingMode(Vertex pickedVertex, Face nearestFace)
        {
            this.cloverController = CloverController.GetInstance();

            // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为baseFace
            this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace);
            if (this.group == null)
            {
                System.Windows.MessageBox.Show("找不到Groups");
                return;
            }
            this.pickedVertex = pickedVertex;
            this.baseFace = nearestFace;
            foreach (Face face in group.GetFaceList())
            {
                if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < baseFace.Layer)
                    baseFace = face;
            }

            // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组
            foreach (Face face in group.GetFaceList())
            {
                if (face.Layer >= baseFace.Layer)
                    this.facesAboveBase.Add(face);
                else
                    this.facesBelowBase.Add(face);
            }

            // 保存pickedVertex的原始位置
            originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z);
        }
Exemplo n.º 2
0
        public List<Face> EnterTuckingMode(Vertex pickedVertex, Face nearestFace)
        {
            this.cloverController = CloverController.GetInstance();
            //cloverController.ShadowSystem.CheckUndoTree();

            // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为floorFace,最上面的那个面作为ceilingFace
            this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace);
            this.pickedVertex = pickedVertex;
            this.floorFace = this.ceilingFace = nearestFace;

            // 是正向还是反向
            Vector3D currNormal = group.Normal * cloverController.RenderController.Entity.Transform.Value;
            Double judge = Vector3D.DotProduct(currNormal, new Vector3D(0, 0, 1));
            isPositive = judge < 0 ? false : true;

            if (isPositive)
            {
                foreach (Face face in group.GetFaceList())
                {
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < floorFace.Layer)
                        floorFace = face;
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > ceilingFace.Layer)
                        ceilingFace = face;
                }
                // 将同Group的面分为在floor和ceiling之间和在floor和ceiling之外两组
                foreach (Face face in group.GetFaceList())
                {
                    if (face.Layer >= floorFace.Layer && face.Layer <= ceilingFace.Layer)
                        this.facesInHouse.Add(face);
                    else
                        this.facesNotInHouse.Add(face);
                }
            }
            else
            {
                foreach (Face face in group.GetFaceList())
                {
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > floorFace.Layer)
                        floorFace = face;
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < ceilingFace.Layer)
                        ceilingFace = face;
                }
                // 将同Group的面分为在floor和ceiling之间和在floor和ceiling之外两组
                foreach (Face face in group.GetFaceList())
                {
                    if (face.Layer <= floorFace.Layer && face.Layer >= ceilingFace.Layer)
                        this.facesInHouse.Add(face);
                    else
                        this.facesNotInHouse.Add(face);
                }
            }

            // 保存pickedVertex的原始位置
            originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z);

            return facesInHouse;
        }
Exemplo n.º 3
0
        public List<Face> EnterFoldingMode(Vertex pickedVertex, Face nearestFace)
        {
            this.cloverController = CloverController.GetInstance();
            //cloverController.ShadowSystem.CheckUndoTree();

            // 寻找同group面中拥有pickedVertex的面中最下面的那个面作为baseFace
            this.group = cloverController.FaceGroupLookupTable.GetGroup(nearestFace);
            this.pickedVertex = pickedVertex;
            this.baseFace = nearestFace;

            // 是正向还是反向
            Vector3D currNormal = group.Normal * cloverController.RenderController.Entity.Transform.Value;
            Double judge = Vector3D.DotProduct(currNormal, new Vector3D(0, 0, 1));
            isPositive = judge < 0 ? false : true;
            if (isPositive)
            {
                foreach (Face face in group.GetFaceList())
                {
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer < baseFace.Layer)
                        baseFace = face;
                }
                // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组
                foreach (Face face in group.GetFaceList())
                {
                    if (face.Layer >= baseFace.Layer)
                        this.facesAboveBase.Add(face);
                    else
                        this.facesBelowBase.Add(face);
                }
            }
            else
            {
                foreach (Face face in group.GetFaceList())
                {
                    if (CloverTreeHelper.IsVertexInFace(pickedVertex, face) && face.Layer > baseFace.Layer)
                        baseFace = face;
                }
                // 将同Group的面分为在base面之上(含baseFace)和base面之下的两组
                foreach (Face face in group.GetFaceList())
                {
                    if (face.Layer <= baseFace.Layer)
                        this.facesAboveBase.Add(face);
                    else
                        this.facesBelowBase.Add(face);
                }
            }

            // 保存pickedVertex的原始位置
            originPoint = new Point3D(pickedVertex.X, pickedVertex.Y, pickedVertex.Z);

            return facesAboveBase;
        }
Exemplo n.º 4
0
        /// <summary>
        /// 退出Blending模式
        /// </summary>
        public void ExitBlendingMode()
        {
            pickedVertex = null;
            nearestFace = null;
            foldLine = null;
            group = null;
            beBlendedFaces = null;
            faceContainVertex = null;
            checkMask = 0;

            // 更新组
            CloverController.GetInstance().FaceGroupLookupTable.UpdateTableAfterBending(11);

            // 反重叠
            RenderController.GetInstance().AntiOverlap();
        }
Exemplo n.º 5
0
 /// <summary>
 /// 判断一个面是否在一个组中
 /// </summary>
 /// <param name="face"></param>
 /// <param name="group"></param>
 /// <returns></returns>
 public static Boolean IsFaceInGroup(Face face, FaceGroup group)
 {
     // 等待杨旭瑜写完group,。。。
     // todo
     return false;
 }
Exemplo n.º 6
0
        /// <summary>
        /// 返回一个组的基面,用以计算其他面的渲染偏差量
        /// </summary>
        /// <param name="group"></param>
        public static Face FindBaseFace(FaceGroup group)
        {
            //todo

            return null;
        }
Exemplo n.º 7
0
 /// <summary>
 /// 寻找所有要折叠(旋转)的面,放在beBlendedFaces中。
 /// </summary>
 void FindBeBlendedFaces()
 {
     // 寻找所有与nearestFace同一group的Face
     group = CloverController.GetInstance().FaceGroupLookupTable.GetGroup(nearestFace);
     checkMask += 4;
     if (group == null)
         System.Windows.MessageBox.Show("这怎么可能?一个face居然不在group中!--Blending");
     // 找到所有拥有pickedVertex的Face
     faceContainVertex = new List<Face>();
     checkMask += 8;
     foreach (Face face in group.GetFaceList())
     {
         if (CloverTreeHelper.IsVertexInFace(pickedVertex, face))
             faceContainVertex.Add(face);
     }
     // 找到所有拥有pickedVertex中layer最“低”的那个面
     // 这里需要加一个正负法线方向的判断 Todo
     Face baseFace = faceContainVertex[0];
     foreach (Face face in faceContainVertex)
     {
         if (face.Layer < baseFace.Layer)
             baseFace = face;
     }
     // group中所有layer高于baseFace的面即为beBlendedFaces
     beBlendedFaces = new List<Face>();
     checkMask += 16;
     foreach (Face face in group.GetFaceList())
     {
         if (face.Layer >= baseFace.Layer)
             beBlendedFaces.Add(face);
     }
 }
Exemplo n.º 8
0
 bool AddGroup( FaceGroup fg )
 {
     foreach ( FaceGroup fgin in faceGroupList )
     {
         // 判断组里面是否已经有了这样的组
         if ( CloverMath.IsTwoVectorTheSameDir( fg.Normal, fgin.Normal ) )
         {
             return false;
         }
     }
     faceGroupList.Add( fg );
     return true;
 }
Exemplo n.º 9
0
 /// <summary>
 /// 往lookuptable中加入face,会自动匹配加入group中或新增group。
 /// 否则强制新建一个group
 /// </summary>
 /// <param name="f"></param>
 void AddFace( Face f )
 {
     foreach ( FaceGroup fg in faceGroupList )
     {
         if ( fg.HasFace( f ) )
         {
             return;
         }
         if ( fg.IsMatch( f ) )
         {
             fg.AddFace( f );
             return;
         }
     }
     FaceGroup newfgt = new FaceGroup( f );
     faceGroupList.Add( newfgt );
 }
Exemplo n.º 10
0
        /// <summary>
        /// 在foldup后更lookuptable
        /// </summary>
        /// <param name="participatedGroup">参与折叠的面</param>
        /// <param name="movedFaceGroup">所有移动的面</param>
        /// <param name="fixedFaceGroup">所有不动的面</param>
        /// <param name="IsFacingUser">是否组的法线面向用户</param>
        /// <returns></returns>
        public bool UpdateTableAfterFoldUp( List<Face> participatedFaces, List<Face> movedFaces, List<Face> fixedFaces, bool IsFacingUser = true )
        {
            if (movedFaces.Count == 0)
                return false;

            RemoveRedundantFaceGroup();
            FaceGroup participatedGroup = GetGroup( participatedFaces[ 0 ] );
            FaceGroup movedFaceGroup = new FaceGroup( movedFaces[ 0 ] );
            FaceGroup fixedFaceGroup = new FaceGroup( fixedFaces[ 0 ] );

            foreach ( Face f in movedFaces )
            {
                if ( !movedFaceGroup.HasFace( f ) )
                {
                    movedFaceGroup.AddFace( f );
                }
            }

            foreach ( Face f in fixedFaces )
            {
                if ( !fixedFaceGroup.HasFace( f ) )
                {
                    fixedFaceGroup.AddFace( f );
                }
            }

            foreach ( Face fp in participatedGroup.GetFaceList() )
            {
                if ( fp.LeftChild == null && fp.RightChild == null )
                {
                    if ( !movedFaceGroup.HasFace( fp ) && !fixedFaceGroup.HasFace( fp ) )
                    {
                        fixedFaceGroup.AddFace( fp );
                    }
                }
            }

            fixedFaceGroup.SortFace();
            fixedFaceGroup.Normal = participatedGroup.Normal;

            return participatedGroup.UpdateGroupAfterFoldUp( participatedGroup, movedFaceGroup, fixedFaceGroup, IsFacingUser );
        }
Exemplo n.º 11
0
        /// <summary>
        /// bend后调用来更新lookuptable
        /// </summary>
        /// <returns></returns>
        public bool UpdateTableAfterBending(double angle, bool IsFacingUser = true)
        {
            BendTpye bendtype;
            if ( Math.Abs( angle ) < 0.00001 ) // 适应误差
            {
                bendtype = BendTpye.BlendZero;
            }
            else if ( Math.Abs( angle ) <= 180 && Math.Abs( angle ) >= 179.999999999999 )// 适应误差
            {
                bendtype = BendTpye.BlendSemiCycle;
            }
            else
            {
                bendtype = BendTpye.BlendNormally;
            }

            if (bendtype == BendTpye.BlendZero)
            {
                return true;
            }

            FaceGroup participateGroup = null;
            // bend半周即180度
            if (bendtype == BendTpye.BlendSemiCycle)
            {
                // 找到相关的组
                foreach (FaceGroup fg in faceGroupList)
                {
                    if ( CloverMath.IsTwoVectorTheSameDir(fg.Normal, bendingParticipateGroup.Normal))
                    {
                        if (participateGroup == null)
                        {
                            participateGroup = fg;
                        }
                        else if ( participateGroup != fg)
                        {
                            return false;// 一次只可能有一个组参与
                        }
                    }
                }

                faceGroupList.Remove( participateGroup );
                bendingParticipateGroup.RevertFaces();

                foreach (Face f in bendingParticipateGroup.GetFaceList())
                {
                    participateGroup.RemoveFace( f );
                }

                participateGroup.SortFace();
                bendingParticipateGroup.SortFace();
                // 判断用户的方向:
                if ( IsFacingUser ) // 组的正面面向用户
                {
                    // 逆序从上贴合
                    int layer = 0;
                    int lastlayer = 0;
                    layer = participateGroup.GetTopLayer() + 1;
                    // 根据是否覆盖来调整layer的值
                    for ( int i = participateGroup.GetFaceList().Count - 1; i >= 0; i-- )
                    {

                        if ( !CloverMath.IsIntersectionOfTwoFaceOnOnePlane( bendingParticipateGroup.GetFaceList()[ bendingParticipateGroup.GetFaceList().Count - 1 ], participateGroup.GetFaceList()[ i ] ) )
                        {
                            layer--;
                        }
                        else if ( i == participateGroup.GetFaceList().Count - 1 )
                        {
                            break;
                        }
                    }

                    lastlayer = bendingParticipateGroup.GetTopLayer();
                    for ( int i = bendingParticipateGroup.GetFaceList().Count - 1; i >= 0; i-- )
                    {
                        if ( bendingParticipateGroup.GetFaceList()[ i ].Layer == lastlayer)
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        else
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            layer++;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        participateGroup.AddFace( bendingParticipateGroup.GetFaceList()[ i ] );
                    }
                }
                else // 组背向用户
                {
                    int layer = 0;
                    int lastlayer = 0;
                    layer = participateGroup.GetBottomLayer() + 1;
                    for ( int i = 0; i < participateGroup.GetFaceList().Count; i++ )
                    {
                        if ( !CloverMath.IsIntersectionOfTwoFaceOnOnePlane( bendingParticipateGroup.GetFaceList()[ 0 ], participateGroup.GetFaceList()[ i ] ) )
                        {
                            layer++;
                        }
                        else if (i == 0)
                        {
                            break;
                        }

                    }

                    lastlayer = bendingParticipateGroup.GetBottomLayer();
                    for ( int i = 0; i < bendingParticipateGroup.GetFaceList().Count; i++ )
                    {
                        if ( bendingParticipateGroup.GetFaceList()[ i ].Layer == lastlayer )
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        else
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            layer--;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        participateGroup.AddFace( bendingParticipateGroup.GetFaceList()[ i ] );
                    }
                }

                faceGroupList.Add( participateGroup );
            }

            // 非180度的折叠
            if (bendtype == BendTpye.BlendNormally)
            {
                if ( !IsBasicBendedFaceTheSameNormalWithItsGroup ) // 新组与原来的组排序方向不同,里面的面的顺序必须倒置
                {
                    bendingParticipateGroup.RevertFaces();
                }

                // 更新参与bend的新组的法线
                bendingParticipateGroup.Normal = bendingParticipateGroup.GetFaceList()[0].Normal;

                // 寻找是否会和某个组重合
                foreach (FaceGroup fg in faceGroupList)
                {
                    if ( CloverMath.IsTwoVectorTheSameDir( fg.Normal, bendingParticipateGroup.Normal ))
                    {
                        if ( fg == bendingParticipateGroup)
                        {
                            continue;
                        }

                        if ( participateGroup == null )
                        {
                            participateGroup = fg;
                        }
                        else if ( participateGroup != fg )
                        {
                            return false;
                        }
                    }
                }

                if (participateGroup == null)
                {
                    FaceGroup newgroup = (FaceGroup)bendingParticipateGroup.Clone();
                    AddGroup( newgroup );
                    bendtype = BendTpye.BlendZero;
                    bendingParticipateGroup = null;
                    return true; // 很幸运,没有什么组跟你重合
                }

                // 有和某个组巧妙地重合:

                // 判断自己组的排序方向和对方是不是一样的
                if ( !CloverMath.IsTwoVectorTheSameDir( participateGroup.Normal, bendingParticipateGroup.Normal, true ) )
                {
                    bendingParticipateGroup.RevertFaces();
                }

                if ( IsFacingUser )// 用户面向对方的组
                {
                    // 从上贴合
                    int layer = 0;
                    int lastlayer = 0;
                    // 根据是否覆盖来调整layer的值
                    for ( int i = participateGroup.GetFaceList().Count - 1; i >= 0; i-- )
                    {

                        if ( !CloverMath.IsIntersectionOfTwoFaceOnOnePlane( bendingParticipateGroup.GetFaceList()[ bendingParticipateGroup.GetFaceList().Count - 1 ], participateGroup.GetFaceList()[ i ] ) )
                        {
                            layer--;
                        }
                        else if ( i == participateGroup.GetFaceList().Count - 1 )
                        {
                            break;
                        }
                    }

                    layer = bendingParticipateGroup.GetTopLayer() + 1;
                    lastlayer = bendingParticipateGroup.GetBottomLayer();
                    for ( int i = 0; i < bendingParticipateGroup.Count; i++ )
                    {
                        if ( bendingParticipateGroup.GetFaceList()[ i ].Layer == lastlayer)
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        else
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            layer++;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }

                        participateGroup.AddFace( bendingParticipateGroup.GetFaceList()[ i ] );
                    }
                }
                else
                {
                    // 从下贴合
                    int layer = 0;
                    int lastlayer = 0;
                    layer = participateGroup.GetBottomLayer();
                    layer--;

                    for ( int i = 0; i < participateGroup.GetFaceList().Count; i++ )
                    {
                        if ( !CloverMath.IsIntersectionOfTwoFaceOnOnePlane( bendingParticipateGroup.GetFaceList()[ 0 ], participateGroup.GetFaceList()[ i ] ) )
                        {
                            layer++;
                        }
                        else if (i == 0)
                        {
                            break;
                        }
                    }
                    lastlayer = participateGroup.GetTopLayer();
                    for ( int i = bendingParticipateGroup.GetFaceList().Count - 1; i >= 0; i-- )
                    {
                        if (bendingParticipateGroup.GetFaceList()[ i ].Layer == lastlayer)
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        else
                        {
                            lastlayer = bendingParticipateGroup.GetFaceList()[ i ].Layer;
                            layer--;
                            bendingParticipateGroup.GetFaceList()[ i ].Layer = layer;
                        }
                        participateGroup.AddFace( bendingParticipateGroup.GetFaceList()[ i ] );
                    }

                }
                faceGroupList.Add( participateGroup );
            }
            bendtype = BendTpye.BlendZero;
            bendingParticipateGroup = null;
            return true;
        }
Exemplo n.º 12
0
        /// <summary>
        /// 在bend前调用
        /// </summary>
        /// <param name="faces">要bend的所有面</param>
        /// <param name="angle">bend的角度,角度</param>
        public bool BeforeBending(List<Face> faces)
        {
            if ( faces == null )
            {
                return false;
            }
            if ( faces.Count == 0)
            {
                return false;
            }
            if (bendingParticipateGroup != null)
            {
                return false;
            }

            // 建立bending的临时组
            bendingParticipateGroup = new FaceGroup( faces[ 0 ] );

            for ( int i = 1; i < faces.Count; i++ )
            {
                bendingParticipateGroup.AddFace( faces[ i ] );
            }
            bendingParticipateGroup.SortFace();

            bendingParticipateGroup.Normal = bendingParticipateGroup.GetFaceList()[ 0 ].Normal;

            if ( CloverMath.IsTwoVectorTheSameDir( bendingParticipateGroup.Normal, GetGroup( bendingParticipateGroup.GetFaceList()[ 0 ] ).Normal, true ) )
            {
                IsBasicBendedFaceTheSameNormalWithItsGroup = true;
            }
            for ( int i = 0; i < faces.Count; i++ )
            {
                RemoveFace( faces[ i ] );
            }
            UpdateGroup();
            // 判断折叠样式
            return true;
        }
Exemplo n.º 13
0
 /// <summary>
 /// 构造第一个面的时候初始化。
 /// </summary>
 /// <param name="f"></param>
 public FaceGroupLookupTable( Face f )
 {
     FaceGroup g = new FaceGroup( f );
     faceGroupList.Add( g );
 }
Exemplo n.º 14
0
 /// <summary>
 /// 更新整个组的面
 /// </summary>
 /// <param name="group"></param>
 public void Update(FaceGroup group, Boolean autoUpdate = true)
 {
     foreach (Face face in group.GetFaceList())
     {
         faceMeshMap[face].Geometry = NewMesh(face, autoUpdate);
     }
 }
Exemplo n.º 15
0
        /// <summary>
        /// 使纸张按组的法线方向散开
        /// </summary>
        /// <param name="group"></param>
        public void DisperseLayer(FaceGroup group)
        {
            if (group == null || group.GetFaceList().Count == 0)
                return;
            List<Face> faceList = group.GetFaceList();
            // 重置同组所有面的渲染点坐标
            foreach (Face face in faceList)
            {
                foreach (Vertex v in face.Vertices)
                {
                    v.RenderPoint = new Point3D(v.X, v.Y, v.Z);
                }
            }

            // 从中间向两头逼近的算法

            // 旭瑜你的group里面face的layer不能保证间距均为1
            // 补丁by kid
            int lastLayer = faceList[0].Layer;
            for (int i = 1; i < faceList.Count; i++)
            {
                if (faceList[i].Layer == faceList[i - 1].Layer)
                    continue;
                faceList[i].Layer = ++lastLayer;
            }

            int step = 1;
            int baseval = step;
            Double pivot = (faceList[faceList.Count - 1].Layer - faceList[0].Layer) / 2.0;
            int up = 0, down = 0;
            if (faceList.Count > 1)
                for (int i = 0; i <= faceList.Count; i++)
                    if (faceList[i].Layer < pivot && faceList[i + 1].Layer > pivot)
                    {
                        down = i;
                        up = i + 1;
                        break;
                    }
            while (true)
            {
                Vector3D offsetVec = group.Normal * (baseval);
                while (up < faceList.Count)
                {
                    foreach (Vertex v in faceList[up].Vertices)
                        v.RenderPoint = v.GetPoint3D() + offsetVec;
                    if (up + 1 == faceList.Count || faceList[up].Layer != faceList[up + 1].Layer)
                        break;
                    up++;
                }
                up++;

                while (down > -1)
                {
                    foreach (Vertex v in faceList[down].Vertices)
                        v.RenderPoint = v.GetPoint3D() - offsetVec;
                    if (down - 1 == -1 || faceList[down].Layer != faceList[down - 1].Layer)
                        break;
                    down--;
                }
                down--;

                baseval += step;
                if (up >= faceList.Count && down <= -1)
                    break;
            }

            //// sb算法
            //int step = 6;
            //Vector3D offsetVec = group.Normal * step;
            //foreach (Face f in faceList)
            //{
            //    foreach (Vertex v in f.Vertices)
            //    {
            //        v.RenderPoint += f.Layer * offsetVec;
            //    }
            //}

            //// 以当前总层数作为依据,指定offset值
            //int step = 6;
            ////int step = 1;

            //// 从faceList的两头向中间逼近,逐层计算偏移量
            //Dictionary<Vertex, int> historyOffset = new Dictionary<Vertex, int>();// 这蛋疼的玩意记录了每个点的历史偏移量。一个顶点不可以两次偏向同一方向
            //int bottom = 0;
            //int top = faceList.Count - 1;
            //int offset = (faceList[top].Layer - faceList[bottom].Layer) * step;
            //while (top >= bottom)
            //{
            //    Vector3D offVec = group.Normal * -offset;
            //    while (true)
            //    {
            //        foreach (Vertex v in faceList[bottom].Vertices)
            //        {
            //            v.RenderPoint += offVec;
            //            //if (!historyOffset.ContainsKey(v))
            //            //{
            //            //    v.RenderPoint += offVec;
            //            //    historyOffset[v] = -offset;
            //            //}
            //            //else
            //            //{
            //            //    if (historyOffset[v] == 0)
            //            //    {
            //            //        v.RenderPoint += offVec;
            //            //        historyOffset[v] = -offset;
            //            //    }
            //            //    else if (historyOffset[v] + offset == 0)
            //            //    {
            //            //        v.RenderPoint += offVec;
            //            //        historyOffset[v] = 0;
            //            //    }
            //            //}
            //        }
            //        bottom++;
            //        if (bottom + 1 > top || faceList[bottom].Layer != faceList[bottom + 1].Layer)
            //            break;
            //    }

            //    offVec *= -1;
            //    while (true)
            //    {
            //        foreach (Vertex v in faceList[top].Vertices)
            //        {
            //            v.RenderPoint += offVec;
            //            //if (!historyOffset.ContainsKey(v))
            //            //{
            //            //    v.RenderPoint += offVec;
            //            //    historyOffset[v] = offset;
            //            //}
            //            //else
            //            //{
            //            //    if (historyOffset[v] == 0)
            //            //    {
            //            //        v.RenderPoint += offVec;
            //            //        historyOffset[v] = offset;
            //            //    }
            //            //    else if (historyOffset[v] - offset == 0)
            //            //    {
            //            //        v.RenderPoint += offVec;
            //            //        historyOffset[v] = 0;
            //            //    }
            //            //}
            //        }
            //        top--;
            //        if (top - 1 < bottom || faceList[top].Layer != faceList[top - 1].Layer)
            //            break;
            //    }

            //    offset -= step;
            //}
        }