Represents an area of a texture to be used by a set of faces. Faces will be mapped to this area depending upon the type of mapping selected (straight or circular)
예제 #1
0
        public UVArea getArea(string name)
        {
            UVArea a = null;

            uvAreas.TryGetValue(name, out a);
            return(a);
        }
예제 #2
0
 public UVArea(UVArea input)
 {
     this.u1 = input.u1;
     this.u2 = input.u2;
     this.v1 = input.v1;
     this.v2 = input.v2;
 }
예제 #3
0
 public List<Vertex> generateVertices(MeshBuilder builder, Vector3 offset, UVArea area, float v, float yCos, float ySin)
 {
     List<Vertex> vertices = builder.generateRadialVerticesFlatUVs(offset, faces, radius, height, startAngle, endAngle, v, area, yCos, ySin);
     startVector = vertices[0].vertex;
     endVector = vertices[vertices.Count - 1].vertex;
     return vertices;
 }
예제 #4
0
 public void setUVArea(UVArea area)
 {
     this.u1 = area.u1;
     this.u2 = area.u2;
     this.v1 = area.v1;
     this.v2 = area.v2;
 }
예제 #5
0
 public void setUVArea(UVArea area)
 {
     this.u1 = area.u1;
     this.u2 = area.u2;
     this.v1 = area.v1;
     this.v2 = area.v2;
 }
예제 #6
0
        public List <Vertex> generateVertices(MeshBuilder builder, Vector3 offset, UVArea area, float v, float yCos, float ySin)
        {
            List <Vertex> vertices = builder.generateRadialVerticesFlatUVs(offset, faces, radius, height, startAngle, endAngle, v, area, yCos, ySin);

            startVector = vertices[0].vertex;
            endVector   = vertices[vertices.Count - 1].vertex;
            return(vertices);
        }
예제 #7
0
        public UVMap(ConfigNode node)
        {
            ConfigNode[] areaNodes = node.GetNodes("UVAREA");
            int          len       = areaNodes.Length;

            for (int i = 0; i < len; i++)
            {
                UVArea area = new UVArea(areaNodes[i]);
                uvAreas.Add(area.name, area);
            }
        }
예제 #8
0
        public Mesh generatePanels(Vector3 pos, UVArea outer, UVArea inner, UVArea caps)
        {
            int         len     = outerArcs.Count;
            MeshBuilder builder = new MeshBuilder();

            for (int i = 0; i < len - 1; i++)
            {
                generatePanelSegment(builder, pos, outerArcs[i], outerArcs[i + 1], outer, false, true, false);                             //outside panels
                generatePanelSegment(builder, pos, innerArcs[i], innerArcs[i + 1], inner, true, false, true);                              //inside panels
            }
            generatePanelSegment(builder, pos, outerArcs[0], innerArcs[0], caps, true, false, false);                                      //bottom cap
            generatePanelSegment(builder, pos, outerArcs[outerArcs.Count - 1], innerArcs[innerArcs.Count - 1], caps, false, false, false); //top cap

            if (shouldGenerateSidewalls)
            {
                generateSidewalls(builder, caps);
            }

            return(builder.buildMesh());
        }
        protected void generateFairingPanel(MeshGenerator gen)
        {
            //generate outer wall
            generateFairingWallSection(gen, outerCap, outerPanel, 0, totalPanelHeight, maxPanelSectionHeight, boltPanelHeight, topOuterRadius, bottomOuterRadius, sidesPerPanel, anglePerSide, startAngle, true);

            //generate inner wall
            generateFairingWallSection(gen, innerCap, innerPanel, 0, totalPanelHeight, maxPanelSectionHeight, boltPanelHeight, topInnerRadius, bottomInnerRadius, sidesPerPanel, anglePerSide, startAngle, false);

            //setup proper scaled UVs to maintain 1:1 aspect ratio for a straight cylinder panel
            UVArea innerCapUV = new UVArea (this.innerCap);
            float vHeight = innerCapUV.v2 - innerCapUV.v1;
            float uScale = vHeight / wallThickness;
            innerCapUV.u2 = (bottomOuterCirc / (float)numOfPanels) * uScale;

            gen.setUVArea(innerCapUV);
            //generate bottom cap
            gen.generateCylinderPartialCap(0, -bottomOuterRadius, 0, bottomOuterRadius, bottomInnerRadius, sidesPerPanel, anglePerSide, startAngle, false);

            innerCapUV.u2 = (topOuterCirc / (float)numOfPanels) * uScale;
            gen.setUVArea(innerCapUV);
            //generate top cap
            gen.generateCylinderPartialCap(0, -bottomOuterRadius, 0 + totalPanelHeight, topOuterRadius, topInnerRadius, sidesPerPanel, anglePerSide, startAngle, true);

            // uScale is already determined by wall thickness
            // thus only uv-U needs scaled based on actual panel aspect ratio
            Vector2 topMeasure = new Vector2 (topOuterRadius - bottomOuterRadius, totalPanelHeight);
            float sideHeight = topMeasure.magnitude;
            innerCapUV.u2 = sideHeight * uScale;
            gen.setUVArea(innerCapUV);
            //generate left? panel side
            gen.generateCylinderPanelSidewall(0, -bottomOuterRadius, 0, totalPanelHeight, topOuterRadius, topInnerRadius, bottomOuterRadius, bottomInnerRadius, startAngle, true);
            //generate right? panel side
            gen.generateCylinderPanelSidewall(0, -bottomOuterRadius, 0, totalPanelHeight, topOuterRadius, topInnerRadius, bottomOuterRadius, bottomInnerRadius, startAngle + anglePerPanel, false);
        }
