コード例 #1
0
        /// <summary>
        /// Creates an array of Sonic Heroes native spline vertices from a supplied parsed OBJ file.
        /// </summary>
        /// <param name="parser">An instance of the OBJ parser containing spline points as its list of vertices.</param>
        /// <returns>List of processed spline vertices.</returns>
        private static       SplineVertex[] MakeSplineVertices(ref ObjParser parser)
        {
            // Generate list of vertices for spline.
            var vertices = new SplineVertex[parser.Vertices.Count];

            for (int x = 0; x < parser.Vertices.Count; x++)
            {
                vertices[x] = new SplineVertex(parser.Vertices[x]);
            }

            // Calculate total spline length.
            int loopMaximum = vertices.Length - 1;

            // Set distance to each next vertex.
            for (int x = 0; x < loopMaximum; x++)
            {
                vertices[x].DistanceToNextVertex = vertices[x].CalculateDistanceToNext(vertices[x + 1]);
            }

            return(vertices);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        private Mesh GetMesh(float playfieldHeight, float meshHeight, int detailLevel, int acc = -1, bool createHitShape = false, float margin = 0f)
        {
            var mesh = new Mesh();
            // i dont understand the calculation of splineaccuracy here /cupiii
            var accuracy = (int)(10.0f * 1.2f);

            if (acc != -1)
            {             // hit shapes and UI display have the same, static, precision
                accuracy = acc;
            }

            var          splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f;
            SplineVertex sv             = new SplineVertex(_data.DragPoints, (int)(_data.Thickness + 0.5), detailLevel, splineAccuracy, margin: margin, loop: true);

            var height = playfieldHeight + meshHeight;


            // one ring for each Splinevertex

            var numRings    = sv.VertexCount;
            var numSegments = accuracy;

            var up        = new Vertex3D(0f, 0f, 1f);
            var points    = new Vertex3D[numRings];        // middlepoints of rings
            var tangents  = new Vertex3D[numRings];        // pointing into the direction of the spline, even first and last
            var right     = new Vertex3D[numRings];        // pointing right, looking into tangent direction
            var down      = new Vertex3D[numRings];        // pointing down from tangent view
            var accLength = new float[numRings];           // accumulated length of the wire beginning at 0;

            // copy the data from the pline into the middle of the new variables
            for (int i = 0; i < sv.VertexCount; i++)
            {
                points[i] = new Vertex3D(sv.MiddlePoints[i].X, sv.MiddlePoints[i].Y, height);
                right[i]  = new Vertex3D(sv.RgvLocal[i].X - sv.MiddlePoints[i].X, sv.RgvLocal[i].Y - sv.MiddlePoints[i].Y, 0f);
                right[i].Normalize();
                tangents[i] = Vertex3D.CrossProduct(right[i], new Vertex3D(0f, 0f, 1f));
                tangents[i].Normalize();
            }

            // calculate downvectors
            for (int i = 0; i < numRings; i++)
            {
                down[i] = Vertex3D.CrossProduct(right[i], tangents[i]);
                down[i].Normalize();
            }

            // For UV calculation we need the whole length of the rubber
            accLength[0] = 0.0f;
            for (int i = 1; i < numRings; i++)
            {
                accLength[i] = accLength[i - 1] + (points[i] - points[i - 1]).Length();
            }
            // add the lenth from the last ring to the first ring
            var totalLength = accLength[numRings - 1] + (points[0] - points[numRings - 1]).Length();;

            var numVertices = (numRings + 1) * numSegments;
            var numIndices  = numRings * numSegments * 6;

            mesh.Vertices = new Vertex3DNoTex2[numVertices];
            mesh.Indices  = new int[numIndices];

            // precalculate the rings (positive X is left, positive Y is up) Starting at the bottom clockwise (X=0, Y=1)
            var ringsX = new float[numSegments];
            var ringsY = new float[numSegments];

            for (int i = 0; i < numSegments; i++)
            {
                ringsX[i] = -1.0f * (float)System.Math.Sin(System.Math.PI * 2 * i / numSegments) * _data.Thickness;
                ringsY[i] = -1.0f * (float)System.Math.Cos(System.Math.PI + System.Math.PI * 2 * i / numSegments) * _data.Thickness;
            }

            var verticesIndex = 0;
            var indicesIndex  = 0;

            // calculate Vertices first
            for (int currentRing = 0; currentRing < numRings; currentRing++)
            {
                // calculate one ring
                for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
                {
                    mesh.Vertices[verticesIndex++] = new Vertex3DNoTex2
                    {
                        X = points[currentRing].X + right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
                        Y = points[currentRing].Y + right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
                        Z = points[currentRing].Z + right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
                        //normals seem to be somehow off, but are caculated again at the end of mesh creation.
                        Nx = right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
                        Ny = right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
                        Nz = right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
                        Tu = accLength[currentRing] / totalLength,
                        Tv = (float)currentSegment / ((float)numSegments - 1)
                    };
                }


                // could be integrated in above for loop, but better to read and will be optimized anyway by compiler
                if (currentRing > 0)
                {
                    for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
                    {
                        var csp1 = currentSegment + 1;
                        if (csp1 >= numSegments)
                        {
                            csp1 = 0;
                        }
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + csp1;
                    }
                }
            }

            // copy first ring into last ring
            for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
            {
                mesh.Vertices[verticesIndex++] = new Vertex3DNoTex2
                {
                    X = points[0].X + right[0].X * ringsX[currentSegment] + down[0].X * ringsY[currentSegment],
                    Y = points[0].Y + right[0].Y * ringsX[currentSegment] + down[0].Y * ringsY[currentSegment],
                    Z = points[0].Z + right[0].Z * ringsX[currentSegment] + down[0].Z * ringsY[currentSegment],
                    //normals seem to be somehow off, but are caculated again at the end of mesh creation.
                    Nx = right[0].X * ringsX[currentSegment] + down[0].X * ringsY[currentSegment],
                    Ny = right[0].Y * ringsX[currentSegment] + down[0].Y * ringsY[currentSegment],
                    Nz = right[0].Z * ringsX[currentSegment] + down[0].Z * ringsY[currentSegment],
                    Tu = 1f,
                    Tv = (float)currentSegment / ((float)numSegments - 1)
                };
            }

            for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
            {
                var csp1 = currentSegment + 1;
                if (csp1 >= numSegments)
                {
                    csp1 = 0;
                }
                mesh.Indices[indicesIndex++] = (numRings - 1) * numSegments + currentSegment;
                mesh.Indices[indicesIndex++] = (numRings) * numSegments + currentSegment;
                mesh.Indices[indicesIndex++] = (numRings) * numSegments + csp1;
                mesh.Indices[indicesIndex++] = (numRings - 1) * numSegments + currentSegment;
                mesh.Indices[indicesIndex++] = (numRings) * numSegments + csp1;
                mesh.Indices[indicesIndex++] = (numRings - 1) * numSegments + csp1;
            }

            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++)
            {
                MathF.Max(maxX, mesh.Vertices[i].X);
                MathF.Max(maxY, mesh.Vertices[i].Y);
                MathF.Max(maxZ, mesh.Vertices[i].Z);
                MathF.Min(minX, mesh.Vertices[i].X);
                MathF.Min(minY, mesh.Vertices[i].X);
                MathF.Min(minZ, mesh.Vertices[i].X);
            }

            _middlePoint.X = (maxX + minX) * 0.5f;
            _middlePoint.Y = (maxY + minY) * 0.5f;
            _middlePoint.Z = (maxZ + minZ) * 0.5f;

            return(mesh);
        }
