zoukankan      html  css  js  c++  java
  • Unity 生成圆角Cube

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using UnityEngine;
    public class CubeMeshController : MonoBehaviour
    {
        private float xSize = 3;
        private float ySize = 2;
        private float zSize = 4;
        private float cornerRadius = 2.3f;
        private int cornerSplitTime = 2;
        private float xRadius;
        private float yRadius;
        private float zRadius;
        private List<Vector2> uvList;
        private List<int> triangleList;
        private List<Vector3> vertexList;
        private int cornerFaceMaxIdx = 4;
        private int curvePointCnt = 9;
        private int cornerPointCnt = 18;
        private int mainFaceVertexOffset; //因为侧面和正面的uv贴图要做区分,不能渐变,offset后的定点用来缝合正面(上下两面)
        private bool isLeftButtomCorner;
        private bool isLeftTopCorner;
        private bool isRightTopCorner;
        private bool isRightButtomCorner;
    
    
        private Mesh GenerateMesh()
        {
            Mesh mesh = new Mesh();
            generateVertices();
            generateTriangles();
            mesh.vertices = vertexList.ToArray();
            mesh.triangles = triangleList.ToArray();
            mesh.RecalculateNormals();
            mesh.RecalculateTangents();
            mesh.uv = uvList.ToArray();
            return mesh;
        }
        public Mesh GetMeshNormal(float xSize, float ySize, float zSize, float cornerRadius = 2f, float cornerSplitTime = 3)
        {
            this.isLeftButtomCorner = true;
            this.isLeftTopCorner = true;
            this.isRightButtomCorner = true;
            this.isRightTopCorner = true;
            this.xSize = xSize;
            this.ySize = ySize;
            this.zSize = zSize;
            this.cornerSplitTime = 3;
            this.cornerRadius = cornerRadius;
            xRadius = xSize / 2.0f;
            yRadius = ySize / 2.0f;
            zRadius = zSize / 2.0f;
            curvePointCnt = ((int)Math.Pow(2, cornerSplitTime) + 1);
            cornerPointCnt = curvePointCnt * 2;
            cornerFaceMaxIdx = curvePointCnt - 1;
            mainFaceVertexOffset = cornerPointCnt * 4;// 这里uniqueVertexCnt表示独立的定点数 72
            return GenerateMesh();
        }
        public Mesh GetMesh(float xSize, float ySize, float zSize, GroundModel groundModel,float cornerRadius = 2f, int cornerSplitTime = 3)
        {
            this.isLeftButtomCorner = groundModel.isLeftButtomCorner;
            this.isLeftTopCorner = groundModel.isLeftTopCorner;
            this.isRightButtomCorner = groundModel.isRightButtomCorner;
            this.isRightTopCorner = groundModel.isRightTopCorner;
            this.xSize = xSize;
            this.ySize = ySize;
            this.zSize = zSize;
            this.cornerSplitTime = cornerSplitTime;
            this.cornerRadius = cornerRadius;
            xRadius = xSize / 2.0f;
            yRadius = ySize / 2.0f;
            zRadius = zSize / 2.0f;
            this.curvePointCnt = ((int)Math.Pow(2, cornerSplitTime) + 1);
            this.cornerPointCnt = this.curvePointCnt * 2;
            this.cornerFaceMaxIdx = this.curvePointCnt - 1;
            this.mainFaceVertexOffset = this.cornerPointCnt * 4; //
            return GenerateMesh();
        }
        private void generateVertices()
        {
            vertexList = new List<Vector3>();
            SetRightTopCornerList();
            SetTopLeftCornerList();
            SetBottomLeftCornerList();
            SetBottomRightCornerList();
            vertexList.AddRange(rightTopCornerList);
            vertexList.AddRange(topLeftConnerList);
            vertexList.AddRange(buttomLeftConnerList);
            vertexList.AddRange(buttomRightConnerList);
    
            //此处再加一遍的原因是因为顶面和侧面的uv不一样
            vertexList.AddRange(rightTopCornerList);
            vertexList.AddRange(topLeftConnerList);
            vertexList.AddRange(buttomLeftConnerList);
            vertexList.AddRange(buttomRightConnerList);
    
            uvList = new List<Vector2>();
            for (int i = 0; i < vertexList.Count; i++)
            {
                Vector3 vertex = vertexList[i];
                Vector2 uv;
                if (i < mainFaceVertexOffset)
                {
                    uv = new Vector2(0.5f + vertex.x /xSize, (0.5f + vertex.y / ySize) * 0.08f);
                }
                else
                {
                    uv = new Vector2(0.5f + vertex.x / xSize,  0.14f + (0.5f + vertex.z/zSize)* 0.86f);
                }
                uvList.Add(uv);
            }
        }
    
        public class VectorCenter
        {
            public Vector3 center;
            public float distance;
            public VectorCenter(Vector3 center, float distance)
            {
                this.center = center;
                this.distance = distance;
            }
        }
    
    
        private void splitAndAppendCenter(Vector3 start, Vector3 end, int splitTime, List<VectorCenter> vectorCenters, Vector3 oriStart, Vector3 circelCenter, float splitlength)
        {
    
            Vector3 center = GetCircleEdgePioint((start + end) / 2.0f, circelCenter, splitlength);
            vectorCenters.Add(new VectorCenter(center, Vector3.Distance(center, oriStart)));
            splitTime -= 1;
            if (splitTime > 0)
            {
                splitAndAppendCenter(start, center, splitTime, vectorCenters, oriStart, circelCenter, splitlength);
                splitAndAppendCenter(center, end, splitTime, vectorCenters, oriStart, circelCenter, splitlength);
            }
        }
    
        private void AddCenterList(List<Vector3> list, Vector3 start, Vector3 end, Vector3 circelCenter, float splitlength)
        {
            List<VectorCenter> vectorCenters = GetCencer(cornerSplitTime - 1, start, end, circelCenter, splitlength);
            foreach (VectorCenter vectorCenter in vectorCenters)
            {
                list.Add(vectorCenter.center);
            }
        }
        private List<VectorCenter> GetCencer(int splitTime, Vector3 start, Vector3 end, Vector3 circleCenter, float _radius)
        {
            List<VectorCenter> vectorCenters = new List<VectorCenter>();
            splitAndAppendCenter(start, end, splitTime, vectorCenters, start, circleCenter, _radius);
            return vectorCenters.OrderBy(item => item.distance).ToList();
    
        }
        List<Vector3> buttomRightConnerList;
        private void SetBottomRightCornerList()
        {
            float spliteLength = cornerRadius;
            if (!isRightButtomCorner)
            {
                spliteLength = 0;
            }
            buttomRightConnerList = new List<Vector3>();
            // buttom face
            Vector3 corner1Point = new Vector3(xRadius, -yRadius, -zRadius);
            Vector3 circelCenter1 = GetCircleCenter(spliteLength, corner1Point, CORNERTYPE.bottomRight);
            Vector3 buttomCenter = GetCircleEdgePioint(corner1Point, circelCenter1, spliteLength);
            Vector3 point1Buttom = new Vector3(xRadius - spliteLength / 2.0f, -yRadius, -zRadius);
            Vector3 point2Buttom = new Vector3(xRadius, -yRadius, -zRadius + spliteLength / 2.0f);
            buttomRightConnerList.Add(point1Buttom);
            AddCenterList(buttomRightConnerList, point1Buttom, buttomCenter, circelCenter1, spliteLength);
            buttomRightConnerList.Add(buttomCenter);
            AddCenterList(buttomRightConnerList, buttomCenter, point2Buttom, circelCenter1, spliteLength);
            buttomRightConnerList.Add(point2Buttom);
            // top face
            Vector3 corner2Point = new Vector3(xRadius, yRadius, -zRadius);
            Vector3 circelCenter2 = GetCircleCenter(spliteLength, corner2Point, CORNERTYPE.bottomRight);
            Vector3 topCenter = GetCircleEdgePioint(corner2Point, circelCenter2, spliteLength);
            Vector3 point1Top = new Vector3(xRadius - spliteLength / 2.0f, yRadius, -zRadius);
            Vector3 point2Top = new Vector3(xRadius, yRadius, -zRadius + spliteLength / 2.0f);
            buttomRightConnerList.Add(point1Top);
            AddCenterList(buttomRightConnerList, point1Top, topCenter, circelCenter2, spliteLength);
            buttomRightConnerList.Add(topCenter);
            AddCenterList(buttomRightConnerList, topCenter, point2Top, circelCenter2, spliteLength);
            buttomRightConnerList.Add(point2Top);
    
        }
        List<Vector3> rightTopCornerList;
        private void SetRightTopCornerList()
        {
            float _cornerRadius = cornerRadius;
            if (!isRightTopCorner)
            {
                _cornerRadius = 0;
            }
            rightTopCornerList = new List<Vector3>();
            // buttom face
            Vector3 corner1Point = new Vector3(xRadius, -yRadius, zRadius);
            Vector3 circleCenter1 = GetCircleCenter(_cornerRadius, corner1Point, CORNERTYPE.topRight);
            Vector3 bottomCenter = GetCircleEdgePioint(corner1Point, circleCenter1, _cornerRadius);
            Vector3 point1Bottom = new Vector3(xRadius, -yRadius, zRadius - _cornerRadius / 2.0f);
            Vector3 point2Bottom = new Vector3(xRadius - _cornerRadius / 2.0f, -yRadius, zRadius);
            rightTopCornerList.Add(point1Bottom);
            AddCenterList(rightTopCornerList, point1Bottom, bottomCenter, circleCenter1, _cornerRadius);
            rightTopCornerList.Add(bottomCenter);
            AddCenterList(rightTopCornerList, bottomCenter, point2Bottom, circleCenter1, _cornerRadius);
            rightTopCornerList.Add(point2Bottom);
            // top face
            Vector3 corner2Point = new Vector3(xRadius, yRadius, zRadius);
            Vector3 circelCenter2 = GetCircleCenter(_cornerRadius, corner2Point, CORNERTYPE.topRight);
            Vector3 topCenter = GetCircleEdgePioint(corner2Point, circelCenter2, _cornerRadius);
            Vector3 point1Top = new Vector3(xRadius, yRadius, zRadius - _cornerRadius / 2.0f);
            Vector3 point2Top = new Vector3(xRadius - _cornerRadius / 2.0f, yRadius, zRadius);
            rightTopCornerList.Add(point1Top);
            AddCenterList(rightTopCornerList, point1Top, topCenter, circelCenter2, _cornerRadius);
            rightTopCornerList.Add(topCenter);
            AddCenterList(rightTopCornerList, topCenter, point2Top, circelCenter2, _cornerRadius);
            rightTopCornerList.Add(point2Top);
        }
        List<Vector3> topLeftConnerList;
        private void SetTopLeftCornerList()
        {
            float spliteLength = cornerRadius;
            if (!isLeftTopCorner)
            {
                spliteLength = 0;
            }
            topLeftConnerList = new List<Vector3>();
            // buttom face
            Vector3 corner1Point = new Vector3(-xRadius, -yRadius, zRadius);
            Vector3 circelCenter1 = GetCircleCenter(spliteLength, corner1Point, CORNERTYPE.topLeft);
            Vector3 buttomCenter = GetCircleEdgePioint(corner1Point, circelCenter1, spliteLength);
            Vector3 point1Buttom = new Vector3(-xRadius + spliteLength / 2.0f, -yRadius, zRadius);
            Vector3 point2Buttom = new Vector3(-xRadius, -yRadius, zRadius - spliteLength / 2.0f);
            topLeftConnerList.Add(point1Buttom);
            AddCenterList(topLeftConnerList, point1Buttom, buttomCenter, circelCenter1, spliteLength);
            topLeftConnerList.Add(buttomCenter);
            AddCenterList(topLeftConnerList, buttomCenter, point2Buttom, circelCenter1, spliteLength);
            topLeftConnerList.Add(point2Buttom);
            // top face
            Vector3 corner2Point = new Vector3(-xRadius, yRadius, zRadius);
            Vector3 circelCenter2 = GetCircleCenter(spliteLength, corner2Point, CORNERTYPE.topLeft);
            Vector3 topCenter = GetCircleEdgePioint(corner2Point, circelCenter2, spliteLength);
            Vector3 point1Top = new Vector3(-xRadius + spliteLength / 2.0f, yRadius, zRadius);
            Vector3 point2Top = new Vector3(-xRadius, yRadius, zRadius - spliteLength / 2.0f);
            topLeftConnerList.Add(point1Top);
            AddCenterList(topLeftConnerList, point1Top, topCenter, circelCenter2, spliteLength);
            topLeftConnerList.Add(topCenter);
            AddCenterList(topLeftConnerList, topCenter, point2Top, circelCenter2, spliteLength);
            topLeftConnerList.Add(point2Top);
    
        }
        List<Vector3> buttomLeftConnerList;
    
        private void SetBottomLeftCornerList()
        {
            float spliteLength = cornerRadius;
            if (!isLeftButtomCorner)
            {
                spliteLength = 0;
            }
            buttomLeftConnerList = new List<Vector3>();
            // buttom face
            Vector3 corner1Point = new Vector3(-xRadius, -yRadius, -zRadius);
            Vector3 circelCenter1 = GetCircleCenter(spliteLength, corner1Point, CORNERTYPE.bottomLeft);
            Vector3 buttomCenter = GetCircleEdgePioint(corner1Point, circelCenter1, spliteLength);
            Vector3 point1Buttom = new Vector3(-xRadius, -yRadius, -zRadius + spliteLength / 2.0f);
            Vector3 point2Buttom = new Vector3(-xRadius + spliteLength / 2.0f, -yRadius, -zRadius);
            buttomLeftConnerList.Add(point1Buttom);
            AddCenterList(buttomLeftConnerList, point1Buttom, buttomCenter, circelCenter1, spliteLength);
            buttomLeftConnerList.Add(buttomCenter);
            AddCenterList(buttomLeftConnerList, buttomCenter, point2Buttom, circelCenter1, spliteLength);
            buttomLeftConnerList.Add(point2Buttom);
            // top face
            Vector3 corner2Point = new Vector3(-xRadius, yRadius, -zRadius);
            Vector3 circelCenter2 = GetCircleCenter(spliteLength, corner2Point, CORNERTYPE.bottomLeft);
            Vector3 topCenter = GetCircleEdgePioint(corner2Point, circelCenter2, spliteLength);
            Vector3 point1Top = new Vector3(-xRadius, yRadius, -zRadius + spliteLength / 2.0f);
            Vector3 point2Top = new Vector3(-xRadius + spliteLength / 2.0f, yRadius, -zRadius);
            buttomLeftConnerList.Add(point1Top);
            AddCenterList(buttomLeftConnerList, point1Top, topCenter, circelCenter2, spliteLength);
            buttomLeftConnerList.Add(topCenter);
            AddCenterList(buttomLeftConnerList, topCenter, point2Top, circelCenter2, spliteLength);
            buttomLeftConnerList.Add(point2Top);
    
        }
        public enum CORNERTYPE
        {
            bottomLeft,
            bottomRight,
            topLeft,
            topRight
    
        }
        private Vector3 GetCircleCenter(float _cornerRadius, Vector3 cornerPoint, CORNERTYPE cornerType)
        {
            Vector3 center = Vector3.zero;
            switch (cornerType)
            {
                case CORNERTYPE.bottomLeft:
                    center = new Vector3(cornerPoint.x + _cornerRadius / 2.0f, cornerPoint.y, cornerPoint.z + _cornerRadius / 2.0f);
                    break;
                case CORNERTYPE.bottomRight:
                    center = new Vector3(cornerPoint.x - _cornerRadius / 2.0f, cornerPoint.y, cornerPoint.z + _cornerRadius / 2.0f);
                    break;
                case CORNERTYPE.topLeft:
                    center = new Vector3(cornerPoint.x + _cornerRadius / 2.0f, cornerPoint.y, cornerPoint.z - _cornerRadius / 2.0f);
                    break;
                case CORNERTYPE.topRight:
                    center = new Vector3(cornerPoint.x - _cornerRadius / 2.0f, cornerPoint.y, cornerPoint.z - _cornerRadius / 2.0f);
                    break;
            }
            return center;
        }
    
        private Vector3 GetCircleEdgePioint(Vector3 cornerPoint, Vector3 centerPoint, float spliteLength)
        {
            return centerPoint + (cornerPoint - centerPoint).normalized * spliteLength / 2.0f;
        }
    
        private void AddSurroundCornerTriangle(int cornerIdx)
        {
            if(cornerIdx != -1)
            {
                int cornerOffset = cornerIdx * cornerPointCnt;
                for (int i = 0; i < this.curvePointCnt - 1; i++)
                {
                   
                    //顺时针,底下1个点上面2个点的三角形
                    triangleList.Add(i + cornerOffset);
                    triangleList.Add(i + this.curvePointCnt + cornerOffset);
                    triangleList.Add(i + this.curvePointCnt + 1 + cornerOffset);
                    //顺时针,底下2个点上面1个点的三角形,与上面的三角形构成四边形
                    triangleList.Add(i + cornerOffset);
                    triangleList.Add(i + this.curvePointCnt + 1 + cornerOffset);
                    triangleList.Add(i + 1 + cornerOffset);
                }
            }
        }
    
        private void AddSurroundFaceTriangle(int cornerIdx)
        {
            int cornerOffset = this.cornerPointCnt * cornerIdx;
    
            //上面三角形
            triangleList.Add((this.curvePointCnt - 1 + cornerOffset));
            triangleList.Add((this.cornerPointCnt - 1 + cornerOffset));
            if(cornerIdx == 3)
            {
                triangleList.Add(this.curvePointCnt);
            }
            else
            {
                triangleList.Add((this.cornerPointCnt + this.curvePointCnt + cornerOffset));
            }
    
            //下面三角形
            triangleList.Add((this.curvePointCnt - 1 + cornerOffset));
            if (cornerIdx == 3)
            {
                triangleList.Add(this.curvePointCnt);
                triangleList.Add(0);
            }
            else
            {
                triangleList.Add((this.cornerPointCnt + this.curvePointCnt + cornerOffset));
                triangleList.Add((this.cornerPointCnt + cornerOffset));
            }
          
        }
    
        
        private void AddBottomAndTopFaceEdge(int cornerIdx)
        {
            if(cornerIdx == 0)
            {
    
                for (int i = 1; i < this.curvePointCnt -1; i++)
                {
                    //底面
                    triangleList.Add(0 + mainFaceVertexOffset);
                    triangleList.Add(i + mainFaceVertexOffset);
                    triangleList.Add(i + 1 + mainFaceVertexOffset);
                }
                for (int i = 1; i < this.curvePointCnt - 1; i++)
                {
                    //顶面
                    triangleList.Add(0 + this.curvePointCnt + mainFaceVertexOffset);
                    triangleList.Add(i + 1 + this.curvePointCnt + mainFaceVertexOffset);
                    triangleList.Add(i + this.curvePointCnt + mainFaceVertexOffset );
    
                }
                
            }
            else
            {
                for (int i = 0; i < this.curvePointCnt - 1; i++)
                {
                    //底面
                    triangleList.Add(0 + mainFaceVertexOffset);
                    triangleList.Add(i + mainFaceVertexOffset + cornerIdx * cornerPointCnt );
                    triangleList.Add(i + 1 + mainFaceVertexOffset + cornerIdx * cornerPointCnt);
                }
                for (int i = 0; i < this.curvePointCnt - 1; i++)
                {
                    //顶面
                    triangleList.Add(0 + this.curvePointCnt + mainFaceVertexOffset );
                    triangleList.Add(i + 1 + this.curvePointCnt + mainFaceVertexOffset + cornerIdx * cornerPointCnt);
                    triangleList.Add(i + this.curvePointCnt + mainFaceVertexOffset + cornerIdx * cornerPointCnt);
                }
            }
            
        }
        
        private void AddButtomAndTopFaceCenter()
        {
            //bottom face 正确
            triangleList.Add(0 + mainFaceVertexOffset);
            triangleList.Add(this.curvePointCnt - 1 + mainFaceVertexOffset);
            triangleList.Add(this.cornerPointCnt + mainFaceVertexOffset);
    
            triangleList.Add(0 + mainFaceVertexOffset);
            triangleList.Add(this.curvePointCnt - 1 + this.cornerPointCnt + mainFaceVertexOffset);
            triangleList.Add(this.cornerPointCnt + this.cornerPointCnt + mainFaceVertexOffset);
    
            triangleList.Add(0 + mainFaceVertexOffset);
            triangleList.Add(this.curvePointCnt - 1 + this.cornerPointCnt * 2 + mainFaceVertexOffset);
            triangleList.Add(this.cornerPointCnt + this.cornerPointCnt * 2 + mainFaceVertexOffset);
    
    
            //顶面
            triangleList.Add(this.curvePointCnt - 1 + this.curvePointCnt + mainFaceVertexOffset);
            triangleList.Add(0 + this.curvePointCnt + mainFaceVertexOffset);
            triangleList.Add(this.cornerPointCnt + +this.curvePointCnt + mainFaceVertexOffset);
    
            triangleList.Add(this.curvePointCnt - 1 + this.cornerPointCnt + this.curvePointCnt + mainFaceVertexOffset);
            triangleList.Add(0 + mainFaceVertexOffset + this.curvePointCnt);
            triangleList.Add(this.cornerPointCnt + this.cornerPointCnt + this.curvePointCnt + mainFaceVertexOffset);
    
    
            triangleList.Add(this.curvePointCnt - 1 + this.curvePointCnt + this.cornerPointCnt * 2 + mainFaceVertexOffset);
            triangleList.Add(0 + mainFaceVertexOffset+ this.curvePointCnt);
            triangleList.Add(this.cornerPointCnt + this.curvePointCnt + this.cornerPointCnt * 2 + mainFaceVertexOffset);
    
    
        }
        private void generateTriangles()
        {
            triangleList = new List<int>();
            for (int cornerIndex = 0; cornerIndex < 4; cornerIndex++)
            {
                AddSurroundCornerTriangle(cornerIndex);
                AddSurroundFaceTriangle(cornerIndex);
                AddBottomAndTopFaceEdge(cornerIndex);
            }
            AddButtomAndTopFaceCenter();
    
        }
    }
  • 相关阅读:
    django core cache 永不失效配置
    zabbix-ODBC-oracle
    time
    zabbix中的触发器依赖
    Servlet1
    每周总结01
    使用IntelliJ IDEA集成TomCat
    hadoop环境配置
    《软件工程》学习进度条博客16
    03梦断代码读后感3
  • 原文地址:https://www.cnblogs.com/sy-liu/p/12937434.html
Copyright © 2011-2022 走看看