예제 #10
0
 public UVArea(UVArea input)
 {
     this.u1 = input.u1;
     this.u2 = input.u2;
     this.v1 = input.v1;
     this.v2 = input.v2;
 }
예제 #11
0
        /// <summary>
        /// Generates a ring of vertices using circular UV mapping, where the center of the ring is the center of the UV area.  
        /// Input radius is the radius of the actual ring, uvRadius is the radius to be used for maximal UV bounds 
        /// (e.g. they will only be different on an inner-ring; where radius=ring radius, and uvRadius = outerRingRadius)
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="faces"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="area">The UV area to map the UV vertex to.</param>
        /// <param name="uvRadius">The radius to be used for the UV area, in case it differs from the radius in use (basically scales the UV area)</param>
        /// <param name="yCos">Determines the x/z normal component</param>
        /// <param name="ySin">Used directly as the y normal component</param>
        /// <returns></returns>
        public List<Vertex> generateRadialVerticesCylinderUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, UVArea area, float uvRadius, float yCos, float ySin)
        {
            List<Vertex> verts = new List<Vertex>();
            float totalAngle = endAngle - startAngle;
            float anglePerFace = 360f / faces;
            int numOfFaces = (int)(totalAngle / anglePerFace);
            float angle, xCos, zSin, nx, ny, nz, x, y, z;

            Vector2 min = new Vector2(-uvRadius, -uvRadius);
            Vector2 max = new Vector2(uvRadius, uvRadius);
            Vector2 pos;
            Vector2 uv;
            for (int i = 0; i < numOfFaces + 1; i++)
            {
                angle = startAngle + anglePerFace * i;
                xCos = Mathf.Cos(angle * Mathf.Deg2Rad);
                zSin = Mathf.Sin(angle * Mathf.Deg2Rad);
                x = xCos * radius + offset.x;
                y = height + offset.y;
                z = zSin * radius + offset.z;
                nx = xCos * yCos;
                ny = ySin;
                nz = zSin * yCos;
                pos = new Vector2(xCos * radius, zSin * radius);
                uv = area.getUV(min, max, pos);
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ny, nz), uv));
            }
            return verts;
        }
