cosmetics on ubder meshing

UbitUmarov [2022-10-23 20:10:36]
cosmetics on ubder meshing
Filename
OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
index 9dc372f..f5aa958 100644
--- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
+++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs
@@ -632,16 +632,11 @@ namespace OpenSim.Region.PhysicsModules.SharedBase
             get { return (int)m_actorType; }
             set {
                 ActorTypes type = (ActorTypes)value;
-                switch (type)
+                m_actorType = type switch
                 {
-                    case ActorTypes.Ground:
-                    case ActorTypes.Water:
-                        m_actorType = type;
-                        break;
-                    default:
-                        m_actorType = ActorTypes.Unknown;
-                        break;
-                }
+                    ActorTypes.Ground or ActorTypes.Water => type,
+                    _ => ActorTypes.Unknown,
+                };
             }
         }

diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
index 4c9a2cb..4210528 100644
--- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs
@@ -56,11 +56,11 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
         // Setting baseDir to a path will enable the dumping of raw files
         // raw files can be imported by blender so a visual inspection of the results can be done

-        const float floatPI = (float)Math.PI;
-        private static string cacheControlFilename = "cntr";
+        const float floatPI = MathF.PI;
+        private readonly static string cacheControlFilename = "cntr";
         private bool m_Enabled = false;

-        public static object diskLock = new object();
+        public static object diskLock = new();

         public bool doMeshFileCache = true;
         public bool doCacheExpire = true;
@@ -74,8 +74,8 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
         private bool doConvexPrims = true;
         private bool doConvexSculpts = true;

-        private Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new Dictionary<AMeshKey, Mesh>();
-        private Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new Dictionary<AMeshKey, Mesh>();
+        private readonly Dictionary<AMeshKey, Mesh> m_uniqueMeshes = new();
+        private readonly Dictionary<AMeshKey, Mesh> m_uniqueReleasedMeshes = new ();

        #region INonSharedRegionModule
         public string Name
@@ -196,7 +196,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             {
                 posRange = ((OSDMap)tmp)["Max"].AsVector3();
                 posMin = ((OSDMap)tmp)["Min"].AsVector3();
-                posRange = posRange - posMin;
+                posRange -= posMin;
                 posRange *= invMaxU16;
             }
             else
@@ -240,7 +240,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
                     ptr += 2;
                     int v3 = Utils.BytesToUInt16(ptr) + faceIndexOffset;
                     ptr += 2;
-                    Face f = new Face(v1, v2, v3);
+                    Face f = new (v1, v2, v3);
                     faces.Add(f);
                 }
             }
@@ -323,14 +323,11 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing

             if(needsConvexProcessing)
             {
-                List<Coord> convexcoords;
-                List<Face> convexfaces;
-                if(CreateBoundingHull(coords, out convexcoords, out convexfaces) && convexcoords != null && convexfaces != null)
+                 if(CreateBoundingHull(coords, out List<Coord> convexcoords, out List<Face> convexfaces) && convexcoords != null && convexfaces != null)
                 {
                     coords.Clear();
                     coords = convexcoords;
-                    numCoords = coords.Count;
-
+
                     faces.Clear();
                     faces = convexfaces;
                     numFaces = faces.Count;
@@ -339,7 +336,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
                      m_log.ErrorFormat("[ubMESH]: failed to create convex for {0} using normal mesh", primName);
             }

-            Mesh mesh = new Mesh(true);
+            Mesh mesh = new(true);
             // Add the corresponding triangles to the mesh
             for (int i = 0; i < numFaces; i++)
             {
@@ -385,200 +382,168 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing

             coords = new List<Coord>();
             faces = new List<Face>();
-            OSD meshOsd = null;

             if (primShape.SculptData == null || primShape.SculptData.Length <= 0)
             {
 //                m_log.InfoFormat("[MESH]: asset data for {0} is zero length", primName);
                 return false;
             }
-
+            OSD osd;
             long start = 0;
-            using (MemoryStream data = new MemoryStream(primShape.SculptData))
+            using (MemoryStream data = new(primShape.SculptData))
             {
                 try
                 {
-                    OSD osd = OSDParser.DeserializeLLSDBinary(data);
-                    if (osd is OSDMap)
-                        meshOsd = (OSDMap)osd;
-                    else
-                    {
-                        m_log.WarnFormat("[Mesh}: unable to cast mesh asset to OSDMap prim: {0} asset {1}",primName, primShape.SculptTexture);
-                        return false;
-                    }
+                    osd = OSDParser.DeserializeLLSDBinary(data);
                 }
                 catch (Exception e)
                 {
-                    m_log.ErrorFormat("[MESH]: Error deserializing mesh asset header: {0} in Prim '{1}' asset {2}", e.Message, primName, primShape.SculptTexture);
+                    m_log.Error($"[MESH]: Error deserializing mesh asset header: {e.Message} in Prim '{primName}' asset {primShape.SculptTexture}");
                     return false;
                 }

                 start = data.Position;
             }

-            if (meshOsd is OSDMap)
+            if (osd is not OSDMap map)
             {
-                OSDMap physicsParms = null;
-                OSDMap map = (OSDMap)meshOsd;
+                m_log.Warn($"[Mesh]: unable to cast mesh asset to OSDMap prim: {primName} asset {primShape.SculptTexture}");
+                return false;
+            }

-                if (!convex)
-                {
-                    if (map.ContainsKey("physics_shape"))
-                        physicsParms = (OSDMap)map["physics_shape"]; // old asset format
-                    else if (map.ContainsKey("physics_mesh"))
-                        physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
+            OSDMap physicsParms = null;

-                    if (physicsParms != null)
-                        usemesh = true;
-                }
+            if (!convex)
+            {
+                if (map.TryGetValue("physics_shape", out OSD pso))
+                    physicsParms = (OSDMap)pso; // old asset format
+                else if (map.TryGetValue("physics_mesh", out OSD pm))
+                    physicsParms = (OSDMap)pm; // new asset format

-                if(!usemesh && (map.ContainsKey("physics_convex")))
-                        physicsParms = (OSDMap)map["physics_convex"];
+                if (physicsParms != null)
+                    usemesh = true;
+            }

-                if (physicsParms == null)
-                {
-                    //m_log.WarnFormat("[MESH]: unknown mesh type for prim {0}",primName);
-                    return false;
-                }
+            if(!usemesh && map.TryGetValue("physics_convex",out OSD pc))
+                    physicsParms = (OSDMap)pc;
+
+            if (physicsParms == null)
+            {
+                //m_log.WarnFormat("[MESH]: unknown mesh type for prim {0}",primName);
+                return false;
+            }

-                int physOffset = physicsParms["offset"].AsInteger() + (int)start;
-                int physSize = physicsParms["size"].AsInteger();
+            int physOffset = physicsParms["offset"].AsInteger() + (int)start;
+            int physSize = physicsParms["size"].AsInteger();

-                if (physOffset < 0 || physSize == 0)
-                    return false; // no mesh data in asset
+            if (physOffset < 0 || physSize == 0)
+                return false; // no mesh data in asset

-                OSD decodedMeshOsd = new OSD();
-                try
+            OSD decodedMeshOsd = new();
+            try
+            {
+                using (MemoryStream outMs = new(4 * physSize))
                 {
-                    using (MemoryStream outMs = new MemoryStream(4 * physSize))
+                    using (MemoryStream inMs = new(primShape.SculptData, physOffset, physSize))
                     {
-                        using (MemoryStream inMs = new MemoryStream(primShape.SculptData, physOffset, physSize))
+                        using (DeflateStream decompressionStream = new(inMs, CompressionMode.Decompress))
                         {
-                            using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress))
-                            {
-                                byte[] readBuffer = new byte[8192];
-                                inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
-                                int readLen = 0;
+                            byte[] readBuffer = new byte[8192];
+                            inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header
+                            int readLen = 0;

-                                while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
-                                    outMs.Write(readBuffer, 0, readLen);
-                            }
+                            while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0)
+                                outMs.Write(readBuffer, 0, readLen);
                         }
-                        outMs.Seek(0, SeekOrigin.Begin);
-                        decodedMeshOsd = OSDParser.DeserializeLLSDBinary(outMs);
                     }
+                    outMs.Seek(0, SeekOrigin.Begin);
+                    decodedMeshOsd = OSDParser.DeserializeLLSDBinary(outMs);
                 }
