public UVArea getArea(string name) { UVArea a = null; uvAreas.TryGetValue(name, out a); return(a); }
public UVArea(UVArea input) { this.u1 = input.u1; this.u2 = input.u2; this.v1 = input.v1; this.v2 = input.v2; }
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; }
public void setUVArea(UVArea area) { this.u1 = area.u1; this.u2 = area.u2; this.v1 = area.v1; this.v2 = area.v2; }
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); }
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); } }
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); }
/// <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; }
/// <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; }
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(); }
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(); }
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); }
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); }
/// <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; }
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); }
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); }
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; }
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); } }
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); } }
/// <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); } }
/// <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); }