예제 #12
0
        /// <summary>
        /// Used to generate a ring of vertices with the uvMapping appropriate for a cylinder wall (increments in +x)
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="faces"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="v"></param>
        /// <param name="area"></param>
        /// <param name="yCos"></param>
        /// <param name="ySin"></param>
        /// <returns></returns>
        public List<Vertex> generateRadialVerticesFlatUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, float v, UVArea area, float yCos, float ySin)
        {
            List<Vertex> verts = new List<Vertex>();
            float startRad = startAngle * Mathf.Deg2Rad;
            float endRad = endAngle * Mathf.Deg2Rad;
            float totalRad = endRad - startRad;
            float radPerFace = (float)((2.0 * Math.PI) / faces);
            float radPerSub = radPerFace / subdivision;
            int numOfFaces = (int)Math.Round(totalRad / radPerFace, 0);

            float rads, xCos, zSin, nx, ny, nz, x, y, z, percentTotalAngle;
            float subRads, x2 = 0, z2 = 0, x3, z3, xCos2 = 0, zSin2 = 0, nextRads = 0, nextPerc=0, subPerc, lerp;

            y = height + offset.y;
            ny = ySin;

            for (int i = 0; i < numOfFaces + 1; i++)
            {
                if (i > 0)//vars were caled last round for the interpolation
                {
                    rads = nextRads;
                    percentTotalAngle = nextPerc;
                    xCos = xCos2;
                    zSin = zSin2;
                    x = x2;
                    z = z2;
                }
                else
                {
                    rads = startRad + (radPerFace * i);
                    percentTotalAngle = (rads - startRad) / totalRad;
                    xCos = Mathf.Cos(rads);
                    zSin = Mathf.Sin(rads);
                    x = xCos * radius + offset.x;
                    z = zSin * radius + offset.z;
                }

                nx = xCos * yCos;
                nz = zSin * yCos;
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ny, nz), new Vector2(area.getU(percentTotalAngle), v)));

                //calculate the points/etc for the next panel face, to lerp between positions; data is re-used next iteration if present
                nextRads = startRad + (radPerFace * (i + 1));
                nextPerc = (nextRads - startRad) / totalRad;
                xCos2 = Mathf.Cos(nextRads);
                zSin2 = Mathf.Sin(nextRads);
                x2 = xCos2 * radius + offset.x;
                z2 = zSin2 * radius + offset.z;

                //do not add subdivision panel if the next vertex is the last one in the ring
                if (i == numOfFaces) { break; }
                //if was the last vert... do not add subs
                for (int k = 1; k < subdivision; k++)
                {
                    lerp = (float)k / subdivision;
                    x3 = Mathf.Lerp(x, x2, lerp);
                    z3 = Mathf.Lerp(z, z2, lerp);
                    subRads = rads + (radPerSub * k);//subangle used for normal calc... position calculated from interpolation to maintain cylinder side matching
                    subPerc = (subRads - startRad) / totalRad;
                    xCos = Mathf.Cos(subRads);
                    zSin = Mathf.Sin(subRads);
                    nx = xCos * yCos;
                    nz = zSin * yCos;
                    verts.Add(addVertex(new Vector3(x3, y, z3), new Vector3(nx, ny, nz), new Vector2(area.getU(subPerc), v)));
                }
            }
            return verts;
        }
예제 #13
0
        public Mesh generatePanels(Vector3 pos, UVArea outer, UVArea inner, UVArea caps)
        {
            int len = outerArcs.Count;
            MeshBuilder builder = new MeshBuilder();

            for (int i = 0; i < len - 1; i++)
            {
                generatePanelSegment(builder, pos, outerArcs[i], outerArcs[i + 1], outer, false, true, false);//outside panels
                generatePanelSegment(builder, pos, innerArcs[i], innerArcs[i + 1], inner, true, false, true);//inside panels
            }
            generatePanelSegment(builder, pos, outerArcs[0], innerArcs[0], caps, true, false, false);//bottom cap
            generatePanelSegment(builder, pos, outerArcs[outerArcs.Count - 1], innerArcs[innerArcs.Count - 1], caps, false, false, false);//top cap

            if (shouldGenerateSidewalls)
            {
                generateSidewalls(builder, caps);
            }

            return builder.buildMesh();
        }
예제 #14
0
 private void loadConfigData()
 {
     ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData);
     ConfigNode insideUVNode = node.GetNode("UVMAP", "name", "inside");
     ConfigNode outsideUVNode = node.GetNode("UVMAP", "name", "outside");
     ConfigNode topNode = node.GetNode("UVMAP", "name", "top");
     ConfigNode bottomNode = node.GetNode("UVMAP", "name", "bottom");
     insideUV = new UVArea(insideUVNode);
     outsideUV = new UVArea(outsideUVNode);
     topUV = new UVArea(topNode);
     bottomUV = new UVArea(bottomNode);
     techLimits = TechLimitHeightDiameter.loadTechLimits(node.GetNodes("TECHLIMIT"));
     updateTechLimits();
 }
