/// <summary> /// Create a mesh for a RoundLine. /// </summary> /// <remarks> /// The RoundLine mesh has 3 sections: /// 1. Two quads, from 0 to 1 (left to right) /// 2. A half-disc, off the left side of the quad /// 3. A half-disc, off the right side of the quad /// /// The X and Y coordinates of the "normal" encode the rho and theta of each vertex /// The "texture" encodes whether to scale and translate the vertex horizontally by length and radius /// </remarks> private void CreateRoundLineMesh() { const int primsPerCap = 6; // A higher primsPerCap produces rounder endcaps at the cost of more vertices const int verticesPerCap = primsPerCap * 2 + 2; const int primsPerCore = 4; const int verticesPerCore = 8; numVertices = (verticesPerCore + verticesPerCap + verticesPerCap) * LinesPerBatch; numPrimitivesPerInstance = primsPerCore + primsPerCap + primsPerCap; numPrimitives = numPrimitivesPerInstance * LinesPerBatch; numIndices = 3 * numPrimitives; short[] indices = new short[numIndices]; RoundLineVertex[] tri = new RoundLineVertex[numVertices]; int iv = 0; int ii = 0; int iVertex; int iIndex; for (int instance = 0; instance < LinesPerBatch; instance++) { // core vertices const float pi2 = MathHelper.PiOver2; const float threePi2 = 3 * pi2; iVertex = iv; tri[iv++] = new RoundLineVertex(new Vector3(0.0f, -1.0f, 0), new Vector2(1, threePi2), new Vector2(0, 0), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, -1.0f, 0), new Vector2(1, threePi2), new Vector2(0, 1), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 0.0f, 0), new Vector2(0, threePi2), new Vector2(0, 1), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 0.0f, 0), new Vector2(0, threePi2), new Vector2(0, 0), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 0.0f, 0), new Vector2(0, pi2), new Vector2(0, 1), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 0.0f, 0), new Vector2(0, pi2), new Vector2(0, 0), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 1.0f, 0), new Vector2(1, pi2), new Vector2(0, 1), instance); tri[iv++] = new RoundLineVertex(new Vector3(0.0f, 1.0f, 0), new Vector2(1, pi2), new Vector2(0, 0), instance); // core indices indices[ii++] = (short)(iVertex + 0); indices[ii++] = (short)(iVertex + 1); indices[ii++] = (short)(iVertex + 2); indices[ii++] = (short)(iVertex + 2); indices[ii++] = (short)(iVertex + 3); indices[ii++] = (short)(iVertex + 0); indices[ii++] = (short)(iVertex + 4); indices[ii++] = (short)(iVertex + 6); indices[ii++] = (short)(iVertex + 5); indices[ii++] = (short)(iVertex + 6); indices[ii++] = (short)(iVertex + 7); indices[ii++] = (short)(iVertex + 5); // left halfdisc iVertex = iv; iIndex = ii; for (int i = 0; i < primsPerCap + 1; i++) { float deltaTheta = MathHelper.Pi / primsPerCap; float theta0 = MathHelper.PiOver2 + i * deltaTheta; float theta1 = theta0 + deltaTheta / 2; // even-numbered indices are at the center of the halfdisc tri[iVertex + 0] = new RoundLineVertex(new Vector3(0, 0, 0), new Vector2(0, theta1), new Vector2(0, 0), instance); // odd-numbered indices are at the perimeter of the halfdisc float x = (float)Math.Cos(theta0); float y = (float)Math.Sin(theta0); tri[iVertex + 1] = new RoundLineVertex(new Vector3(x, y, 0), new Vector2(1, theta0), new Vector2(1, 0), instance); if (i < primsPerCap) { // indices follow this pattern: (0, 1, 3), (2, 3, 5), (4, 5, 7), ... indices[iIndex + 0] = (short)(iVertex + 0); indices[iIndex + 1] = (short)(iVertex + 1); indices[iIndex + 2] = (short)(iVertex + 3); iIndex += 3; ii += 3; } iVertex += 2; iv += 2; } // right halfdisc for (int i = 0; i < primsPerCap + 1; i++) { float deltaTheta = MathHelper.Pi / primsPerCap; float theta0 = 3 * MathHelper.PiOver2 + i * deltaTheta; float theta1 = theta0 + deltaTheta / 2; float theta2 = theta0 + deltaTheta; // even-numbered indices are at the center of the halfdisc tri[iVertex + 0] = new RoundLineVertex(new Vector3(0, 0, 0), new Vector2(0, theta1), new Vector2(0, 1), instance); // odd-numbered indices are at the perimeter of the halfdisc float x = (float)Math.Cos(theta0); float y = (float)Math.Sin(theta0); tri[iVertex + 1] = new RoundLineVertex(new Vector3(x, y, 0), new Vector2(1, theta0), new Vector2(1, 1), instance); if (i < primsPerCap) { // indices follow this pattern: (0, 1, 3), (2, 3, 5), (4, 5, 7), ... indices[iIndex + 0] = (short)(iVertex + 0); indices[iIndex + 1] = (short)(iVertex + 1); indices[iIndex + 2] = (short)(iVertex + 3); iIndex += 3; ii += 3; } iVertex += 2; iv += 2; } } vb = new VertexBuffer(device, RoundLineVertex.VertexDeclaration, numVertices, BufferUsage.WriteOnly); vb.SetData(tri); ib = new IndexBuffer(device, IndexElementSize.SixteenBits, numIndices, BufferUsage.WriteOnly); ib.SetData(indices); }