예제 #1
0
 /// <summary>
 /// 计算一组三角形网格中每个顶点的Normal值
 /// 1.对每个三角形片元分析,根据*三个顶点*的坐标位置计算出该片元的法向矢量
 /// 2.将法向矢量赋值给三个顶点
 /// 3.对有片元进行处理完毕后,每个顶点的normal值是所有*与之相邻的片元法向矢量的和*
 /// 4.最后遍历每个顶点,对Norma值归一化即可
 /// </summary>
 /// <param name="inputVex"></param>
 /// <param name="inputInd"></param>
 public static void ComputeVertexNormal(ref MyVertex[] inputVex, int[] inputInd)
 {
     // 遍历每个三角形片元
     for (int i = 0; i < inputInd.Length / 3; i++)
     {
         // 三角形对应的三个顶点索引
         int i0 = inputInd[i * 3 + 0];
         int i1 = inputInd[i * 3 + 1];
         int i2 = inputInd[i * 3 + 2];
         // 三角形三个顶点
         MyVertex v0 = inputVex[i0];
         MyVertex v1 = inputVex[i1];
         MyVertex v2 = inputVex[i2];
         // 计算平面法向矢量
         Vector3 e0         = v1.Position - v0.Position;
         Vector3 e1         = v2.Position - v0.Position;
         Vector3 faceNormal = Vector3.Cross(e0, e1);
         // 因为这个三角形占用了这三个顶点
         // 因此这三个顶点的normal值应该添加该平面三角形的法线向量
         inputVex[i0].Normal += faceNormal;
         inputVex[i1].Normal += faceNormal;
         inputVex[i2].Normal += faceNormal;
     }
     // 遍历每个顶点,将其Normal值归一化
     for (int i = 0; i < inputVex.Length; i++)
     {
         inputVex[i].Normal = Vector3.Normalize(inputVex[i].Normal);
     }
 }
예제 #2
0
        public static MeshData[] LoadModelFromFile(string filename)
        {
            var importer = new AssimpContext();

            if (!importer.IsImportFormatSupported(System.IO.Path.GetExtension(filename)))
            {
                throw new ArgumentException($"Model format {System.IO.Path.GetExtension(filename)} is not supported. Cannot load {filename}.", nameof(filename));
            }
            var             postProcessFlags = PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace;
            var             model            = importer.ImportFile(filename, postProcessFlags);
            List <MeshData> meshDatas        = new List <MeshData>(model.MeshCount);
            MeshData        meshData         = new MeshData();

            foreach (var mesh in model.Meshes)
            {
                List <MyVertex> myVertices = new List <MyVertex>(mesh.VertexCount);
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    var pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3();

                    var norm = mesh.HasNormals ? mesh.Normals[i] : new Vector3D();
                    var texC = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][i] : new Vector3D(1, 1, 0);
                    var v    = new MyVertex(pos, norm.ToVector3(), texC.ToVector2());
                    myVertices.Add(v);
                }
                var indices = mesh.GetIndices().ToList();
                meshData.Vertices = myVertices.ToArray();
                meshData.Indices  = indices.ToArray();
                meshDatas.Add(meshData);
            }
            return(meshDatas.ToArray());
        }
예제 #3
0
        /// <summary>
        /// 生成平面
        /// </summary>
        /// <param name="length">平面长度 X方向</param>
        /// <param name="width">平面宽度 Z方向</param>
        /// <param name="lenNum">X方向切片数</param>
        /// <param name="widNum">Z方向切片数</param>
        /// <param name="outMesh">输出数据</param>
        public static void GeneratePlane(float length, float width, int lenNum, int widNum, out MeshData outMesh)
        {
            //[0]顶点数据
            List <MyVertex> tempVertice = new List <MyVertex>();
            MyVertex        tempVex;

            lenNum += 1;
            widNum += 1;
            float dl = length / lenNum;
            float dw = width / widNum;
            float y  = 0f;

            for (int i = 0; i < lenNum; i++)
            {
                float x = -length / 2 + i * dl;
                //第i列(从前往后)
                for (int j = 0; j < widNum; j++)
                {
                    //第j行(从左往右)
                    float z = -width / 2 + j * dw;
                    tempVex          = new MyVertex();
                    tempVex.Position = new Vector3(x, y, z);
                    tempVex.Normal   = new Vector3(0, 1, 0);
                    tempVertice.Add(tempVex);
                }
            }
            //[1]索引数据
            List <int> tempIndex = new List <int>();

            for (int i = 0; i < lenNum - 1; i++)
            {
                //第i列(从前往后)
                for (int j = 0; j < widNum - 1; j++)
                {
                    //第j行(从左往右)
                    tempIndex.Add(i * widNum + j);
                    tempIndex.Add(i * widNum + j + 1);
                    tempIndex.Add((i + 1) * widNum + j + 1);
                    tempIndex.Add((i + 1) * widNum + j + 1);
                    tempIndex.Add((i + 1) * widNum + j);
                    tempIndex.Add(i * widNum + j);
                }
            }

            outMesh.Indices  = tempIndex.ToArray();
            outMesh.Vertices = tempVertice.ToArray();
        }