예제 #15
0
        private void generateSidewalls(MeshBuilder builder, UVArea caps)
        {
            int len = outerArcs.Count;

            float[] distances   = new float[len];
            float[] us          = new float[len];
            float   totalLength = 0;
            float   length;
            Vector3 a, b;

            for (int i = 0; i < len - 1; i++)
            {
                a                = outerArcs[i].startVector;
                b                = outerArcs[i + 1].startVector;
                length           = Vector3.Distance(a, b);
                totalLength     += length;
                distances[i + 1] = length;
            }

            length = 0;
            float percent;
            float uDelta = caps.u2 - caps.u1;

            for (int i = 0; i < len; i++)
            {
                length += distances[i];
                percent = length / totalLength;
                us[i]   = caps.u1 + percent * uDelta;
            }

            Vector3 leftNorm = new Vector3();

            leftNorm.x = outerArcs[0].startVector.z;
            leftNorm.z = -outerArcs[0].startVector.x;
            leftNorm.Normalize();
            Vector3 rightNorm = new Vector3();

            rightNorm.x = outerArcs[0].endVector.z;
            rightNorm.z = -outerArcs[0].endVector.x;
            rightNorm.Normalize();
            rightNorm = -rightNorm;//as faces get inverted for this side, so norms get inverted as well

            //left
            List <Vertex> outerStartVerts = new List <Vertex>();
            List <Vertex> innerStartVerts = new List <Vertex>();

            //right
            List <Vertex> outerEndVerts = new List <Vertex>();
            List <Vertex> innerEndVerts = new List <Vertex>();

            len = outerArcs.Count;
            Vector3 outer, inner;
            Vector2 uv;

            for (int i = 0; i < len; i++)
            {
                outer = outerArcs[i].startVector;
                uv    = new Vector2(us[i], caps.v1);
                outerStartVerts.Add(builder.addVertex(outer, leftNorm, uv));
                inner = innerArcs[i].startVector;
                uv    = new Vector2(us[i], caps.v2);
                innerStartVerts.Add(builder.addVertex(inner, leftNorm, uv));

                outer = outerArcs[i].endVector;
                uv    = new Vector2(us[i], caps.v1);
                outerEndVerts.Add(builder.addVertex(outer, rightNorm, uv));
                inner = innerArcs[i].endVector;
                uv    = new Vector2(us[i], caps.v2);
                innerEndVerts.Add(builder.addVertex(inner, rightNorm, uv));
            }
            builder.generateQuads(outerStartVerts, innerStartVerts, false);
            builder.generateQuads(outerEndVerts, innerEndVerts, true);
        }
예제 #16
0
        private void generatePanelSegment(MeshBuilder builder, Vector3 pos, Arc arcA, Arc arcB, UVArea area, bool invertFaces, bool invertNormalY, bool invertNormalXZ)
        {
            float heightDiff  = arcB.height - arcA.height;
            float offset      = arcA.radius - arcB.radius;
            float sideRadians = Mathf.Atan2(heightDiff, offset) - 90 * Mathf.Deg2Rad;
            float yCos        = Mathf.Cos(sideRadians);
            float ySin        = Mathf.Sin(sideRadians);

            if (invertNormalY)
            {
                ySin *= -1;
            }
            if (invertNormalXZ)
            {
                yCos *= -1;
            }
            List <Vertex> verts1 = new List <Vertex>();
            List <Vertex> verts2 = new List <Vertex>();

            verts1.AddRange(arcA.generateVertices(builder, pos, area, area.v1, yCos, ySin));
            verts2.AddRange(arcB.generateVertices(builder, pos, area, area.v2, yCos, ySin));
            builder.generateQuads(verts1, verts2, invertFaces);
        }
예제 #17
0
        /// <summary>
        /// Generates a ring of vertices using circular UV mapping, where the center of the ring is the center of the UV area.
        /// This would be used to generate a partial ring, such as the procedural decoupler
        /// Input radius is the radius of the actual ring, uvRadius is the radius to be used for maximal UV bounds 
        /// (e.g. they will only be different on an inner-ring; where radius=ring radius, and uvRadius = outerRingRadius)
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="faces"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="area">The UV area to map the UV vertex to.</param>
        /// <param name="uvRadius">The radius to be used for the UV area, in case it differs from the radius in use (basically scales the UV area)</param>
        /// <param name="yCos">Determines the x/z normal component</param>
        /// <param name="ySin">Used directly as the y normal component</param>
        /// <returns></returns>
        public List<Vertex> generateRadialVerticesCylinderUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, UVArea area, float uvRadius, float yCos, float ySin)
        {
            List<Vertex> verts = new List<Vertex>();
            float startRad = startAngle * Mathf.Deg2Rad;
            float endRad = endAngle * Mathf.Deg2Rad;
            float totalRad = endRad - startRad;
            float radPerFace = (2f*Mathf.PI) / faces;
            //int numOfFaces = (int)(totalRad / radPerFace);
            int numOfFaces = (int)Math.Round(totalRad / radPerFace, 0);
            float rads, xCos, zSin, nx, nz, x, y, z;

            Vector2 min = new Vector2(-uvRadius, -uvRadius);
            Vector2 max = new Vector2(uvRadius, uvRadius);
            Vector2 pos;
            Vector2 uv;

            //unchanging vars
            y = height + offset.y;

            for (int i = 0; i < numOfFaces + 1; i++)
            {
                rads = startRad + (radPerFace * i);
                xCos = Mathf.Cos(rads);
                zSin = Mathf.Sin(rads);
                x = xCos * radius + offset.x;
                z = zSin * radius + offset.z;
                nx = xCos * yCos;
                nz = zSin * yCos;
                pos = new Vector2(xCos * radius, zSin * radius);
                uv = area.getUV(min, max, pos);
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ySin, nz), uv));
            }
            return verts;
        }