-                catch (Exception e)
-                {
-                    m_log.Error("[MESH]: exception decoding physical mesh prim " + primName +" : " + e.ToString());
-                    return false;
-                }
+            }
+            catch (Exception e)
+            {
+                m_log.Error("[MESH]: exception decoding physical mesh prim " + primName +" : " + e.ToString());
+                return false;
+            }

-                if (usemesh)
+            if (usemesh)
+            {
+                // physics_shape is an array of OSDMaps, one for each submesh
+                if (decodedMeshOsd is OSDArray decodedMeshOsdArray)
                 {
-                    OSDArray decodedMeshOsdArray = null;
-
-                    // physics_shape is an array of OSDMaps, one for each submesh
-                    if (decodedMeshOsd is OSDArray)
+                    //Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
+                    foreach (OSD subMeshOsd in decodedMeshOsdArray)
                     {
-//                      Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
-
-                        decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
-                        foreach (OSD subMeshOsd in decodedMeshOsdArray)
-                        {
-                            if (subMeshOsd is OSDMap)
-                                AddSubMesh(subMeshOsd as OSDMap, coords, faces);
-                        }
+                        if (subMeshOsd is OSDMap subm)
+                            AddSubMesh(subm, coords, faces);
                     }
                 }
+                return true;
+            }
+            else if(decodedMeshOsd is OSDMap cmap)
+            {
+                byte[] data;
+
+                List<float3> vs = new();
+                PHullResult hullr = new();
+                float3 f3;
+                Vector3 range;
+                Vector3 min;
+
+                const float invMaxU16 = 1.0f / 65535f;
+                int t1;
+                int t2;
+                int t3;
+                int i;
+                int nverts;
+                int nindexs;
+
+                if (cmap.ContainsKey("Max"))
+                    range = cmap["Max"].AsVector3();
                 else
-                {
-                    OSDMap cmap = (OSDMap)decodedMeshOsd;
-                    if (cmap == null)
-                        return false;
-
-                    byte[] data;
-
-                    List<float3> vs = new List<float3>();
-                    PHullResult hullr = new PHullResult();
-                    float3 f3;
-                    Vector3 range;
-                    Vector3 min;
-
-                    const float invMaxU16 = 1.0f / 65535f;
-                    int t1;
-                    int t2;
-                    int t3;
-                    int i;
-                    int nverts;
-                    int nindexs;
-
-                    if (cmap.ContainsKey("Max"))
-                        range = cmap["Max"].AsVector3();
-                    else
-                        range = new Vector3(0.5f, 0.5f, 0.5f);
+                    range = new Vector3(0.5f, 0.5f, 0.5f);

-                    if (cmap.ContainsKey("Min"))
-                        min = cmap["Min"].AsVector3();
-                    else
-                        min = new Vector3(-0.5f, -0.5f, -0.5f);
+                if (cmap.ContainsKey("Min"))
+                    min = cmap["Min"].AsVector3();
+                else
+                    min = new Vector3(-0.5f, -0.5f, -0.5f);

-                    range = range - min;
-                    range *= invMaxU16;
+                range -= min;
+                range *= invMaxU16;

-                    if(!convex)
+                if(!convex)
+                {
+                    // if mesh data not present and not convex then we need convex decomposition data
+                    if (cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions"))
                     {
-                        // if mesh data not present and not convex then we need convex decomposition data
-                        if (cmap.ContainsKey("HullList") && cmap.ContainsKey("Positions"))
+                        List<int> hsizes = new();
+                        int totalpoints = 0;
+                        data = cmap["HullList"].AsBinary();
+                        for (i = 0; i < data.Length; i++)
                         {
-                            List<int> hsizes = new List<int>();
-                            int totalpoints = 0;
-                            data = cmap["HullList"].AsBinary();
-                            for (i = 0; i < data.Length; i++)
-                            {
-                                t1 = data[i];
-                                if (t1 == 0)
-                                    t1 = 256;
-                                totalpoints += t1;
-                                hsizes.Add(t1);
-                            }
+                            t1 = data[i];
+                            if (t1 == 0)
+                                t1 = 256;
+                            totalpoints += t1;
+                            hsizes.Add(t1);
+                        }

-                            data = cmap["Positions"].AsBinary();
-                            fixed(byte* ptrstart = data)
-                            {
-                                byte* ptr = ptrstart;
+                        data = cmap["Positions"].AsBinary();
+                        fixed(byte* ptrstart = data)
+                        {
+                            byte* ptr = ptrstart;

-                                int vertsoffset = 0;
+                            int vertsoffset = 0;

-                                if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point
+                            if (totalpoints == data.Length / 6) // 2 bytes per coord, 3 coords per point
+                            {
+                                foreach (int hullsize in hsizes)
                                 {
-                                    foreach (int hullsize in hsizes)
+                                    if (hullsize < 4)
                                     {
-                                        if (hullsize < 4)
+                                        if (hullsize < 3)
                                         {
-                                            if (hullsize < 3)
-                                            {
-                                                ptr += 6 * hullsize;
-                                                continue;
-                                            }
-
-                                            for (i = 0; i < hullsize; i++)
-                                            {
-                                                t1 = Utils.BytesToUInt16(ptr); ptr += 2;
-                                                t2 = Utils.BytesToUInt16(ptr); ptr += 2;
-                                                t3 = Utils.BytesToUInt16(ptr); ptr += 2;
-
-                                                coords.Add(new Coord(
-                                                                t1 * range.X + min.X,
-                                                                t2 * range.Y + min.Y,
-                                                                t3 * range.Z + min.Z)
-                                                           );
-
-                                            }
-
-                                            faces.Add(new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2));
-
-                                            vertsoffset += hullsize;
+                                            ptr += 6 * hullsize;
                                             continue;
                                         }

@@ -588,134 +553,149 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
                                             t2 = Utils.BytesToUInt16(ptr); ptr += 2;
                                             t3 = Utils.BytesToUInt16(ptr); ptr += 2;

-                                            f3 = new float3(t1 * range.X + min.X,
+                                            coords.Add(new Coord(
+                                                            t1 * range.X + min.X,
                                                             t2 * range.Y + min.Y,
-                                                            t3 * range.Z + min.Z);
-                                            vs.Add(f3);
+                                                            t3 * range.Z + min.Z)
+                                                        );
+
                                         }

-                                        List<int> indices;
-                                        if (!HullUtils.ComputeHull(vs, out indices))
-                                        {
-                                            vs.Clear();
-                                            continue;
-                                        }
+                                        faces.Add(new Face(vertsoffset, vertsoffset + 1, vertsoffset + 2));

-                                        nverts = vs.Count;
-                                        nindexs = indices.Count;
+                                        vertsoffset += hullsize;
+                                        continue;
+                                    }

-                                        if (nindexs % 3 != 0)
-                                        {
-                                            vs.Clear();
-                                            continue;
-                                        }
+                                    for (i = 0; i < hullsize; i++)
+                                    {
+                                        t1 = Utils.BytesToUInt16(ptr); ptr += 2;
+                                        t2 = Utils.BytesToUInt16(ptr); ptr += 2;
+                                        t3 = Utils.BytesToUInt16(ptr); ptr += 2;
+
+                                        f3 = new float3(t1 * range.X + min.X,
+                                                        t2 * range.Y + min.Y,
+                                                        t3 * range.Z + min.Z);
+                                        vs.Add(f3);
+                                    }
+
+                                    if (!HullUtils.ComputeHull(vs, out List<int> indices))
+                                    {
+                                        vs.Clear();
+                                        continue;
+                                    }

-                                        for (i = 0; i < vs.Count; i++)
-                                            coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));
+                                    nverts = vs.Count;
+                                    nindexs = indices.Count;

-                                        for (i = 0; i < indices.Count; i += 3)
-                                        {
-                                            t1 = indices[i];
-                                            if (t1 > nverts)
-                                                break;
-                                            t2 = indices[i + 1];
-                                            if (t2 > nverts)
-                                                break;
-                                            t3 = indices[i + 2];
-                                            if (t3 > nverts)
-                                                break;
-                                            faces.Add(new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3));
-                                        }
-                                        vertsoffset += nverts;
+                                    if (nindexs % 3 != 0)
+                                    {
                                         vs.Clear();
+                                        continue;
+                                    }
+
+                                    for (i = 0; i < vs.Count; i++)
+                                        coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));
+
+                                    for (i = 0; i < indices.Count; i += 3)
+                                    {
+                                        t1 = indices[i];
+                                        if (t1 > nverts)
+                                            break;
+                                        t2 = indices[i + 1];
+                                        if (t2 > nverts)
+                                            break;
+                                        t3 = indices[i + 2];
+                                        if (t3 > nverts)
+                                            break;
+                                        faces.Add(new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3));
                                     }
+                                    vertsoffset += nverts;
+                                    vs.Clear();
                                 }
                             }
