zoukankan      html  css  js  c++  java
  • WPF 3D足球导览

          根据博文:https://www.cnblogs.com/duel/p/regular3dpoints.html获取足球的3D坐标后,在每一个坐标位置创建一个ModelVisual3D元素,既能实现炫酷的3D界面。在此基础上我基于这些点构建了3D足球。

    动态效果图:

    Football3D1.gif

    Football3D2.gif

    每一个足球的块上,我贴上了不同的图,点击图获取对应的信息在右侧显示。

    实现原理:

      首先对所有顶点根据Y值进行分层,第一层的顶点见下图:

         image.png

    所有与第一层相互连接的点为第二层:

        image.png

    以此类推,总共可获得八层顶点。

    然后,拿到第一层(第一组)的顶点(5个),第一组五个顶点组成了正五边型,正五边形每一条边对应两个顶点,根据距离计算,可以从第二层中找到与第一层顶点距离最近的点,如下图第一层的正五边形的其中一条边AB,在第二层中可以通过计算拿到与A、B两个点距离最近的C、D两个点。然后以C、D作为基点从第三层中又可以得到同时距离C、D 两个点距离最近的两个点E、F。  

    image.png image.png

     从上面两个图你可以直观的看见,在第二层中分别与A、B距离最近的点只能是C、D。 在第三层中同时距离C点和D点最近的点只能是E、F。  ABCDEF六个点即构成了足球的一个面。 

    按照这种以层级和距离的方式即可计算得到足球的每一面所包含的3D坐标。

    循环计算实现逻辑代码:

    // Get Bucky Ball all Blocks
    private void GetBuckyBallBlocks()
    {
        // BuckyBallPoints -> List<List<Point3D>>
        int nLevelCount = BuckyBallPoints.Count; // 总层数 - 8
        for (int i = 0; i < nLevelCount; i++) // 
        {
            int nCurLevel = i;  //当前层
            //  下一层
            int nSecondLevelBaseCur = nCurLevel + 1;
            //  第三层
            int nThirdLevelBaseCur = nCurLevel + 2;
    
            //  three levels as a group, and every group defined five blocks
            //(1,2,3)(2,3,4)(3,4,5)(4,5,6)(5,6,7)(6,7,8)
            if (nThirdLevelBaseCur < nLevelCount)
            {
                // 计算距离,根据距离判断是否属于同一个面
                this.CalculateBuckyBallBlocks(BuckyBallPoints[nCurLevel], 
                    BuckyBallPoints[nSecondLevelBaseCur],
                    BuckyBallPoints[nThirdLevelBaseCur]);
            }
        }
        // 第一层(现成的正五边形)
        this.BuckyBallBlocks.Add(BuckyBallPoints[0]);
        // bottom block points  第八层(现成的正五边形)
        this.BuckyBallBlocks.Add(BuckyBallPoints[BuckyBallPoints.Count - 1]);
    }

    通过以上方式获得每一个面对应的顶点坐标后,即可通过坐标构建平面。 

    关键代码:

    // 根据顶面创建3D平面
    private MeshGeometry3D CreateBlockMeshGeometry3D(List<Point3D> ltPoints)
    {
        Point3D[] Point3Ds = new Point3D[ltPoints.Count];
        for (int i = 0; i < ltPoints.Count; i++)
            Point3Ds[i] = ltPoints[i];
    
        MeshGeometry3D oGeometry = new MeshGeometry3D()
        {
            Positions = new Point3DCollection(Point3Ds)
        };
    
        if (ltPoints.Count == 6)
            oGeometry.TriangleIndices = new Int32Collection(new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 4, 0, 4, 5 });
        else if (ltPoints.Count == 5)
            oGeometry.TriangleIndices = new Int32Collection(new int[] { 0, 1, 2, 0, 2, 3, 0, 3, 4 });
        else
            ShowErrorAndExit();
    
        PointCollection texCoords = new PointCollection();
        for (int i = ltPoints.Count -1; i >= 0; i--)
            texCoords.Add(new Point(ltPoints[i].X, ltPoints[i].Y));
        oGeometry.TextureCoordinates = texCoords;
    
        return oGeometry;
    }

    最后给每一个构建的平面的Visual属性附上加载的图片和点击事件既能实现我Demo中的效果。

    最后附上Demo整体效果图:

    Football3D3.gif

        工具:Visual Studio 2017

        工程:WPF C#

        源代码下载

                  

  • 相关阅读:
    Android拷贝工程不覆盖原工程的配置方法
    Android中BindService方式使用的理解
    getApplicationContext()、Activity.this、 getBaseContext区别
    深入理解ASP.NET MVC(4)
    深入理解ASP.NET MVC(1)
    深入理解ASP.NET MVC(2)
    深入理解ASP.NET MVC(目录)
    C# 代码优化
    NPOI 创建Excel 设置宽度 样式 颜色对比表
    2. Mysql数据库的入门知识
  • 原文地址:https://www.cnblogs.com/duel/p/3dfootball.html
Copyright © 2011-2022 走看看