예제 #18
0
 private void generatePanelSegment(MeshBuilder builder, Vector3 pos, Arc arcA, Arc arcB, UVArea area, bool invertFaces, bool invertNormalY, bool invertNormalXZ)
 {
     float heightDiff = arcB.height - arcA.height;
     float offset = arcA.radius - arcB.radius;
     float sideRadians = Mathf.Atan2(heightDiff, offset) - 90 * Mathf.Deg2Rad;
     float yCos = Mathf.Cos(sideRadians);
     float ySin = Mathf.Sin(sideRadians);
     if (invertNormalY) { ySin *= -1; }
     if (invertNormalXZ) { yCos *= -1; }
     List<Vertex> verts1 = new List<Vertex>();
     List<Vertex> verts2 = new List<Vertex>();
     verts1.AddRange(arcA.generateVertices(builder, pos, area, area.v1, yCos, ySin));
     verts2.AddRange(arcB.generateVertices(builder, pos, area, area.v2, yCos, ySin));
     builder.generateQuads(verts1, verts2, invertFaces);
 }
예제 #19
0
 public UVMap(ConfigNode node)
 {
     ConfigNode[] areaNodes = node.GetNodes("UVAREA");
     int len = areaNodes.Length;
     for (int i = 0; i < len; i++)
     {
         UVArea area = new UVArea(areaNodes[i]);
         uvAreas.Add(area.name, area);
     }
 }
예제 #20
0
        private void generateSidewalls(MeshBuilder builder, UVArea caps)
        {
            int len = outerArcs.Count;
            float[] distances = new float[len];
            float[] us = new float[len];
            float totalLength = 0;
            float length;
            Vector3 a, b;
            for (int i = 0; i < len - 1; i++)
            {
                a = outerArcs[i].startVector;
                b = outerArcs[i + 1].startVector;
                length = Vector3.Distance(a, b);
                totalLength += length;
                distances[i + 1] = length;
            }

            length = 0;
            float percent;
            float uDelta = caps.u2 - caps.u1;
            for (int i = 0; i < len; i++)
            {
                length += distances[i];
                percent = length / totalLength;
                us[i] = caps.u1 + percent * uDelta;
            }

            Vector3 leftNorm = new Vector3();
            leftNorm.x = outerArcs[0].startVector.z;
            leftNorm.z = -outerArcs[0].startVector.x;
            leftNorm.Normalize();
            Vector3 rightNorm = new Vector3();
            rightNorm.x = outerArcs[0].endVector.z;
            rightNorm.z = -outerArcs[0].endVector.x;
            rightNorm.Normalize();
            rightNorm = -rightNorm;//as faces get inverted for this side, so norms get inverted as well

            //left
            List<Vertex> outerStartVerts = new List<Vertex>();
            List<Vertex> innerStartVerts = new List<Vertex>();

            //right
            List<Vertex> outerEndVerts = new List<Vertex>();
            List<Vertex> innerEndVerts = new List<Vertex>();

            len = outerArcs.Count;
            Vector3 outer, inner;
            Vector2 uv;
            for (int i = 0; i < len; i++)
            {
                outer = outerArcs[i].startVector;
                uv = new Vector2(us[i], caps.v1);
                outerStartVerts.Add(builder.addVertex(outer, leftNorm, uv));
                inner = innerArcs[i].startVector;
                uv = new Vector2(us[i], caps.v2);
                innerStartVerts.Add(builder.addVertex(inner, leftNorm, uv));

                outer = outerArcs[i].endVector;
                uv = new Vector2(us[i], caps.v1);
                outerEndVerts.Add(builder.addVertex(outer, rightNorm, uv));
                inner = innerArcs[i].endVector;
                uv = new Vector2(us[i], caps.v2);
                innerEndVerts.Add(builder.addVertex(inner, rightNorm, uv));
            }
            builder.generateQuads(outerStartVerts, innerStartVerts, false);
            builder.generateQuads(outerEndVerts, innerEndVerts, true);
        }