예제 #4
0
        /// <summary>
        /// 生成柱体
        /// </summary>
        /// <param name="topRadius">顶部半径</param>
        /// <param name="bottomRadius">底部半径</param>
        /// <param name="height">高度</param>
        /// <param name="sliceCount">切片数</param>
        /// <param name="stackCount">断层数</param>
        /// <param name="outMesh">输出的MeshData网格结构</param>
        public static void GenerateCylinder(float topRadius, float bottomRadius, float height, int sliceCount, int stackCount, out MeshData outMesh)
        {
            //[0] 侧面数据
            // init meshdata size
            var vertexsNum = (stackCount + 1) * (sliceCount + 1);
            var indexNum   = stackCount * sliceCount * 6;

            outMesh = new MeshData(vertexsNum, indexNum);
            // Stacks
            float stackHeight = height / stackCount;
            // radius increment
            float radiusStep = (topRadius - bottomRadius) / stackCount;
            // ring count
            var   ringCount   = stackCount + 1;
            int   vetexNumber = 0;
            float dTheta      = 2.0f * (float)Math.PI / sliceCount;

            // 层层建模 侧面顶点数据
            for (int i = 0; i < ringCount; i++)
            {
                // 建模中心 y 在中心高度处,从低往高建
                float y = -0.5f * height + i * stackHeight;
                float r = bottomRadius + i * radiusStep;
                // vertices
                // 起始顶点和最终顶点只是位置一样,但顶点其它分量不同
                for (int j = 0; j <= sliceCount; j++)
                {
                    float    c        = (float)Math.Cos(j * dTheta);
                    float    s        = (float)Math.Sin(j * dTheta);
                    MyVertex myVertex = new MyVertex();
                    myVertex.Position = new Vector3(r * c, y, r * s);
                    float   dr        = bottomRadius - topRadius;
                    Vector3 bitangent = new Vector3(dr * c, -height, dr * s);
                    myVertex.Normal = Vector3.Normalize(Vector3.Cross(new Vector3(-s, 0f, c), bitangent));
                    outMesh.Vertices[vetexNumber] = myVertex;
                    vetexNumber++;
                }
            }

            //[1] 修改索引
            int number      = 0;
            int numsPerRing = sliceCount + 1;

            for (int i = 0; i < stackCount; i++)
            {
                for (int j = 0; j < sliceCount; j++)
                {
                    outMesh.Indices[number + 0] = i * numsPerRing + j;
                    outMesh.Indices[number + 1] = (i + 1) * numsPerRing + j;
                    outMesh.Indices[number + 2] = (i + 1) * numsPerRing + j + 1;
                    outMesh.Indices[number + 3] = (i + 1) * numsPerRing + j + 1;
                    outMesh.Indices[number + 4] = i * numsPerRing + j + 1;
                    outMesh.Indices[number + 5] = i * numsPerRing + j;
                    number += 6;
                }
            }

            //[2] 顶面数据和索引
            // 顶面顶点数据
            List <MyVertex> tempVertex = outMesh.Vertices.ToList();

            for (int i = 0; i <= sliceCount; i++)
            {
                float    x        = (float)(topRadius * Math.Cos(i * dTheta));
                float    z        = (float)(topRadius * Math.Sin(i * dTheta));
                MyVertex myVertex = new MyVertex();
                myVertex.Position = new Vector3(x, 0.5f * height, z);
                myVertex.Normal   = new Vector3(0, 1, 0);

                tempVertex.Add(myVertex);
            }
            // 顶点中心数据
            var myVertexCenter = new MyVertex();

            myVertexCenter.Position = new Vector3(0, 0.5f * height, 0);
            myVertexCenter.Normal   = new Vector3(0, 1, 0);

            tempVertex.Add(myVertexCenter);
            outMesh.Vertices = tempVertex.ToArray();

            // 顶面索引
            List <int> tempIndices = outMesh.Indices.ToList();

            for (int i = 0; i <= sliceCount; i++)
            {
                tempIndices.Add(outMesh.Vertices.Length - 1);
                tempIndices.Add(outMesh.Vertices.Length - 2 - i);
                tempIndices.Add(outMesh.Vertices.Length - 1 - i);
            }
            outMesh.Indices = tempIndices.ToArray();

            //[3] 底面数据和索引
            // 底面顶点数据
            tempVertex = outMesh.Vertices.ToList();
            for (int i = 0; i <= sliceCount; i++)
            {
                float    x        = (float)(topRadius * Math.Cos(i * dTheta));
                float    z        = (float)(topRadius * Math.Sin(i * dTheta));
                MyVertex myVertex = new MyVertex();
                myVertex.Position = new Vector3(x, -0.5f * height, z);
                myVertex.Normal   = new Vector3(0, -1, 0);

                tempVertex.Add(myVertex);
            }
            // 顶点中心数据
            myVertexCenter          = new MyVertex();
            myVertexCenter.Position = new Vector3(0, -0.5f * height, 0);
            myVertexCenter.Normal   = new Vector3(0, -1, 0);

            tempVertex.Add(myVertexCenter);
            outMesh.Vertices = tempVertex.ToArray();

            // 顶面索引
            tempIndices = outMesh.Indices.ToList();
            for (int i = 0; i <= sliceCount; i++)
            {
                tempIndices.Add(outMesh.Vertices.Length - 1);
                tempIndices.Add(outMesh.Vertices.Length - 2 - i);
                tempIndices.Add(outMesh.Vertices.Length - 1 - i);
            }
            outMesh.Indices = tempIndices.ToArray();
        }