-                            if (coords.Count > 0 && faces.Count > 0)
-                                return true;
-                        }
-                        else
-                        {
-                            // if neither mesh or decomposition present, warn and use convex
-                            //m_log.WarnFormat("[MESH]: Data for PRIM shape type ( mesh or decomposition) not found for prim {0}",primName);
                         }
+                        if (coords.Count > 0 && faces.Count > 0)
+                            return true;
                     }
-                    vs.Clear();
+                    else
+                    {
+                        // if neither mesh or decomposition present, warn and use convex
+                        //m_log.WarnFormat("[MESH]: Data for PRIM shape type ( mesh or decomposition) not found for prim {0}",primName);
+                    }
+                }
+                vs.Clear();

-                    if (cmap.TryGetValue("BoundingVerts", out OSD odata))
+                if (cmap.TryGetValue("BoundingVerts", out OSD odata))
+                {
+                    data = odata.AsBinary();
+                    if (data.Length < 3 * 6)
                     {
-                        data = odata.AsBinary();
-                        if (data.Length < 3 * 6)
-                        {
-                            vs.Clear();
-                            return false;
-                        }
+                        vs.Clear();
+                        return false;
+                    }

-                        fixed (byte* ptrstart = data)
+                    fixed (byte* ptrstart = data)
+                    {
+                        byte* end = ptrstart + data.Length;
+                        byte* ptr = ptrstart;
+                        while(ptr < end)
                         {
-                            byte* end = ptrstart + data.Length;
-                            byte* ptr = ptrstart;
-                            while(ptr < end)
-                            {
-                                t1 = Utils.BytesToUInt16(ptr); ptr += 2;
-                                t2 = Utils.BytesToUInt16(ptr); ptr += 2;
-                                t3 = Utils.BytesToUInt16(ptr); ptr += 2;
-
-                                f3 = new float3((t1 * range.X + min.X),
-                                          (t2 * range.Y + min.Y),
-                                          (t3 * range.Z + min.Z));
-                                vs.Add(f3);
-                            }
+                            t1 = Utils.BytesToUInt16(ptr); ptr += 2;
+                            t2 = Utils.BytesToUInt16(ptr); ptr += 2;
+                            t3 = Utils.BytesToUInt16(ptr); ptr += 2;
+
+                            f3 = new float3((t1 * range.X + min.X),
+                                        (t2 * range.Y + min.Y),
+                                        (t3 * range.Z + min.Z));
+                            vs.Add(f3);
                         }
+                    }

-                        nverts = vs.Count;
+                    nverts = vs.Count;

-                        if (nverts < 4)
-                        {
-                            for (i = 0; i < vs.Count; i++)
-                                coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));
+                    if (nverts < 4)
+                    {
+                        for (i = 0; i < vs.Count; i++)
+                            coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));

-                            faces.Add(new Face(0, 1, 2));
+                        faces.Add(new Face(0, 1, 2));

-                            vs.Clear();
-                            return true;
-                        }
+                        vs.Clear();
+                        return true;
+                    }

-                        List<int> indices;
-                        if (!HullUtils.ComputeHull(vs, out indices))
-                            return false;
+                    if (!HullUtils.ComputeHull(vs, out List<int> indices))
+                        return false;

-                        nindexs = indices.Count;
+                    nindexs = indices.Count;

-                        if (nindexs % 3 != 0)
-                            return false;
+                    if (nindexs % 3 != 0)
+                        return false;

-                        for (i = 0; i < vs.Count; i++)
-                            coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));
+                    for (i = 0; i < vs.Count; i++)
+                        coords.Add(new Coord(vs[i].x, vs[i].y, vs[i].z));

-                        for (i = 0; i < indices.Count; i += 3)
-                        {
-                            t1 = indices[i];
-                            if (t1 > nverts)
-                                break;
-                            t2 = indices[i + 1];
-                            if (t2 > nverts)
-                                break;
-                            t3 = indices[i + 2];
-                            if (t3 > nverts)
-                                break;
-
-                            faces.Add(new Face(t1, t2, t3));
-                        }
-                        vs.Clear();
-                        if (coords.Count > 0 && faces.Count > 0)
-                            return true;
+                    for (i = 0; i < indices.Count; i += 3)
+                    {
+                        t1 = indices[i];
+                        if (t1 > nverts)
+                            break;
+                        t2 = indices[i + 1];
+                        if (t2 > nverts)
+                            break;
+                        t3 = indices[i + 2];
+                        if (t3 > nverts)
+                            break;
+
+                        faces.Add(new Face(t1, t2, t3));
                     }
