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);
        }
Пример #2
0
        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);
        }