예제 #5
0
        /// <summary>
        /// 生成球体
        /// </summary>
        /// <param name="rad">球体半径</param>
        /// <param name="sliceNum">切片数</param>
        /// <param name="stackNum">断层数</param>
        /// <param name="sphereMesh">输出的MeshData网格结构</param>
        public static void GenerateSphere(int rad, int sliceNum, int stackNum, out MeshData sphereMesh)
        {
            //[0]侧面
            sphereMesh = new MeshData(1, 1);
            float dTheta     = 2.0f * (float)Math.PI / sliceNum;
            float dPhi       = (float)Math.PI / stackNum;
            float Phi        = 0;
            var   tempVertex = sphereMesh.Vertices.ToList();

            tempVertex.Clear();
            //[1]底部顶点
            tempVertex.Add(new MyVertex()
            {
                Position = new Vector3(0, -rad, 0),
                Normal   = new Vector3(0, -1, 0),
            });
            float layerColor = 0f;

            //[2]层层建模 侧面顶点数据
            for (int i = 1; i < stackNum; i++)
            {
                // 建模中心 y 在中心高度处,从低往高建
                float y = -rad * (float)Math.Cos(Phi + i * dPhi);
                float r = rad * (float)Math.Sin(Phi + i * dPhi);
                // 起始顶点和最终顶点只是位置一样,但顶点其它分量不同
                for (int j = 0; j <= sliceNum; j++)
                {
                    float    c        = (float)Math.Cos(j * dTheta);
                    float    s        = (float)Math.Sin(j * dTheta);
                    MyVertex myVertex = new MyVertex();
                    myVertex.Position = new Vector3(r * c, y, r * s);
                    myVertex.Normal   = new Vector3(0, 1f, 0);
                    tempVertex.Add(myVertex);
                }
                layerColor += 0.1f;
            }
            //[3]顶部
            tempVertex.Add(new MyVertex()
            {
                Position = new Vector3(0, rad, 0),
                Normal   = new Vector3(0, 1, 0),
            });
            sphereMesh.Vertices = tempVertex.ToArray();

            //[4]索引部分
            int        numsPerRing = sliceNum + 1;
            List <int> tempIndice  = sphereMesh.Indices.ToList();

            tempIndice.Clear();
            int number = 0;

            for (int i = 0; i < sliceNum; i++)
            {
                tempIndice.Add(0);
                tempIndice.Add(number + 1);
                tempIndice.Add(number + 2);
                number += 1;
            }
            for (int i = 0; i < stackNum - 2; i++)
            {
                for (int j = 1; j <= sliceNum; j++)
                {
                    tempIndice.Add(i * numsPerRing + j);
                    tempIndice.Add((i + 1) * numsPerRing + j);
                    tempIndice.Add((i + 1) * numsPerRing + j + 1);
                    tempIndice.Add((i + 1) * numsPerRing + j + 1);
                    tempIndice.Add(i * numsPerRing + j + 1);
                    tempIndice.Add(i * numsPerRing + j);
                }
            }
            number = 0;
            for (int i = 0; i < sliceNum; i++)
            {
                tempIndice.Add(sphereMesh.Vertices.Length - 1);
                tempIndice.Add(sphereMesh.Vertices.Length - 2 - number);
                tempIndice.Add(sphereMesh.Vertices.Length - 3 - number);
                number += 1;
            }
            sphereMesh.Indices = tempIndice.ToArray();
        }