-                    return false;
+                    vs.Clear();
+                    if (coords.Count > 0 && faces.Count > 0)
+                        return true;
                 }
             }
-
-            return true;
+            return false;
         }

         /// <summary>
@@ -728,70 +708,56 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
         /// <param name="coords">Coords are added to this list by the method.</param>
         /// <param name="faces">Faces are added to this list by the method.</param>
         /// <returns>true if coords and faces were successfully generated, false if not</returns>
-        private bool GenerateCoordsAndFacesFromPrimSculptData(
+        private static bool GenerateCoordsAndFacesFromPrimSculptData(
             string primName, PrimitiveBaseShape primShape, float lod, out List<Coord> coords, out List<Face> faces)
         {
             coords = new List<Coord>();
             faces = new List<Face>();
             PrimMesher.SculptMesh sculptMesh;
-            Image idata = null;
+            Image idata;

-                if (primShape.SculptData == null || primShape.SculptData.Length == 0)
-                    return false;
+            if (primShape.SculptData == null || primShape.SculptData.Length == 0)
+                return false;

-                try
-                {
-                    OpenMetaverse.Imaging.ManagedImage unusedData;
-                    OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
+            try
+            {
+                OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out OpenMetaverse.Imaging.ManagedImage unusedData, out idata);

-                    unusedData = null;
+                unusedData = null;

-                    if (idata == null)
-                    {
-                        // In some cases it seems that the decode can return a null bitmap without throwing
-                        // an exception
-                        m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap.  Ignoring.", primName);
-                        return false;
-                    }
-                }
-                catch (DllNotFoundException)
-                {
-                    m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed.  Often times this is because of an old version of GLIBC.  You must have version 2.4 or above!");
-                    return false;
-                }
-                catch (IndexOutOfRangeException)
-                {
-                    m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
-                    return false;
-                }
-                catch (Exception ex)
+                if (idata == null)
                 {
-                    m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
+                    // In some cases it seems that the decode can return a null bitmap without throwing
+                    // an exception
+                    m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap.  Ignoring.", primName);
                     return false;
                 }
-
-            PrimMesher.SculptMesh.SculptType sculptType;
+            }
+            catch (DllNotFoundException)
+            {
+                m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed.  Often times this is because of an old version of GLIBC.  You must have version 2.4 or above!");
+                return false;
+            }
+            catch (IndexOutOfRangeException)
+            {
+                m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
+                return false;
+            }
+            catch (Exception ex)
+            {
+                m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
+                return false;
+            }
             // remove mirror and invert bits
             OpenMetaverse.SculptType pbsSculptType = ((OpenMetaverse.SculptType)(primShape.SculptType & 0x3f));
-            switch (pbsSculptType)
+            var sculptType = pbsSculptType switch
             {
-                case OpenMetaverse.SculptType.Cylinder:
-                    sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
-                    break;
-                case OpenMetaverse.SculptType.Plane:
-                    sculptType = PrimMesher.SculptMesh.SculptType.plane;
-                    break;
-                case OpenMetaverse.SculptType.Torus:
-                    sculptType = PrimMesher.SculptMesh.SculptType.torus;
-                    break;
-                case OpenMetaverse.SculptType.Sphere:
-                    sculptType = PrimMesher.SculptMesh.SculptType.sphere;
-                    break;
-                default:
-                    sculptType = PrimMesher.SculptMesh.SculptType.plane;
-                    break;
-            }
-
+                OpenMetaverse.SculptType.Cylinder => PrimMesher.SculptMesh.SculptType.cylinder,
+                OpenMetaverse.SculptType.Plane => PrimMesher.SculptMesh.SculptType.plane,
+                OpenMetaverse.SculptType.Torus => PrimMesher.SculptMesh.SculptType.torus,
+                OpenMetaverse.SculptType.Sphere => PrimMesher.SculptMesh.SculptType.sphere,
+                _ => PrimMesher.SculptMesh.SculptType.plane,
+            };
             bool mirror = ((primShape.SculptType & 128) != 0);
             bool invert = ((primShape.SculptType & 64) != 0);

@@ -861,26 +827,25 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
                 sides = 3;
             else if (profshape == (byte)ProfileShape.Circle)
             {
-                switch (iLOD)
+                sides = iLOD switch
                 {
-                    case LevelOfDetail.High:    sides = 24;     break;
-                    case LevelOfDetail.Medium:  sides = 12;     break;
-                    case LevelOfDetail.Low:     sides = 6;      break;
-                    case LevelOfDetail.VeryLow: sides = 3;      break;
-                    default:                    sides = 24;     break;
-                }
+                    LevelOfDetail.High => 24,
+                    LevelOfDetail.Medium => 12,
+                    LevelOfDetail.Low => 6,
+                    LevelOfDetail.VeryLow => 3,
+                    _ => 24,
+                };
             }
             else if (profshape == (byte)ProfileShape.HalfCircle)
             { // half circle, prim is a sphere
-                switch (iLOD)
+                sides = iLOD switch
                 {
-                    case LevelOfDetail.High:    sides = 24;     break;
-                    case LevelOfDetail.Medium:  sides = 12;     break;
-                    case LevelOfDetail.Low:     sides = 6;      break;
-                    case LevelOfDetail.VeryLow: sides = 3;      break;
-                    default:                    sides = 24;     break;
-                }
-
+                    LevelOfDetail.High => 24,
+                    LevelOfDetail.Medium => 12,
+                    LevelOfDetail.Low => 6,
+                    LevelOfDetail.VeryLow => 3,
+                    _ => 24,
+                };
                 profileBegin = 0.5f * profileBegin + 0.5f;
                 profileEnd = 0.5f * profileEnd + 0.5f;
             }
@@ -888,14 +853,14 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             int hollowSides = sides;
             if (primShape.HollowShape == HollowShape.Circle)
             {
-                switch (iLOD)
+                hollowSides = iLOD switch
                 {
-                    case LevelOfDetail.High:    hollowSides = 24;     break;
-                    case LevelOfDetail.Medium:  hollowSides = 12;     break;
-                    case LevelOfDetail.Low:     hollowSides = 6;      break;
-                    case LevelOfDetail.VeryLow: hollowSides = 3;      break;
-                    default:                    hollowSides = 24;     break;
-                }
+                    LevelOfDetail.High => 24,
+                    LevelOfDetail.Medium => 12,
+                    LevelOfDetail.Low => 6,
+                    LevelOfDetail.VeryLow => 3,
+                    _ => 24,
+                };
             }
             else if (primShape.HollowShape == HollowShape.Square)
                 hollowSides = 4;
@@ -980,9 +945,9 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             return true;
         }

-        public AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex)
+        public static AMeshKey GetMeshUniqueKey(PrimitiveBaseShape primShape, Vector3 size, byte lod, bool convex)
         {
-            AMeshKey key = new AMeshKey();
+            AMeshKey key = new();
             Byte[] someBytes;

             key.hashB = 5181;
@@ -1028,7 +993,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing

             if (size == m_MeshUnitSize)
             {
-                hash = hash << 8;
+                hash <<= 8;
                 hash |= 8;
             }
             else
@@ -1036,7 +1001,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
                 someBytes = size.GetBytes();
                 for (int i = 0; i < someBytes.Length; i++)
                     hash = mdjb2(hash, someBytes[i]);
-                hash = hash << 8;
+                hash <<= 8;
             }

             if (convex)
