internal Mesh GetMesh(Table.Table table, int acc = -1, bool createHitShape = false) { var mesh = new Mesh(_data.Name); const int accuracy = (int)(10.0f * 1.2f); // see also above var splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f; var sv = new SplineVertex(_data.DragPoints, _data.Thickness, table.GetDetailLevel(), (int)splineAccuracy); var numRings = sv.VertexCount - 1; var numSegments = accuracy; var numVertices = numRings * numSegments; var numIndices = 6 * numVertices; //m_numVertices*2+2; var height = _data.HitHeight + table.TableHeight; mesh.Vertices = new Vertex3DNoTex2[numVertices]; mesh.Indices = new int[numIndices]; var prevB = new Vertex3D(); var invNr = 1.0f / numRings; var invNs = 1.0f / numSegments; var index = 0; for (var i = 0; i < numRings; i++) { var i2 = i == numRings - 1 ? 0 : i + 1; var tangent = new Vertex3D(sv.MiddlePoints[i2].X - sv.MiddlePoints[i].X, sv.MiddlePoints[i2].Y - sv.MiddlePoints[i].Y, 0.0f); Vertex3D biNormal; Vertex3D normal; if (i == 0) { var up = new Vertex3D(sv.MiddlePoints[i2].X + sv.MiddlePoints[i].X, sv.MiddlePoints[i2].Y + sv.MiddlePoints[i].Y, height * 2.0f); normal = new Vertex3D(tangent.Y * up.Z, -tangent.X * up.Z, tangent.X * up.Y - tangent.Y * up.X); // = CrossProduct(tangent, up) biNormal = new Vertex3D(tangent.Y * normal.Z, -tangent.X * normal.Z, tangent.X * normal.Y - tangent.Y * normal.X); // = CrossProduct(tangent, normal) } else { normal = prevB.Clone().Cross(tangent); biNormal = tangent.Clone().Cross(normal); } biNormal.Normalize(); normal.Normalize(); prevB = biNormal; var u = i * invNr; for (var j = 0; j < numSegments; j++) { var v = ((float)j + u) * invNs; var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNs), tangent, normal) .MultiplyScalar(_data.Thickness * 0.5f); mesh.Vertices[index] = new Vertex3DNoTex2 { X = sv.MiddlePoints[i].X + tmp.X, Y = sv.MiddlePoints[i].Y + tmp.Y }; if (createHitShape && (j == 0 || j == 3)) { //!! hack, adapt if changing detail level for hitshape // for a hit shape create a more rectangle mesh and not a smooth one tmp.Z *= 0.6f; } mesh.Vertices[index].Z = height + tmp.Z; //texel mesh.Vertices[index].Tu = u; mesh.Vertices[index].Tv = v; index++; } } // calculate faces for (var i = 0; i < numRings; i++) { for (var j = 0; j < numSegments; j++) { var quad = new int[4]; quad[0] = i * numSegments + j; if (j != numSegments - 1) { quad[1] = i * numSegments + j + 1; } else { quad[1] = i * numSegments; } if (i != numRings - 1) { quad[2] = (i + 1) * numSegments + j; if (j != numSegments - 1) { quad[3] = (i + 1) * numSegments + j + 1; } else { quad[3] = (i + 1) * numSegments; } } else { quad[2] = j; if (j != numSegments - 1) { quad[3] = j + 1; } else { quad[3] = 0; } } mesh.Indices[(i * numSegments + j) * 6] = quad[0]; mesh.Indices[(i * numSegments + j) * 6 + 1] = quad[1]; mesh.Indices[(i * numSegments + j) * 6 + 2] = quad[2]; mesh.Indices[(i * numSegments + j) * 6 + 3] = quad[3]; mesh.Indices[(i * numSegments + j) * 6 + 4] = quad[2]; mesh.Indices[(i * numSegments + j) * 6 + 5] = quad[1]; } } Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, numIndices); var maxX = Constants.FloatMin; var minX = Constants.FloatMax; var maxY = Constants.FloatMin; var minY = Constants.FloatMax; var maxZ = Constants.FloatMin; var minZ = Constants.FloatMax; for (var i = 0; i < numVertices; i++) { if (maxX < mesh.Vertices[i].X) { maxX = mesh.Vertices[i].X; } if (minX > mesh.Vertices[i].X) { minX = mesh.Vertices[i].X; } if (maxY < mesh.Vertices[i].Y) { maxY = mesh.Vertices[i].Y; } if (minY > mesh.Vertices[i].Y) { minY = mesh.Vertices[i].Y; } if (maxZ < mesh.Vertices[i].Z) { maxZ = mesh.Vertices[i].Z; } if (minZ > mesh.Vertices[i].Z) { minZ = mesh.Vertices[i].Z; } } MiddlePoint.X = (maxX + minX) * 0.5f; MiddlePoint.Y = (maxY + minY) * 0.5f; MiddlePoint.Z = (maxZ + minZ) * 0.5f; return(mesh); }
private Vertex3DNoTex2[] CreateWire(int numRings, int numSegments, IReadOnlyList <Vertex2D> midPoints, IReadOnlyList <float> initialHeights) { var vertices = new Vertex3DNoTex2[numRings * numSegments]; var prev = new Vertex3D(); var index = 0; for (var i = 0; i < numRings; i++) { var i2 = i == numRings - 1 ? i : i + 1; var height = initialHeights[i]; var tangent = new Vertex3D( midPoints[i2].X - midPoints[i].X, midPoints[i2].Y - midPoints[i].Y, initialHeights[i2] - initialHeights[i] ); if (i == numRings - 1) { // for the last spline point use the previous tangent again, otherwise we won't see the complete wire (it stops one control point too early) tangent.X = midPoints[i].X - midPoints[i - 1].X; tangent.Y = midPoints[i].Y - midPoints[i - 1].Y; } Vertex3D biNormal; Vertex3D normal; if (i == 0) { var up = new Vertex3D( midPoints[i2].X + midPoints[i].X, midPoints[i2].Y + midPoints[i].Y, initialHeights[i2] - height ); normal = Vertex3D.CrossProduct(tangent, up); //normal biNormal = Vertex3D.CrossProduct(tangent, normal); } else { normal = Vertex3D.CrossProduct(prev, tangent); biNormal = Vertex3D.CrossProduct(tangent, normal); } biNormal.Normalize(); normal.Normalize(); prev = biNormal; var invNumRings = 1.0f / numRings; var invNumSegments = 1.0f / numSegments; var u = i * invNumRings; for (var j = 0; j < numSegments; j++, index++) { var v = (j + u) * invNumSegments; var tmp = Vertex3D.GetRotatedAxis(j * (360.0f * invNumSegments), tangent, normal) * (_data.WireDiameter * 0.5f); vertices[index] = new Vertex3DNoTex2 { X = midPoints[i].X + tmp.X, Y = midPoints[i].Y + tmp.Y, Z = height + tmp.Z, Tu = u, Tv = v }; // normals var n = new Vertex3D( vertices[index].X - midPoints[i].X, vertices[index].Y - midPoints[i].Y, vertices[index].Z - height ); var len = 1.0f / MathF.Sqrt(n.X * n.X + n.Y * n.Y + n.Z * n.Z); vertices[index].Nx = n.X * len; vertices[index].Ny = n.Y * len; vertices[index].Nz = n.Z * len; } } return(vertices); }