예제 #21
0
        public List<Vertex> generateRadialVerticesFlatUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, float v, UVArea area, float yCos, float ySin)
        {
            List<Vertex> verts = new List<Vertex>();
            float totalAngle = endAngle - startAngle;
            float anglePerFace = 360f / faces;
            int numOfFaces = (int)(totalAngle / anglePerFace);

            float anglePerVert = totalAngle / (float)(numOfFaces + 1);

            float angle, xCos, zSin, nx, ny, nz, x, y, z, percentTotalAngle;

            for (int i = 0; i < numOfFaces + 1; i++)
            {
                angle = startAngle + anglePerFace * i;
                percentTotalAngle = (angle - startAngle) / totalAngle;

                xCos = Mathf.Cos(angle * Mathf.Deg2Rad);
                zSin = Mathf.Sin(angle * Mathf.Deg2Rad);
                x = xCos * radius + offset.x;
                y = height + offset.y;
                z = zSin * radius + offset.z;
                nx = xCos * yCos;
                ny = ySin;
                nz = zSin * yCos;
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ny, nz), new Vector2(area.getU(percentTotalAngle), v)));
            }
            return verts;
        }
예제 #22
0
        public void generateCylinderCap(Vector3 offset, int faces, float outerRadius, float innerRadius, float height, float startAngle, float endAngle, UVArea area, bool bottomCap)
        {
            float         ySin       = bottomCap ? -1 : 1;
            List <Vertex> outerVerts = generateRadialVerticesCylinderUVs(offset, faces, outerRadius, height, startAngle, endAngle, area, outerRadius, 0, ySin);

            if (innerRadius > 0)//partial cap
            {
                List <Vertex> innerVerts = generateRadialVerticesCylinderUVs(offset, faces, innerRadius, height, startAngle, endAngle, area, outerRadius, 0, ySin);
                generateQuads(outerVerts, innerVerts, bottomCap);
            }
            else
            {
                Vector2 min      = new Vector2(-outerRadius, -outerRadius);
                Vector2 max      = new Vector2(outerRadius, outerRadius);
                Vector2 centerUV = area.getUV(min, max, new Vector2(0, 0));
                Vertex  center   = addVertex(offset + new Vector3(0, height, 0), bottomCap ? Vector3.down : Vector3.up, centerUV);
                generateTriangleFan(outerVerts, center, bottomCap);
            }
        }
예제 #23
0
 public void generateCylinderCap(Vector3 offset, int faces, float outerRadius, float innerRadius, float height, float startAngle, float endAngle, UVArea area, bool bottomCap)
 {
     float ySin = bottomCap ? -1 : 1;
     List<Vertex> outerVerts = generateRadialVerticesCylinderUVs(offset, faces, outerRadius, height, startAngle, endAngle, area, outerRadius, 0, ySin);
     if (innerRadius > 0)//partial cap
     {
         List<Vertex> innerVerts = generateRadialVerticesCylinderUVs(offset, faces, innerRadius, height, startAngle, endAngle, area, outerRadius, 0, ySin);
         generateQuads(outerVerts, innerVerts, bottomCap);
     }
     else
     {
         Vector2 min = new Vector2(-outerRadius, -outerRadius);
         Vector2 max = new Vector2(outerRadius, outerRadius);
         Vector2 centerUV = area.getUV(min, max, new Vector2(0, 0));
         Vertex center = addVertex(offset + new Vector3(0, height, 0), bottomCap ? Vector3.down : Vector3.up, centerUV);
         generateTriangleFan(outerVerts, center, bottomCap);
     }
 }