@@ -1054,15 +1019,17 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             return key;
         }

-        private ulong mdjb2(ulong hash, byte c)
+        private static ulong mdjb2(ulong hash, byte c)
         {
-            return ((hash << 5) + hash) + (ulong)c;
+            //return ((hash << 5) + hash) + (ulong)c;
+            return 33 * hash + c;
         }

-        private ulong mdjb2(ulong hash, ushort c)
+        private static ulong mdjb2(ulong hash, ushort c)
         {
-            hash = ((hash << 5) + hash) + (ulong)((byte)c);
-            return ((hash << 5) + hash) + (ulong)(c >> 8);
+            //hash = ((hash << 5) + hash) + (ulong)((byte)c);
+            //return ((hash << 5) + hash) + (ulong)(c >> 8);
+            return 33 * hash + c;
         }

         public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
@@ -1119,7 +1086,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             return null;
         }

-        private static Vector3 m_MeshUnitSize = new Vector3(1.0f, 1.0f, 1.0f);
+        private static Vector3 m_MeshUnitSize = new(1.0f, 1.0f, 1.0f);

         public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod, bool isPhysical, bool convex, bool forOde)
         {
@@ -1264,7 +1231,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             if (m_uniqueReleasedMeshes.Count == 0)
                 return;

-            List<Mesh> meshstodelete = new List<Mesh>();
+            List<Mesh> meshstodelete = new();
             int refcntr;

             lock (m_uniqueReleasedMeshes)
@@ -1291,7 +1258,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
         public void FileNames(AMeshKey key, out string dir, out string fullFileName)
         {
             string id = key.ToString();
-            string init = id.Substring(0, 1);
+            string init = id[..1];
             dir = System.IO.Path.Combine(cachePath, init);
             fullFileName = System.IO.Path.Combine(dir, id);
         }
@@ -1299,7 +1266,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
         public string FullFileName(AMeshKey key)
         {
             string id = key.ToString();
-            string init = id.Substring(0,1);
+            string init = id[..1];
             id = System.IO.Path.Combine(init, id);
             id = System.IO.Path.Combine(cachePath, id);
             return id;
@@ -1354,10 +1321,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             bool ok = false;

             // Make sure the target cache directory exists
-            string dir = String.Empty;
-            string filename = String.Empty;
-
-            FileNames(key, out dir, out filename);
+            FileNames(key, out string dir, out string filename);

             lock (diskLock)
             {
@@ -1537,17 +1501,17 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing
             }
         }

-        public bool CreateBoundingHull(List<Coord> inputVertices, out List<Coord> convexcoords, out List<Face> newfaces)
+        public static bool CreateBoundingHull(List<Coord> inputVertices, out List<Coord> convexcoords, out List<Face> newfaces)
         {
             convexcoords = null;
             newfaces = null;
-            HullDesc desc = new HullDesc();
-            HullResult result = new HullResult();
+            HullDesc desc = new();
+            HullResult result = new();

             int nInputVerts = inputVertices.Count;
             int i;

-            List<float3> vs = new List<float3>(nInputVerts);
+            List<float3> vs = new(nInputVerts);
             float3 f3;

             //useless copy
diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
index f3a57d3..7645183 100644
--- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
+++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs
@@ -29,6 +29,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 using System.IO;
+using System.Xml.XPath;

 namespace PrimMesher
 {
@@ -60,27 +61,25 @@ namespace PrimMesher

         public Quat(MainAxis BaseAxis, float angle)
         {
-            angle *= 0.5f;
-            double c = Math.Cos(angle);
-            float s = (float)Math.Sqrt(1.0 - c * c);
-
-            W = (float)c;
             switch (BaseAxis)
             {
                 case MainAxis.X:
-                    X = s;
+                    W = MathF.Cos(0.5f * angle);
+                    X = MathF.Sqrt(1.0f - W * W);
                     Y = 0;
                     Z = 0;
                     break;
                 case MainAxis.Y:
+                    W = MathF.Cos(0.5f * angle);
+                    Y = MathF.Sqrt(1.0f - W * W);
                     X = 0;
-                    Y = s;
                     Z = 0;
                     break;
                 case MainAxis.Z:
+                    W = MathF.Cos(0.5f * angle);
+                    Z = MathF.Sqrt(1.0f - W * W);
                     X = 0;
                     Y = 0;
-                    Z = s;
                     break;
                 default: //error
                     X = 0;
@@ -93,18 +92,18 @@ namespace PrimMesher

         public float Length()
         {
-            return (float)Math.Sqrt(X * X + Y * Y + Z * Z + W * W);
+            return MathF.Sqrt(X * X + Y * Y + Z * Z + W * W);
         }

         public Quat Normalize()
         {
             const float MAG_THRESHOLD = 0.0000001f;
-            float mag = Length();
+            float mag = (X * X + Y * Y + Z * Z + W * W);

             // Catch very small rounding errors when normalizing
             if (mag > MAG_THRESHOLD)
             {
-                float oomag = 1f / mag;
+                float oomag = 1f / MathF.Sqrt(mag);
                 X *= oomag;
                 Y *= oomag;
                 Z *= oomag;
@@ -151,7 +150,7 @@ namespace PrimMesher

         public float Length()
         {
-            return (float)Math.Sqrt(X * X + Y * Y + Z * Z);
+            return MathF.Sqrt(X * X + Y * Y + Z * Z);
         }

         public Coord Invert()
@@ -280,7 +279,7 @@ namespace PrimMesher
     {
         private float iX, iY; // intersection point

-        private static Angle[] angles3 =
+        private static readonly Angle[] angles3 =
         {
             new Angle(0.0f, 1.0f, 0.0f),
             new Angle(0.33333333333333333f, -0.5f, 0.86602540378443871f),
@@ -288,7 +287,7 @@ namespace PrimMesher
             new Angle(1.0f, 1.0f, 0.0f)
         };

-        private static Angle[] angles4 =
+        private static readonly Angle[] angles4 =
         {
             new Angle(0.0f, 1.0f, 0.0f),
             new Angle(0.25f, 0.0f, 1.0f),
@@ -297,7 +296,7 @@ namespace PrimMesher
             new Angle(1.0f, 1.0f, 0.0f)
         };

-        private static Angle[] angles6 =
+        private static readonly Angle[] angles6 =
         {
             new Angle(0.0f, 1.0f, 0.0f),
             new Angle(0.16666666666666667f, 0.5f, 0.8660254037844386f),
@@ -308,7 +307,7 @@ namespace PrimMesher
             new Angle(1.0f, 1.0f, 0.0f)
         };

-        private static Angle[] angles12 =
+        private static readonly Angle[] angles12 =
         {
             new Angle(0.0f, 1.0f, 0.0f),
             new Angle(0.083333333333333329f, 0.86602540378443871f, 0.5f),
@@ -325,7 +324,7 @@ namespace PrimMesher
             new Angle(1.0f, 1.0f, 0.0f)
         };

-        private static Angle[] angles24 =
+        private static readonly Angle[] angles24 =
         {
             new Angle(0.0f, 1.0f, 0.0f),
             new Angle(0.041666666666666664f, 0.96592582628906831f, 0.25881904510252074f),
@@ -354,7 +353,7 @@ namespace PrimMesher
             new Angle(1.0f, 1.0f, 0.0f)
         };

-        private Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
+        private static Angle interpolatePoints(float newPoint, Angle p1, Angle p2)
         {
             float m = (newPoint - p1.angle) / (p2.angle - p1.angle);
             return new Angle(newPoint, p1.X + m * (p2.X - p1.X), p1.Y + m * (p2.Y - p1.Y));
@@ -379,8 +378,8 @@ namespace PrimMesher
         {
             angles = new List<Angle>();

-            const float twoPi = 2.0f * (float)Math.PI;
-            const float twoPiInv = 0.5f / (float)Math.PI;
+            const float twoPi = 2.0f * MathF.PI;
+            const float twoPiInv = 0.5f / MathF.PI;

             if (sides < 1)
                 throw new Exception("number of sides not greater than zero");
@@ -391,27 +390,14 @@ namespace PrimMesher
             {
                 startAngle *= twoPiInv;
                 stopAngle *= twoPiInv;
-
-                Angle[] sourceAngles;
-                switch (sides)
+                Angle[] sourceAngles = sides switch
                 {
-                    case 3:
-                        sourceAngles = angles3;
-                        break;
-                    case 4:
-                        sourceAngles = angles4;
-                        break;
-                    case 6:
-                        sourceAngles = angles6;
-                        break;
-                    case 12:
-                        sourceAngles = angles12;
-                        break;
-                    default:
-                        sourceAngles = angles24;
-                        break;
-                }
-
+                    3 => angles3,
+                    4 => angles4,
+                    6 => angles6,
+                    12 => angles12,
+                    _ => angles24,
+                };
                 int startAngleIndex = (int)(startAngle * sides);
                 int endAngleIndex = sourceAngles.Length - 1;

@@ -447,7 +433,7 @@ namespace PrimMesher
                 double stepSize = twoPi / sides;

                 int startStep = (int)(startAngle / stepSize);
-                double angle = stepSize * startStep;
+                float angle = (float)stepSize * startStep;
                 int step = startStep;
                 double stopAngleTest = stopAngle;
                 if (stopAngle < twoPi)
@@ -462,18 +448,18 @@ namespace PrimMesher
                 while (angle <= stopAngleTest)
                 {
                     Angle newAngle;
-                    newAngle.angle = (float)angle;
-                    newAngle.X = (float)System.Math.Cos(angle);
-                    newAngle.Y = (float)System.Math.Sin(angle);
+                    newAngle.angle = angle;
+                    newAngle.X = MathF.Cos(angle);
+                    newAngle.Y = MathF.Sin(angle);
                     angles.Add(newAngle);
                     step += 1;
-                    angle = stepSize * step;
+                    angle = (float)(stepSize * step);
                 }

                 if (startAngle > angles[0].angle)
                 {
                     Angle newAngle;
-                    intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, (float)Math.Cos(startAngle), (float)Math.Sin(startAngle));
+                    intersection(angles[0].X, angles[0].Y, angles[1].X, angles[1].Y, 0.0f, 0.0f, MathF.Cos(startAngle), MathF.Sin(startAngle));
                     newAngle.angle = startAngle;
                     newAngle.X = iX;
                     newAngle.Y = iY;
@@ -484,7 +470,7 @@ namespace PrimMesher
                 if (stopAngle < angles[index].angle)
                 {
                     Angle newAngle;
-                    intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, (float)Math.Cos(stopAngle), (float)Math.Sin(stopAngle));
+                    intersection(angles[index - 1].X, angles[index - 1].Y, angles[index].X, angles[index].Y, 0.0f, 0.0f, MathF.Cos(stopAngle), MathF.Sin(stopAngle));
                     newAngle.angle = stopAngle;
                     newAngle.X = iX;
                     newAngle.Y = iY;
@@ -499,7 +485,7 @@ namespace PrimMesher
     /// </summary>
     public class Profile
     {
-        private const float twoPi = 2.0f * (float)Math.PI;
+        private const float twoPi = 2.0f * MathF.PI;

         public string errorMessage = null;

@@ -532,12 +518,12 @@ namespace PrimMesher
             coords = new List<Coord>();
             faces = new List<Face>();

-            List<Coord> hollowCoords = new List<Coord>();
+            List<Coord> hollowCoords = new();

             bool hasHollow = (hollow > 0.0f);

-            AngleList angles = new AngleList();
-            AngleList hollowAngles = new AngleList();
+            AngleList angles = new();
+            AngleList hollowAngles = new();

             float xScale = 0.5f;
             float yScale = 0.5f;
@@ -562,7 +548,7 @@ namespace PrimMesher
             numOuterVerts = angles.angles.Count;

             Angle angle;
-            Coord newVert = new Coord();
+            Coord newVert = new();

             // flag to create as few triangles as possible for 3 or 4 side profile
             bool simpleFace = (sides < 5 && !hasHollow && !hasProfileCut);
@@ -597,7 +583,7 @@ namespace PrimMesher
             }
             else if (!simpleFace)
             {
-                Coord center = new Coord(0.0f, 0.0f, 0.0f);
+                Coord center = new(0.0f, 0.0f, 0.0f);
                 this.coords.Add(center);
             }

@@ -630,7 +616,7 @@ namespace PrimMesher

                     if (numOuterVerts == numHollowVerts)
                     {
-                        Face newFace = new Face();
+                        Face newFace = new();

                         for (int coordIndex = 0; coordIndex < numOuterVerts - 1; coordIndex++)
                         {
@@ -659,7 +645,7 @@ namespace PrimMesher
                     }
                     else if (numOuterVerts < numHollowVerts)
                     {
-                        Face newFace = new Face();
+                        Face newFace = new();
                         int j = 0; // j is the index for outer vertices
                         int i;
                         int maxJ = numOuterVerts - 1;
@@ -730,7 +716,7 @@ namespace PrimMesher
                     }
                     else // numHollowVerts < numOuterVerts
                     {
-                        Face newFace = new Face();
+                        Face newFace = new();
                         int j = 0; // j is the index for inner vertices
                         int maxJ = numHollowVerts - 1;
                         for (int i = 0; i < numOuterVerts; i++)
@@ -793,24 +779,26 @@ namespace PrimMesher
                 {
                     for (int i = 1; i < numAngles ; i++)
                     {
-                        Face newFace = new Face();
-                        newFace.v1 = 0;
-                        newFace.v2 = i;
-                        newFace.v3 = i + 1;
+                        Face newFace = new()
+                        {
+                            v1 = 0,
+                            v2 = i,
+                            v3 = i + 1
+                        };
                         faces.Add(newFace);
                     }
                     if (!hasProfileCut)
                     {
-                        Face newFace = new Face();
-                        newFace.v1 = 0;
-                        newFace.v2 = numAngles;
-                        newFace.v3 = 1;
+                        Face newFace = new()
+                        {
+                            v1 = 0,
+                            v2 = numAngles,
+                            v3 = 1
+                        };
                         faces.Add(newFace);
                     }
                 }
             }
-
-            hollowCoords = null;
         }


@@ -821,7 +809,7 @@ namespace PrimMesher

         public Profile Copy(bool needFaces)
         {
-            Profile copy = new Profile();
+            Profile copy = new();

             copy.coords.AddRange(coords);

@@ -874,9 +862,9 @@ namespace PrimMesher
             {
                 vert = coords[i];
                 vert.X *= x;
-                vert.X = (float)Math.Round(vert.X,5);
+                vert.X = MathF.Round(vert.X,5);
                 vert.Y *= y;
-                vert.Y = (float)Math.Round(vert.Y,5);
+                vert.Y = MathF.Round(vert.Y,5);
                 coords[i] = vert;
             }

@@ -930,17 +918,12 @@ namespace PrimMesher
         {
             if (path == null)
                 return;
-            String fileName = name + "_" + title + ".raw";
-            String completePath = System.IO.Path.Combine(path, fileName);
-            StreamWriter sw = new StreamWriter(completePath);

+            string completePath = System.IO.Path.Combine(path, $"{name}_{title}.raw");
+            using StreamWriter sw = new(completePath);
             for (int i = 0; i < faces.Count; i++)
             {
-                string s = coords[faces[i].v1].ToString();
-                s += " " + coords[faces[i].v2].ToString();
-                s += " " + coords[faces[i].v3].ToString();
-
-                sw.WriteLine(s);
+                sw.WriteLine($"{coords[faces[i].v1]} {coords[faces[i].v3]} {coords[faces[i].v3]}");
             }

             sw.Close();
@@ -960,7 +943,7 @@ namespace PrimMesher

     public class Path
     {
-        public List<PathNode> pathNodes = new List<PathNode>();
+        public List<PathNode> pathNodes = new();

         public float twistBegin = 0.0f;
         public float twistEnd = 0.0f;
@@ -979,7 +962,7 @@ namespace PrimMesher
         public float revolutions = 1.0f;
         public int stepsPerRevolution = 24;

-        private const float twoPi = 2.0f * (float)Math.PI;
+        private const float twoPi = 2.0f * MathF.PI;

         public void Create(PathType pathType, int steps)
         {
@@ -998,7 +981,7 @@ namespace PrimMesher

                 float length = pathCutEnd - pathCutBegin;
                 float twistTotal = twistEnd - twistBegin;
-                float twistTotalAbs = Math.Abs(twistTotal);
+                float twistTotalAbs = MathF.Abs(twistTotal);
                 if (twistTotalAbs > 0.01f)
                     steps += (int)(twistTotalAbs * 3.66); //  dahlia's magic number

@@ -1020,7 +1003,7 @@ namespace PrimMesher

                 while (!done)
                 {
-                    PathNode newNode = new PathNode();
+                    PathNode newNode = new();

                     newNode.xScale = 1.0f;
                     if (taperX > 0.0f)
@@ -1063,12 +1046,12 @@ namespace PrimMesher
                 // if the profile has a lot of twist, add more layers otherwise the layers may overlap
                 // and the resulting mesh may be quite inaccurate. This method is arbitrary and doesn't
                 // accurately match the viewer
-                float twistTotalAbs = Math.Abs(twistTotal);
+                float twistTotalAbs = MathF.Abs(twistTotal);
                 if (twistTotalAbs > 0.01f)
                 {
-                    if (twistTotalAbs > Math.PI * 1.5f)
+                    if (twistTotalAbs > MathF.PI * 1.5f)
                         steps *= 2;
-                    if (twistTotalAbs > Math.PI * 3.0f)
+                    if (twistTotalAbs > MathF.PI * 3.0f)
                         steps *= 2;
                 }

@@ -1077,7 +1060,7 @@ namespace PrimMesher
                 float totalSkew = skew * 2.0f * pathLength;
                 float skewStart = pathCutBegin * 2.0f * skew - skew;
                 float xOffsetTopShearXFactor = topShearX * (0.25f + 0.5f * (0.5f - holeSizeY));
-                float yShearCompensation = 1.0f + Math.Abs(topShearY) * 0.25f;
+                float yShearCompensation = 1.0f + MathF.Abs(topShearY) * 0.25f;

                 // It's not quite clear what pushY (Y top shear) does, but subtracting it from the start and end
                 // angles appears to approximate it's effects on path cut. Likewise, adding it to the angle used
@@ -1097,9 +1080,9 @@ namespace PrimMesher
                 bool done = false;
                 while (!done) // loop through the length of the path and add the layers
                 {
-                    PathNode newNode = new PathNode();
+                    PathNode newNode = new();

-                    float xProfileScale = (1.0f - Math.Abs(skew)) * holeSizeX;
+                    float xProfileScale = (1.0f - MathF.Abs(skew)) * holeSizeX;
                     float yProfileScale = holeSizeY;

                     float percentOfPath = angle / (twoPi * revolutions);
@@ -1127,11 +1110,11 @@ namespace PrimMesher
                     float twist = twistBegin + twistTotal * percentOfPath;

                     float xOffset = 0.5f * (skewStart + totalSkew * percentOfAngles);
-                    xOffset += (float)Math.Sin(angle) * xOffsetTopShearXFactor;
+                    xOffset += MathF.Sin(angle) * xOffsetTopShearXFactor;

-                    float yOffset = yShearCompensation * (float)Math.Cos(angle) * (0.5f - yPathScale) * radiusScale;
+                    float yOffset = yShearCompensation * MathF.Cos(angle) * (0.5f - yPathScale) * radiusScale;

-                    float zOffset = (float)Math.Sin(angle + topShearY) * (0.5f - yPathScale) * radiusScale;
+                    float zOffset = MathF.Sin(angle + topShearY) * (0.5f - yPathScale) * radiusScale;

                     newNode.position = new Coord(xOffset, yOffset, zOffset);

@@ -1168,8 +1151,6 @@ namespace PrimMesher
     public class PrimMesh
     {
         public string errorMessage = "";
-        private const float twoPi = 2.0f * (float)Math.PI;
-
         public List<Coord> coords;
 //        public List<Coord> normals;
         public List<Face> faces;
@@ -1289,19 +1270,19 @@ namespace PrimMesher
         /// </summary>
         public void Extrude(PathType pathType)
         {
-            bool needEndFaces = false;
+            bool needEndFaces;

             coords = new List<Coord>();
             faces = new List<Face>();

             int steps = 1;

-            float length = pathCutEnd - pathCutBegin;
+            //float length = pathCutEnd - pathCutBegin;

             hasProfileCut = profileEnd - profileStart < 0.9999f;

             float twistTotal = twistEnd - twistBegin;
-            float twistTotalAbs = Math.Abs(twistTotal);
+            float twistTotalAbs = MathF.Abs(twistTotal);
             if (twistTotalAbs > 0.01f)
                 steps += (int)(twistTotalAbs * 3.66); //  dahlia's magic number

@@ -1330,7 +1311,7 @@ namespace PrimMesher
             {
                 if (sides == 3)
                 {
-                    initialProfileRot = (float)Math.PI;
+                    initialProfileRot = MathF.PI;
                     if (hollowSides == 4)
                     {
                         if (hollow > 0.7f)
@@ -1341,13 +1322,13 @@ namespace PrimMesher
                 }
                 else if (sides == 4)
                 {
-                    initialProfileRot = 0.25f * (float)Math.PI;
+                    initialProfileRot = 0.25f * MathF.PI;
                     if (hollowSides != 4)
                         hollow *= 0.707f;
                 }
                 else if (sides > 4)
                 {
-                    initialProfileRot = (float)Math.PI;
+                    initialProfileRot = MathF.PI;
                     if (hollowSides == 4)
                     {
                         if (hollow > 0.7f)
@@ -1370,7 +1351,7 @@ namespace PrimMesher
                 }
                 else if (sides == 4)
                 {
-                    initialProfileRot = 1.25f * (float)Math.PI;
+                    initialProfileRot = 1.25f * MathF.PI;
                     if (hollowSides != 4)
                         hollow *= 0.707f;
                 }
@@ -1378,8 +1359,7 @@ namespace PrimMesher
                     hollow *= 1.414f;
             }

-            Profile profile = new Profile(sides, profileStart, profileEnd, hollow, hollowSides,
-                                HasProfileCut,true);
+            Profile profile = new(sides, profileStart, profileEnd, hollow, hollowSides, HasProfileCut, true);
             errorMessage = profile.errorMessage;

             numPrimFaces = profile.numPrimFaces;
@@ -1389,23 +1369,25 @@ namespace PrimMesher
                 profile.AddRot(new Quat(Quat.MainAxis.Z, initialProfileRot));
             }

-            Path path = new Path();
-            path.twistBegin = twistBegin;
-            path.twistEnd = twistEnd;
-            path.topShearX = topShearX;
-            path.topShearY = topShearY;
-            path.pathCutBegin = pathCutBegin;
-            path.pathCutEnd = pathCutEnd;
-            path.dimpleBegin = dimpleBegin;
-            path.dimpleEnd = dimpleEnd;
-            path.skew = skew;
-            path.holeSizeX = holeSizeX;
-            path.holeSizeY = holeSizeY;
-            path.taperX = taperX;
-            path.taperY = taperY;
-            path.radius = radius;
-            path.revolutions = revolutions;
-            path.stepsPerRevolution = stepsPerRevolution;
+            Path path = new()
+            {
+                twistBegin = twistBegin,
+                twistEnd = twistEnd,
+                topShearX = topShearX,
+                topShearY = topShearY,
+                pathCutBegin = pathCutBegin,
+                pathCutEnd = pathCutEnd,
+                dimpleBegin = dimpleBegin,
+                dimpleEnd = dimpleEnd,
+                skew = skew,
+                holeSizeX = holeSizeX,
+                holeSizeY = holeSizeY,
+                taperX = taperX,
+                taperY = taperY,
+                radius = radius,
+                revolutions = revolutions,
+                stepsPerRevolution = stepsPerRevolution
+            };

             path.Create(pathType, steps);

@@ -1433,10 +1415,10 @@ namespace PrimMesher

                 // fill faces between layers

-                List<Face> linkfaces = new List<Face>();
+                List<Face> linkfaces = new();
                 int numVerts = newLayer.coords.Count;
-                Face newFace1 = new Face();
-                Face newFace2 = new Face();
+                Face newFace1 = new();
+                Face newFace2 = new();

                 if (nodeIndex > 0)
                 {
@@ -1533,10 +1515,10 @@ namespace PrimMesher
         // more cleanup will be done at Meshmerizer.cs
         }

-        private Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
+        private static Coord SurfaceNormal(Coord c1, Coord c2, Coord c3)
         {
-            Coord edge1 = new Coord(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
-            Coord edge2 = new Coord(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);
+            Coord edge1 = new(c2.X - c1.X, c2.Y - c1.Y, c2.Z - c1.Z);
+            Coord edge2 = new(c3.X - c1.X, c3.Y - c1.Y, c3.Z - c1.Z);

             Coord normal = Coord.Cross(edge1, edge2);

@@ -1570,29 +1552,31 @@ namespace PrimMesher
         /// <returns></returns>
         public PrimMesh Copy()
         {
-            PrimMesh copy = new PrimMesh(sides, profileStart, profileEnd, hollow, hollowSides);
-            copy.twistBegin = twistBegin;
-            copy.twistEnd = twistEnd;
-            copy.topShearX = topShearX;
-            copy.topShearY = topShearY;
-            copy.pathCutBegin = pathCutBegin;
-            copy.pathCutEnd = pathCutEnd;
-            copy.dimpleBegin = dimpleBegin;
-            copy.dimpleEnd = dimpleEnd;
-            copy.skew = skew;
-            copy.holeSizeX = holeSizeX;
-            copy.holeSizeY = holeSizeY;
-            copy.taperX = taperX;
-            copy.taperY = taperY;
-            copy.radius = radius;
-            copy.revolutions = revolutions;
-            copy.stepsPerRevolution = stepsPerRevolution;
-
-            copy.numPrimFaces = numPrimFaces;
-            copy.errorMessage = errorMessage;
-
-            copy.coords = new List<Coord>(coords);
-            copy.faces = new List<Face>(faces);
+            PrimMesh copy = new(sides, profileStart, profileEnd, hollow, hollowSides)
+            {
+                twistBegin = twistBegin,
+                twistEnd = twistEnd,
+                topShearX = topShearX,
+                topShearY = topShearY,
+                pathCutBegin = pathCutBegin,
+                pathCutEnd = pathCutEnd,
+                dimpleBegin = dimpleBegin,
+                dimpleEnd = dimpleEnd,
+                skew = skew,
+                holeSizeX = holeSizeX,
+                holeSizeY = holeSizeY,
+                taperX = taperX,
+                taperY = taperY,
+                radius = radius,
+                revolutions = revolutions,
+                stepsPerRevolution = stepsPerRevolution,
+
+                numPrimFaces = numPrimFaces,
+                errorMessage = errorMessage,
+
+                coords = new List<Coord>(coords),
+                faces = new List<Face>(faces)
+            };

             return copy;
         }
@@ -1644,7 +1628,7 @@ namespace PrimMesher
             int numVerts = this.coords.Count;
             //Coord vert;

-            Coord m = new Coord(x, y, z);
+            Coord m = new(x, y, z);
             for (i = 0; i < numVerts; i++)
                 coords[i] *= m;
         }
@@ -1659,16 +1643,13 @@ namespace PrimMesher
         {
             if (path == null)
                 return;
-            String fileName = name + "_" + title + ".raw";
-            String completePath = System.IO.Path.Combine(path, fileName);
-            using (StreamWriter sw = new StreamWriter(completePath))
+            string completePath = System.IO.Path.Combine(path, $"{name}_{title}.raw");
+            using StreamWriter sw = new(completePath);
+            for (int i = 0; i < this.faces.Count; i++)
             {
-                for (int i = 0; i < this.faces.Count; i++)
-                {
-                    sw.Write(coords[faces[i].v1].ToString());
-                    sw.Write(coords[faces[i].v2].ToString());
-                    sw.WriteLine(coords[faces[i].v3].ToString());
-                }
+                sw.Write(coords[faces[i].v1].ToString());
+                sw.Write(coords[faces[i].v2].ToString());
+                sw.WriteLine(coords[faces[i].v3].ToString());
             }
         }
     }
ViewGit