コード例 #4
0
        private Mesh GetMesh(float playfieldHeight, float meshHeight, int detailLevel, float bendradius, int acc = -1, bool createHitShape = false, float margin = 0f)
        {
            var mesh = new Mesh();
            // i dont understand the calculation of splineaccuracy here /cupiii
            var accuracy = (int)(10.0f * 1.2f);

            if (acc != -1)               // hit shapes and UI display have the same, static, precision
            {
                accuracy = acc;
            }

            var          splineAccuracy = acc != -1 ? 4.0f * MathF.Pow(10.0f, (10.0f - PhysicsConstants.HitShapeDetailLevel) * (float)(1.0 / 1.5)) : -1.0f;
            SplineVertex sv             = new SplineVertex(_data.DragPoints, (int)(_data.Thickness + 0.5), detailLevel, splineAccuracy, margin: margin, loop: false);

            var height = playfieldHeight + meshHeight;

            var standheight = _data.Standheight;

            // dont lat the Collider be higher than the visible mesh, just shift the top of the MWG.
            if (createHitShape)
            {
                standheight = standheight - _data.Height + height;
            }


            // one ring for each Splinevertex, two for the stands, and "bendradius" tomes two for the bend (should be enough)
            // todo: could be better, if accuracy was taken into account
            var numRingsInBend = (int)(bendradius + 1);
            var numRings       = sv.VertexCount - 1 + numRingsInBend * 2 + 2;
            var numSegments    = accuracy;

            var up        = new Vertex3D(0f, 0f, 1f);
            var points    = new Vertex3D[numRings];        // middlepoints of rings
            var tangents  = new Vertex3D[numRings];        // pointing into the direction of the spline, even first and last
            var right     = new Vertex3D[numRings];        // pointing right, looking into tangent direction
            var down      = new Vertex3D[numRings];        // pointing down from tangent view
            var accLength = new float[numRings];           // accumulated length of the wire beginning at 0;

            // copy the data from the pline into the middle of the new variables
            for (int i = 0; i < sv.VertexCount - 1; i++)
            {
                points[i + numRingsInBend + 1] = new Vertex3D(sv.MiddlePoints[i].X, sv.MiddlePoints[i].Y, height);
                right[i + numRingsInBend + 1]  = new Vertex3D(sv.RgvLocal[i].X - sv.MiddlePoints[i].X, sv.RgvLocal[i].Y - sv.MiddlePoints[i].Y, 0f);
                right[i + numRingsInBend + 1].Normalize();
                tangents[i + numRingsInBend + 1] = Vertex3D.CrossProduct(right[i + numRingsInBend + 1], new Vertex3D(0f, 0f, 1f));
                tangents[i + numRingsInBend + 1].Normalize();
            }

            // first set up beginning of the stand
            points[0]   = points[numRingsInBend + 1] + tangents[numRingsInBend + 1] * bendradius * -1 + up * standheight * -1f;
            tangents[0] = new Vertex3D(0f, 0f, 1f);
            right[0]    = right[numRingsInBend + 1];
            // set up the first point of the bend
            points[1]   = points[numRingsInBend + 1] + tangents[numRingsInBend + 1] * bendradius * -1 + up * bendradius * -1f;
            tangents[1] = tangents[0];
            right[1]    = right[0];
            // now bend from point 1 to numRingsInBend+1(-1)
            var diffXY = points[numRingsInBend + 1] - points[1];

            diffXY.Z = 0;
            var diffZ = points[numRingsInBend + 1] - points[1];

            diffZ.X = 0;
            diffZ.Y = 0;
            for (int i = 1; i < (numRingsInBend + 1); i++)
            {
                points[numRingsInBend - i + 1] = points[1] + diffXY - (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * diffXY + (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) * diffZ;
                var tmp = tangents[numRingsInBend + 1];
                tmp.Normalize();
                tangents[numRingsInBend - i + 1] = tmp * (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) + (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * up;
                right[numRingsInBend - i + 1]    = right[0];
            }
            // set up last point
            points[numRings - 1]   = points[(numRings - 1) - numRingsInBend - 1] + tangents[numRings - 1 - numRingsInBend - 1] * bendradius + up * standheight * -1f;
            tangents[numRings - 1] = new Vertex3D(0f, 0f, -1f);
            right[numRings - 1]    = right[(numRings - 1) - numRingsInBend - 1];
            // and the point before
            points[numRings - 2]   = points[(numRings - 1) - numRingsInBend - 1] + tangents[numRings - 1 - numRingsInBend - 1] * bendradius + up * bendradius * -1f;
            tangents[numRings - 2] = tangents[numRings - 1];
            right[numRings - 2]    = right[numRings - 1];
            // now bend again
            diffXY   = points[numRings - 1 - numRingsInBend - 1] - points[numRings - 2];
            diffXY.Z = 0;
            diffZ    = points[numRings - 1 - numRingsInBend - 1] - points[numRings - 2];
            diffZ.X  = 0;
            diffZ.Y  = 0;
            for (int i = 1; i < (numRingsInBend + 1); i++)
            {
                points[numRings - 2 - numRingsInBend + i] = points[numRings - 2] + diffXY - (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * diffXY + (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) * diffZ;
                var tmp = tangents[numRings - 1 - numRingsInBend - 1];
                tmp.Normalize();
                tangents[numRings - 2 - numRingsInBend + i] = tmp * (float)System.Math.Cos(System.Math.PI / 2 / numRingsInBend * i) + (float)System.Math.Sin(System.Math.PI / 2 / numRingsInBend * i) * up * -1;
                right[numRings - 2 - numRingsInBend + i]    = right[numRings - 1];
            }

            // calculate downvectors
            for (int i = 0; i < numRings; i++)
            {
                down[i] = Vertex3D.CrossProduct(right[i], tangents[i]);
                down[i].Normalize();
            }

            // For UV calculation we need the whole length of the wire
            accLength[0] = 0.0f;
            for (int i = 1; i < numRings; i++)
            {
                accLength[i] = accLength[i - 1] + (points[i] - points[i - 1]).Length();
            }
            var totalLength = accLength[numRings - 1];

            var numVertices = numRings * numSegments;
            var numIndices  = (numRings - 1) * numSegments * 6;

            mesh.Vertices = new Vertex3DNoTex2[numVertices];
            mesh.Indices  = new int[numIndices];

            // precalculate the rings (positive X is left, positive Y is up) Starting at the bottom clockwise (X=0, Y=1)
            var ringsX = new float[numSegments];
            var ringsY = new float[numSegments];

            for (int i = 0; i < numSegments; i++)
            {
                ringsX[i] = -1.0f * (float)System.Math.Sin(System.Math.PI * 2 * i / numSegments) * _data.Thickness;
                ringsY[i] = -1.0f * (float)System.Math.Cos(System.Math.PI + System.Math.PI * 2 * i / numSegments) * _data.Thickness;
            }

            var verticesIndex = 0;
            var indicesIndex  = 0;

            // calculate Vertices first
            for (int currentRing = 0; currentRing < numRings; currentRing++)
            {
                // calculate one ring
                for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
                {
                    mesh.Vertices[verticesIndex++] = new Vertex3DNoTex2
                    {
                        X = points[currentRing].X + right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
                        Y = points[currentRing].Y + right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
                        Z = points[currentRing].Z + right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
                        //normals seem to be somehow off, but are caculated again at the end of mesh creation.
                        Nx = right[currentRing].X * ringsX[currentSegment] + down[currentRing].X * ringsY[currentSegment],
                        Ny = right[currentRing].Y * ringsX[currentSegment] + down[currentRing].Y * ringsY[currentSegment],
                        Nz = right[currentRing].Z * ringsX[currentSegment] + down[currentRing].Z * ringsY[currentSegment],
                        Tu = accLength[currentRing] / totalLength,
                        Tv = (float)currentSegment / ((float)numSegments - 1)
                    };
                }


                // could be integrated in above for loop, but better to read and will be optimized anyway by compiler
                if (currentRing > 0)
                {
                    for (int currentSegment = 0; currentSegment < numSegments; currentSegment++)
                    {
                        var csp1 = currentSegment + 1;
                        if (csp1 >= numSegments)
                        {
                            csp1 = 0;
                        }
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + currentSegment;
                        mesh.Indices[indicesIndex++] = currentRing * numSegments + csp1;
                        mesh.Indices[indicesIndex++] = (currentRing - 1) * numSegments + csp1;
                    }
                }
            }

            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++)
            {
                MathF.Max(maxX, mesh.Vertices[i].X);
                MathF.Max(maxY, mesh.Vertices[i].Y);
                MathF.Max(maxZ, mesh.Vertices[i].Z);
                MathF.Min(minX, mesh.Vertices[i].X);
                MathF.Min(minY, mesh.Vertices[i].X);
                MathF.Min(minZ, mesh.Vertices[i].X);
            }

            _middlePoint.X = (maxX + minX) * 0.5f;
            _middlePoint.Y = (maxY + minY) * 0.5f;
            _middlePoint.Z = (maxZ + minZ) * 0.5f;

            return(mesh);
        }