예제 #24
0
        /// <summary>
        /// Generates a ring of vertices using circular UV mapping, where the center of the ring is the center of the UV area.
        /// This would be used to generate a partial ring, such as the procedural decoupler
        /// Input radius is the radius of the actual ring, uvRadius is the radius to be used for maximal UV bounds
        /// (e.g. they will only be different on an inner-ring; where radius=ring radius, and uvRadius = outerRingRadius)
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="faces"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="area">The UV area to map the UV vertex to.</param>
        /// <param name="uvRadius">The radius to be used for the UV area, in case it differs from the radius in use (basically scales the UV area)</param>
        /// <param name="yCos">Determines the x/z normal component</param>
        /// <param name="ySin">Used directly as the y normal component</param>
        /// <returns></returns>
        public List <Vertex> generateRadialVerticesCylinderUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, UVArea area, float uvRadius, float yCos, float ySin)
        {
            List <Vertex> verts      = new List <Vertex>();
            float         startRad   = startAngle * Mathf.Deg2Rad;
            float         endRad     = endAngle * Mathf.Deg2Rad;
            float         totalRad   = endRad - startRad;
            float         radPerFace = (2f * Mathf.PI) / faces;
            //int numOfFaces = (int)(totalRad / radPerFace);
            int   numOfFaces = (int)Math.Round(totalRad / radPerFace, 0);
            float rads, xCos, zSin, nx, nz, x, y, z;

            Vector2 min = new Vector2(-uvRadius, -uvRadius);
            Vector2 max = new Vector2(uvRadius, uvRadius);
            Vector2 pos;
            Vector2 uv;

            //unchanging vars
            y = height + offset.y;

            for (int i = 0; i < numOfFaces + 1; i++)
            {
                rads = startRad + (radPerFace * i);
                xCos = Mathf.Cos(rads);
                zSin = Mathf.Sin(rads);
                x    = xCos * radius + offset.x;
                z    = zSin * radius + offset.z;
                nx   = xCos * yCos;
                nz   = zSin * yCos;
                pos  = new Vector2(xCos * radius, zSin * radius);
                uv   = area.getUV(min, max, pos);
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ySin, nz), uv));
            }
            return(verts);
        }
        protected void generateFairingWallSection(MeshGenerator gen, UVArea capUV, UVArea panelUV, float startY, float totalHeight, float maxHeightPerPanel, float boltPanelHeight, float topRadius, float bottomRadius, int sides, float anglePerSide, float startAngle, bool outsideWall)
        {
            UVArea capUVCopy = new UVArea(capUV);
            UVArea panelUVCopy = new UVArea(panelUV);
            Vector2 start = new Vector2(bottomRadius, startY);//1.25, 0
            Vector2 topOffset = new Vector2(topRadius - bottomRadius, totalHeight);

            float vlen = topOffset.magnitude;
            float capPercent = boltPanelHeight / vlen;
            float fullPanelPercent = maxHeightPerPanel / vlen;
            float panelHeight = vlen - boltPanelHeight*2.0f;

            float height;
            Vector2 pBottom;
            Vector2 pTop;

            if(boltPanelHeight>0)
            {
                //generate caps
                float capVHeight = capUV.v2 - capUV.v1;
                float capVScale = capVHeight / boltPanelHeight;
                float capU = (bottomOuterCirc / (float)this.numOfPanels) * capVScale;
                capUVCopy.u2 = capU;

                //top cap
                pBottom = start;
                pTop = start + (topOffset * capPercent);
                height = pTop.y - pBottom.y;
                gen.setUVArea(capUVCopy);
                gen.generateCylinderWallSection(centerX, centerZ, pBottom.y, height, pTop.x, pBottom.x, sides, anglePerSide, startAngle, outsideWall);

                capU = (topOuterCirc / (float)this.numOfPanels) * capVScale;
                capUVCopy.u2 = capU;
                //bottom cap
                pBottom = start + topOffset - (topOffset*capPercent);
                pTop = start + topOffset;
                height = pTop.y - pBottom.y;
                gen.setUVArea(capUVCopy);
                gen.generateCylinderWallSection(centerX, centerZ, pBottom.y, height, pTop.x, pBottom.x, sides, anglePerSide, startAngle, outsideWall);
            }

            //generate panels
            //setup UV scaling for full height panels
            float panelVHeight = panelUV.v2 - panelUV.v1;
            float panelVScale = panelVHeight / maxHeightPerPanel;
            float panelU = (bottomOuterCirc / (float)this.numOfPanels) * panelVScale;
            panelUVCopy.u2 = panelU;//scale the u2 coordinate (right-hand extent) by the scale factor, to setup a 1:1 texture ratio across the panel

            gen.setUVArea(panelUVCopy);
            // modulus operation to get the whole and remainder
            float extraPanelHeight = panelHeight / maxHeightPerPanel;
            int numOfVerticalSections = (int)extraPanelHeight;
            extraPanelHeight-=numOfVerticalSections;

            pBottom = start + (topOffset * capPercent);
            for(int i = 0; i<numOfVerticalSections; i++)//generate full panels
            {
                pTop = pBottom + (fullPanelPercent * topOffset);
                height = pTop.y - pBottom.y;
                gen.generateCylinderWallSection(centerX, centerZ, pBottom.y, height, pTop.x, pBottom.x, sides, anglePerSide, startAngle, outsideWall);
                //increment for next full panel
                pBottom = pTop;
            }
            if(extraPanelHeight>0)//gen extra partial panel if needed
            {
                //gen 'extra' panel
                //setup UV scaling for partial height panel, both u and V;
                panelVHeight = panelUV.v2 - panelUV.v1;
                panelVScale = panelVHeight / maxHeightPerPanel;
                panelU = (bottomOuterCirc / (float)this.numOfPanels) * panelVScale;
                panelUVCopy.u2 = panelU;//scale u area
                float panelV = panelUVCopy.v1 + panelVScale * extraPanelHeight;
                panelUVCopy.v2 = panelV;//scale v area

                float extraPanelPercent = extraPanelHeight / vlen;
                pTop = pBottom + (extraPanelPercent * topOffset);
                height = pTop.y - pBottom.y;
                gen.setUVArea(panelUVCopy);
                gen.generateCylinderWallSection(centerX, centerZ, pBottom.y, height, pTop.x, pBottom.x, sides, anglePerSide, startAngle, outsideWall);
            }
        }
예제 #26
0
        /// <summary>
        /// Used to generate a ring of vertices with the uvMapping appropriate for a cylinder wall (increments in +x)
        /// </summary>
        /// <param name="offset"></param>
        /// <param name="faces"></param>
        /// <param name="radius"></param>
        /// <param name="height"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="v"></param>
        /// <param name="area"></param>
        /// <param name="yCos"></param>
        /// <param name="ySin"></param>
        /// <returns></returns>
        public List <Vertex> generateRadialVerticesFlatUVs(Vector3 offset, int faces, float radius, float height, float startAngle, float endAngle, float v, UVArea area, float yCos, float ySin)
        {
            List <Vertex> verts      = new List <Vertex>();
            float         startRad   = startAngle * Mathf.Deg2Rad;
            float         endRad     = endAngle * Mathf.Deg2Rad;
            float         totalRad   = endRad - startRad;
            float         radPerFace = (float)((2.0 * Math.PI) / faces);
            float         radPerSub  = radPerFace / subdivision;
            int           numOfFaces = (int)Math.Round(totalRad / radPerFace, 0);

            float rads, xCos, zSin, nx, ny, nz, x, y, z, percentTotalAngle;
            float subRads, x2 = 0, z2 = 0, x3, z3, xCos2 = 0, zSin2 = 0, nextRads = 0, nextPerc = 0, subPerc, lerp;

            y  = height + offset.y;
            ny = ySin;

            for (int i = 0; i < numOfFaces + 1; i++)
            {
                if (i > 0)//vars were caled last round for the interpolation
                {
                    rads = nextRads;
                    percentTotalAngle = nextPerc;
                    xCos = xCos2;
                    zSin = zSin2;
                    x    = x2;
                    z    = z2;
                }
                else
                {
                    rads = startRad + (radPerFace * i);
                    percentTotalAngle = (rads - startRad) / totalRad;
                    xCos = Mathf.Cos(rads);
                    zSin = Mathf.Sin(rads);
                    x    = xCos * radius + offset.x;
                    z    = zSin * radius + offset.z;
                }

                nx = xCos * yCos;
                nz = zSin * yCos;
                verts.Add(addVertex(new Vector3(x, y, z), new Vector3(nx, ny, nz), new Vector2(area.getU(percentTotalAngle), v)));

                //calculate the points/etc for the next panel face, to lerp between positions; data is re-used next iteration if present
                nextRads = startRad + (radPerFace * (i + 1));
                nextPerc = (nextRads - startRad) / totalRad;
                xCos2    = Mathf.Cos(nextRads);
                zSin2    = Mathf.Sin(nextRads);
                x2       = xCos2 * radius + offset.x;
                z2       = zSin2 * radius + offset.z;

                //do not add subdivision panel if the next vertex is the last one in the ring
                if (i == numOfFaces)
                {
                    break;
                }
                //if was the last vert... do not add subs
                for (int k = 1; k < subdivision; k++)
                {
                    lerp    = (float)k / subdivision;
                    x3      = Mathf.Lerp(x, x2, lerp);
                    z3      = Mathf.Lerp(z, z2, lerp);
                    subRads = rads + (radPerSub * k);//subangle used for normal calc... position calculated from interpolation to maintain cylinder side matching
                    subPerc = (subRads - startRad) / totalRad;
                    xCos    = Mathf.Cos(subRads);
                    zSin    = Mathf.Sin(subRads);
                    nx      = xCos * yCos;
                    nz      = zSin * yCos;
                    verts.Add(addVertex(new Vector3(x3, y, z3), new Vector3(nx, ny, nz), new Vector2(area.getU(subPerc), v)));
                }
            }
            return(verts);
        }