update warp3d and xmlrpc

UbitUmarov [2024-04-21 02:01:47]
update warp3d and xmlrpc
Filename
trunk/managed/Warp3Dmod/Properties/AssemblyInfo.cs
trunk/managed/Warp3Dmod/System.Drawing.Common.dll
trunk/managed/Warp3Dmod/Warp3D.cs
trunk/managed/Warp3Dmod/Warp3D.csproj
trunk/managed/Warp3Dmod/warp_3ds_Importer.cs
trunk/managed/Warp3Dmod/warp_Camera.cs
trunk/managed/Warp3Dmod/warp_Color.cs
trunk/managed/Warp3Dmod/warp_CoreObject.cs
trunk/managed/Warp3Dmod/warp_Edge.cs
trunk/managed/Warp3Dmod/warp_Environment.cs
trunk/managed/Warp3Dmod/warp_FXLensFlare .cs
trunk/managed/Warp3Dmod/warp_FXPlugin.cs
trunk/managed/Warp3Dmod/warp_Light.cs
trunk/managed/Warp3Dmod/warp_Lightmap.cs
trunk/managed/Warp3Dmod/warp_Material.cs
trunk/managed/Warp3Dmod/warp_Math.cs
trunk/managed/Warp3Dmod/warp_Matrix.cs
trunk/managed/Warp3Dmod/warp_Object.cs
trunk/managed/Warp3Dmod/warp_ObjectFactory.cs
trunk/managed/Warp3Dmod/warp_Quaternion.cs
trunk/managed/Warp3Dmod/warp_Rasterizer.cs
trunk/managed/Warp3Dmod/warp_RenderPipeline.cs
trunk/managed/Warp3Dmod/warp_Scene.cs
trunk/managed/Warp3Dmod/warp_Screen.cs
trunk/managed/Warp3Dmod/warp_Texture.cs
trunk/managed/Warp3Dmod/warp_TextureFactory.cs
trunk/managed/Warp3Dmod/warp_TextureProjector.cs
trunk/managed/Warp3Dmod/warp_TextureSettings.cs
trunk/managed/Warp3Dmod/warp_Triangle.cs
trunk/managed/Warp3Dmod/warp_Vector.cs
trunk/managed/Warp3Dmod/warp_Vertex.cs
trunk/managed/XmlRpc/AssemblyInfo.cs
trunk/managed/XmlRpc/Logger.cs
trunk/managed/XmlRpc/SimpleHttpRequest.cs
trunk/managed/XmlRpc/XmlRpcBoxcarRequest.cs
trunk/managed/XmlRpc/XmlRpcDeserializer.cs
trunk/managed/XmlRpc/XmlRpcException.cs
trunk/managed/XmlRpc/XmlRpcExposedAttribute.cs
trunk/managed/XmlRpc/XmlRpcRequest.cs
trunk/managed/XmlRpc/XmlRpcRequestDeserializer.cs
trunk/managed/XmlRpc/XmlRpcRequestSerializer.cs
trunk/managed/XmlRpc/XmlRpcResponder.cs
trunk/managed/XmlRpc/XmlRpcResponse.cs
trunk/managed/XmlRpc/XmlRpcResponseDeserializer.cs
trunk/managed/XmlRpc/XmlRpcResponseSerializer.cs
trunk/managed/XmlRpc/XmlRpcSerializer.cs
trunk/managed/XmlRpc/XmlRpcSystemObject.cs
trunk/managed/XmlRpc/xmlrpc.csproj
diff --git a/trunk/managed/Warp3Dmod/Properties/AssemblyInfo.cs b/trunk/managed/Warp3Dmod/Properties/AssemblyInfo.cs
index ab90e8e..787a128 100644
--- a/trunk/managed/Warp3Dmod/Properties/AssemblyInfo.cs
+++ b/trunk/managed/Warp3Dmod/Properties/AssemblyInfo.cs
@@ -35,5 +35,5 @@ using System.Security.Permissions;
 //
 // You can specify all the values or you can default the Revision and Build Numbers
 // by using the '*' as shown below:
-[assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.0.0.1")]
+[assembly: AssemblyFileVersion("1.0.0.1")]
diff --git a/trunk/managed/Warp3Dmod/System.Drawing.Common.dll b/trunk/managed/Warp3Dmod/System.Drawing.Common.dll
new file mode 100644
index 0000000..7c9e87b
Binary files /dev/null and b/trunk/managed/Warp3Dmod/System.Drawing.Common.dll differ
diff --git a/trunk/managed/Warp3Dmod/Warp3D.cs b/trunk/managed/Warp3Dmod/Warp3D.cs
index b205f84..2ea8362 100644
--- a/trunk/managed/Warp3Dmod/Warp3D.cs
+++ b/trunk/managed/Warp3Dmod/Warp3D.cs
@@ -5,16 +5,16 @@ using System.Collections;

 namespace Warp3D
 {
-	public class Warp3D
-	{
-		warp_Scene _scene = null;
+    public class Warp3D
+    {
+        warp_Scene _scene;

-        private Hashtable _plugins = new Hashtable();
-        private Hashtable _models = new Hashtable();
+        private readonly Hashtable _plugins = new();
+        private readonly Hashtable _models = new();

-		public Warp3D()
-		{
-		}
+        public Warp3D()
+        {
+        }

         public warp_Scene Scene
         {
@@ -22,39 +22,29 @@ namespace Warp3D
             set { _scene = value; }
         }

-        public bool RegisterPlugIN( string name, warp_FXPlugin plugin )
+        public bool RegisterPlugIN(string name, warp_FXPlugin plugin)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            _plugins.Add( name, plugin );
+            _plugins.Add(name, plugin);

             return true;
         }

-        public void ShiftDefaultCamera( float x, float y, float z )
+        public void ShiftDefaultCamera(float x, float y, float z)
         {
-            _scene.defaultCamera.shift( x, y, z );
+            _scene.defaultCamera.shift(x, y, z);
         }

-        public bool AddSphere( string name, float radius, int segments )
+        public bool AddSphere(string name, float radius, int segments)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

             warp_Object o = warp_ObjectFactory.SPHERE(radius, segments);
-
-            if( o == null )
-            {
-                return false;
-            }
-
-            _scene.addObject( name, o );
-			_scene.rebuild();
+            _scene.addObject(name, o);
+            _scene.rebuild();

             return true;
         }
@@ -66,733 +56,568 @@ namespace Warp3D

         public bool AddPlane(string name, float size, bool doubleSide)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

             warp_Object o = warp_ObjectFactory.SIMPLEPLANE(size, doubleSide);
-
-            if ( o == null )
-            {
-                return false;
-            }
-
-            _scene.addObject( name, o );
+            _scene.addObject(name, o);

             return true;
         }

-        public bool AddCube( string name, float size )
+        public bool AddCube(string name, float size)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = warp_ObjectFactory.CUBE( size );
-
-            if ( o == null )
-            {
-                return false;
-            }
-
-            _scene.addObject( name, o );
-			_scene.rebuild();
+            warp_Object o = warp_ObjectFactory.CUBE(size);
+            _scene.addObject(name, o);
+            _scene.rebuild();

             return true;
         }

-		public bool AddBox( string name, float x, float y, float z )
-		{
-			if ( _scene == null )
-			{
-				return false;
-			}
+        public bool AddBox(string name, float x, float y, float z)
+        {
+            if (_scene is null)
+                return false;

-			warp_Object o = warp_ObjectFactory.BOX( x, y, z );
+            warp_Object o = warp_ObjectFactory.BOX(x, y, z);
+            _scene.addObject(name, o);
+            _scene.rebuild();

-			if ( o == null )
-			{
-				return false;
-			}
+            return true;
+        }

-			_scene.addObject( name, o );
-			_scene.rebuild();

-			return true;
-		}
+        public bool ProjectFrontal(string name)
+        {
+            if (_scene is null)
+                return false;

+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
+                return false;

-        public bool ProjectFrontal( string name )
+            warp_TextureProjector.projectFrontal(o);
+            return true;
+        }
+        public bool ProjectCylindric(string name)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-			warp_Object o = _scene.sceneobject(name);
-			if(o == null)
-			{
-				return false;
-			}
-
-            warp_TextureProjector.projectFrontal( o );
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
+                return false;

+            warp_TextureProjector.projectCylindric(o);
             return true;
         }

-        public bool ProjectCylindric( string name )
+        public bool ShiftObject(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-            warp_TextureProjector.projectCylindric( o );

+            o.shift(x, y, z);
             return true;
         }

-        public bool ShiftObject( string name, float x, float y, float z )
+        public bool SetPos(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-			o.shift( x, y, z );

+            o.setPos(x, y, z);
             return true;
         }

-		public bool SetPos( string name, float x, float y, float z )
-		{
-			if ( _scene == null )
-			{
-				return false;
-			}

-			warp_Object o = _scene.sceneobject( name );
-			if ( o == null )
-			{
-				return false;
-			}
+        public bool AddLensFlare(string name)
+        {
+            if (_scene is null)
+                return false;

-			o.setPos( x, y, z );
+            warp_FXLensFlare lensFlare = new(name, _scene, false);
+            lensFlare.preset1();

-			return true;
-		}
+            RegisterPlugIN(name, lensFlare);

+            return true;
+        }

-        public bool AddLensFlare( string name )
+        public bool NormaliseScene()
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }
-
-            warp_FXLensFlare lensFlare = new warp_FXLensFlare( name, _scene, false );
-			lensFlare.preset1();
-
-            RegisterPlugIN( name, lensFlare );

+            _scene.normalize();
             return true;
         }

-		public bool NormaliseScene()
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
+        public bool SetAmbient(int c)
+        {
+            if (_scene is null)
+                return false;

-			_scene.normalize();
+            _scene.setAmbient(c);
+            return true;
+        }

-			return true;
-		}
+        public bool RotateScene(warp_Quaternion quat, float x, float y, float z)
+        {
+            if (_scene is null)
+                return false;

-		public bool SetAmbient(int c)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
+            _scene.rotate(quat, x, y, z);
+            return true;
+        }

-			_scene.setAmbient(c);
+        public bool RotateScene(float x, float y, float z)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            _scene.rotate(x, y, z);
+            return true;
+        }

-        public bool RotateScene( warp_Quaternion quat, float x, float y, float z )
+        public bool RotateScene(warp_Matrix m)
         {
-            if ( _scene == null )
+            if (_scene is null)
             {
                 return false;
             }

-            _scene.rotate( quat,  x,  y,  z );
+            _scene.rotate(m);

             return true;
         }

-		public bool RotateScene(float x, float y, float z)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			_scene.rotate(x, y, z);
-
-			return true;
-		}
-
-        public bool RotateScene( warp_Matrix m )
+        public bool ScaleScene(float x, float y, float z)
         {
-            if ( _scene == null )
+            if (_scene is null)
             {
                 return false;
             }

-            _scene.rotate( m );
+            _scene.scale(x, y, z);

             return true;
         }

-		public bool ScaleScene(float x, float y, float z)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			_scene.scale(x, y, z);
-
-			return true;
-		}
-
-		public bool TranslateScene(float x, float y, float z)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			_scene.shift(x, y, z);
-
-			return true;
-		}
-
-
-		public bool RotateObject(string name, float x, float y, float z)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			warp_Object o = _scene.sceneobject(name);
-			if(o == null)
-			{
-				return false;
-			}
+        public bool TranslateScene(float x, float y, float z)
+        {
+            if (_scene is null)
+                return false;

-			o.rotate(x, y, z);
+            _scene.shift(x, y, z);
+            return true;
+        }

-			return true;
-		}

-        public bool RotateSelf( string name, float x, float y, float z )
+        public bool RotateObject(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-            o.rotateSelf( x, y, z );

+            o.rotate(x, y, z);
             return true;
         }

-        public bool RotateSelf( string name, warp_Matrix m )
+        public bool RotateSelf(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-            o.rotateSelf( m );

+            o.rotateSelf(x, y, z);
             return true;
         }

-        public bool RotateSelf( string name, warp_Quaternion quat )
+        public bool RotateSelf(string name, warp_Matrix m)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-            o.rotateSelf( quat );

+            o.rotateSelf(m);
             return true;
         }

-
-        public bool ScaleObject( string name, float s )
+        public bool RotateSelf(string name, warp_Quaternion quat)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Object o = _scene.sceneobject( name );
-            if ( o == null )
-            {
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
                 return false;
-            }
-
-            o.scale( s );

+            o.rotateSelf(quat);
             return true;
         }

-		public bool SetObjectMaterial(string name, string m)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			warp_Material material = (warp_Material)_scene.materialData[m];
-			if (material == null)
-			{
-				return false;
-			}

-			_scene.sceneobject(name).setMaterial(material);
+        public bool ScaleObject(string name, float s)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            warp_Object o = _scene.sceneobject(name);
+            if (o is null)
+                return false;

-		public bool SetEnvMap(string name, string path)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
+            o.scale(s);
+            return true;
+        }

-			warp_Texture texture = null;
-			try
-			{
-				texture = new warp_Texture( path );
-			}
-			catch(Exception)
-			{
-				return false;
-			}
+        public bool SetObjectMaterial(string name, string m)
+        {
+            if (_scene is null)
+                return false;

-			warp_Material material = (warp_Material)_scene.materialData[name];
-			if (material == null)
-			{
-				return false;
-			}
+            if (_scene.objectData.TryGetValue(name, out warp_Object o) && _scene.materialData.TryGetValue(m, out warp_Material material) && material is not null)
+            {
+                o.setMaterial(material);
+                return true;
+            }
+            return false;
+        }

-			material.setEnvmap(texture);
+        public bool SetEnvMap(string name, string path)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            if (_scene.materialData.TryGetValue(name, out warp_Material material) && material is not null)
+            {
+                warp_Texture texture;
+                try
+                {
+                    texture = new warp_Texture(path);
+                }
+                catch (Exception)
+                {
+                    return false;
+                }

-		public bool AddLight(string name, float x, float y, float z, int color, int d, int s)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
+                material.setEnvmap(texture);
+                return true;
+            }
+            return false;
+        }

-			_scene.addLight(name,new warp_Light(new warp_Vector(x,y,z),color,d,s));
+        public bool AddLight(string name, float x, float y, float z, int color, int d, int s)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            _scene.addLight(name, new warp_Light(new warp_Vector(x, y, z), color, d, s));
+            return true;
+        }

-        public bool RotateModelSelf( string name, float x, float y, float z )
+        public bool RotateModelSelf(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            Hashtable model = ( Hashtable )_models[ name ];
-            if ( model == null )
-            {
+            if (_models[name] is not Hashtable model)
                 return false;
-            }

-            foreach ( DictionaryEntry myDE in model )
+            foreach (DictionaryEntry myDE in model)
             {
-                string key = ( string )myDE.Key;
-                warp_Object o = ( warp_Object )myDE.Value;
-
-                o.rotateSelf( x, y, z );
+                warp_Object o = (warp_Object)myDE.Value;
+                o.rotateSelf(x, y, z);
             }

             return true;
         }

-        public bool RotateModel( string name, float x, float y, float z )
+        public bool RotateModel(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            Hashtable model = ( Hashtable )_models[ name ];
-            if ( model == null )
-            {
+            if (_models[name] is not Hashtable model)
                 return false;
-            }

-            foreach ( DictionaryEntry myDE in model )
+            foreach (DictionaryEntry myDE in model)
             {
-                string key = ( string )myDE.Key;
-                warp_Object o = ( warp_Object )myDE.Value;
-
-                o.rotate( x, y, z );
+                warp_Object o = (warp_Object)myDE.Value;
+                o.rotate(x, y, z);
             }

             return true;
         }

-        public bool TranslateModel( string name, float x, float y, float z )
+        public bool TranslateModel(string name, float x, float y, float z)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            Hashtable model = ( Hashtable )_models[ name ];
-            if ( model == null )
-            {
+            if (_models[name] is not Hashtable model)
                 return false;
-            }

-            foreach ( DictionaryEntry myDE in model )
+            foreach (DictionaryEntry myDE in model)
             {
-                string key = ( string )myDE.Key;
-                warp_Object o = ( warp_Object )myDE.Value;
-
-                o.shift( x, y, z );
+                warp_Object o = (warp_Object)myDE.Value;
+                o.shift(x, y, z);
             }

             return true;
         }

-        public bool ScaleModel( string name, float scale )
+        public bool ScaleModel(string name, float scale)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            Hashtable model = (Hashtable)_models[ name ];
-            if ( model == null )
-            {
+            if (_models[name] is not Hashtable model)
                 return false;
-            }

-            foreach ( DictionaryEntry myDE in model )
+            foreach (DictionaryEntry myDE in model)
             {
-                string key = ( string )myDE.Key;
-                warp_Object o = ( warp_Object )myDE.Value;
-
-                o.scaleSelf( scale );
+                warp_Object o = (warp_Object)myDE.Value;
+                o.scaleSelf(scale);
             }

             return true;
         }

-		public Hashtable Import3Ds(string name, string path, bool addtoscene)
-		{
-			if (_scene == null)
-			{
-				return null;
-			}
+        public Hashtable Import3Ds(string name, string path, bool addtoscene)
+        {
+            if (_scene is null)
+                return null;

-            Hashtable list = null;
-			warp_3ds_Importer studio = new warp_3ds_Importer();
-			try
-			{
-				list = studio.importFromFile( name, path );
+            Hashtable list;
+            warp_3ds_Importer studio = new();
+            try
+            {
+                list = studio.importFromFile(name, path);

-                if ( addtoscene )
+                if (addtoscene)
                 {
-                    foreach ( DictionaryEntry myDE in list )
+                    foreach (DictionaryEntry myDE in list)
                     {
                         string key = (string)myDE.Key;
                         warp_Object o = (warp_Object)myDE.Value;

-                        _scene.addObject( key , o );
+                        _scene.addObject(key, o);
                     }
                 }

                 _scene.rebuild();
-                _models.Add( name, list );
-			}
-			catch(Exception)
-			{
-				return null;
-			}
-
-			return list;
-		}
-
-		public bool SetBackgroundColor(int c)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			_scene.environment.bgcolor = c;
-
-			return true;
-		}
-
-		public bool SetBackgroundTexture(string path)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			warp_Texture texture = null;
-			try
-			{
-				texture = new warp_Texture(path);
-			}
-			catch (Exception)
-			{
-				return false;
-			}
-
-			_scene.environment.setBackground(texture);
-
-			return true;
-		}
-
-        public bool SetBackgroundMaterial( string path )
-        {
-            if ( _scene == null )
+                _models.Add(name, list);
+            }
+            catch (Exception)
             {
-                return false;
+                return null;
             }

-            warp_Material material = null;
+            return list;
+        }
+
+        public bool SetBackgroundColor(int c)
+        {
+            if (_scene is null)
+                return false;
+
+            _scene.environment.bgcolor = c;
+            return true;
+        }
+
+        public bool SetBackgroundTexture(string path)
+        {
+            if (_scene is null)
+                return false;
+
+            warp_Texture texture;
             try
             {
-                material = new warp_Material( path );
+                texture = new warp_Texture(path);
             }
-            catch ( Exception )
-            {
-                return false;
-            }
-
-            warp_Texture texture = material.getTexture();
-            if ( texture == null )
+            catch (Exception)
             {
                 return false;
             }

-            _scene.environment.setBackground( texture );
-
+            _scene.environment.setBackground(texture);
             return true;
         }

-        public bool SetWireframe( string name, bool w )
+        public bool SetBackgroundMaterial(string path)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Material material = ( warp_Material )_scene.materialData[ name ];
-            if ( material == null )
+            warp_Material material;
+            try
+            {
+                material = new warp_Material(path);
+            }
+            catch (Exception)
             {
                 return false;
             }

-            material.setWireframe( w );
+            warp_Texture texture = material.getTexture();
+            if (texture is null)
+                return false;

+            _scene.environment.setBackground(texture);
             return true;
         }

-		public bool SetTexture(string name, string path)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			warp_Texture texture = null;
-			try
-			{
-				texture = new warp_Texture( path );
-			}
-			catch(Exception)
-			{
-				return false;
-			}
+        public bool SetWireframe(string name, bool w)
+        {
+            if (_scene is null)
+                return false;

-			warp_Material material = (warp_Material)_scene.materialData[name];
-			if (material == null)
-			{
-				return false;
-			}
+            if (_scene.materialData.TryGetValue(name, out warp_Material material))
+            {
+                material.setWireframe(w);
+                return true;
+            }
+            return false;
+        }

-			material.setTexture(texture);
+        public bool SetTexture(string name, string path)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            if (_scene.materialData.TryGetValue(name, out warp_Material material))
+            {
+                warp_Texture texture;
+                try
+                {
+                    texture = new warp_Texture(path);
+                }
+                catch (Exception)
+                {
+                    return false;
+                }
+                material.setTexture(texture);
+                return true;
+            }
+            return false;

-		public bool AddMaterial(string name)
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
+        }

-			warp_Material material = new warp_Material();
-			_scene.addMaterial(name, material);
+        public bool AddMaterial(string name)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            warp_Material material = new();
+            _scene.addMaterial(name, material);
+            return true;
+        }

-        public bool AddMaterial( string name, int color )
+        public bool AddMaterial(string name, int color)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }
-
-            warp_Material material = new warp_Material( color );
-            _scene.addMaterial( name, material );

+            warp_Material material = new(color);
+            _scene.addMaterial(name, material);
             return true;
         }

-        public bool AddMaterial( string name, string path )
+        public bool AddMaterial(string name, string path)
         {
-            if ( _scene == null )
-            {
+            if (_scene is null)
                 return false;
-            }

-            warp_Material material = null;
+            warp_Material material;
             try
             {
-                material = new warp_Material( path );
+                material = new warp_Material(path);
             }
-            catch ( Exception )
+            catch (Exception)
             {
                 return false;
             }

-            _scene.addMaterial( name, material );
-
+            _scene.addMaterial(name, material);
             return true;
         }

-        public bool SetReflectivity( string name, int r )
-		{
-			if (_scene == null)
-			{
-				return false;
-			}
-
-			warp_Material material = (warp_Material)_scene.materialData[name];
-			if (material == null)
-			{
-				return false;
-			}
-
-			material.setReflectivity(r);
+        public bool SetReflectivity(string name, int r)
+        {
+            if (_scene is null)
+                return false;

-			return true;
-		}
+            if (_scene.materialData.TryGetValue(name, out warp_Material material))
+            {
+                material.setReflectivity(r);
+                return true;
+            }
+            return false;
+        }

-		public bool Render()
-		{
-			try
-			{
-				_scene.render();
+        public bool Render()
+        {
+            try
+            {
+                _scene.render();

-                foreach ( DictionaryEntry myDE in _plugins )
+                foreach (DictionaryEntry myDE in _plugins)
                 {
-                    warp_FXPlugin plugin = ( warp_FXPlugin )myDE.Value;
+                    warp_FXPlugin plugin = (warp_FXPlugin)myDE.Value;
                     plugin.apply();
                 }
-			}
-			catch (Exception)
-			{
-				return false;
-			}
-
-			return true;
-		}
-
-		public bool CreateScene(int width, int height)
-		{
-			try
-			{
-				_scene = new warp_Scene(width, height);
+            }
+            catch (Exception)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        public bool CreateScene(int width, int height)
+        {
+            try
+            {
+                _scene = new warp_Scene(width, height);
                 _plugins.Clear();
                 _models.Clear();
-			}
-			catch (Exception)
-			{
-				Reset();
-				return false;
-			}
-
-			return true;
-		}
-
-		public void Reset()
-		{
-			_scene = null;
+            }
+            catch (Exception)
+            {
+                Reset();
+                return false;
+            }
+
+            return true;
+        }
+
+        public void Reset()
+        {
+            _scene = null;
             _plugins.Clear();
             _models.Clear();
-		}
-	}
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/Warp3D.csproj b/trunk/managed/Warp3Dmod/Warp3D.csproj
index 18ae9f7..02e9e7c 100644
--- a/trunk/managed/Warp3Dmod/Warp3D.csproj
+++ b/trunk/managed/Warp3Dmod/Warp3D.csproj
@@ -1,186 +1,49 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProductVersion>8.0.50727</ProductVersion>
-    <SchemaVersion>2.0</SchemaVersion>
-    <ProjectGuid>{6E48530B-16AB-4861-9CED-97334739D675}</ProjectGuid>
+    <TargetFramework>net8.0</TargetFramework>
     <OutputType>Library</OutputType>
-    <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>Warp3D</RootNamespace>
-    <AssemblyName>Warp3D</AssemblyName>
-    <SignAssembly>true</SignAssembly>
+    <SignAssembly>false</SignAssembly>
     <AssemblyOriginatorKeyFile>
     </AssemblyOriginatorKeyFile>
-    <SccProjectName>SAK</SccProjectName>
-    <SccLocalPath>SAK</SccLocalPath>
-    <SccAuxPath>SAK</SccAuxPath>
-    <SccProvider>SAK</SccProvider>
-    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
-    <FileUpgradeFlags>
-    </FileUpgradeFlags>
-    <UpgradeBackupLocation>
-    </UpgradeBackupLocation>
-    <OldToolsVersion>2.0</OldToolsVersion>
-    <TargetFrameworkProfile />
     <PublishUrl>publish\</PublishUrl>
-    <Install>true</Install>
-    <InstallFrom>Disk</InstallFrom>
     <UpdateEnabled>false</UpdateEnabled>
     <UpdateMode>Foreground</UpdateMode>
     <UpdateInterval>7</UpdateInterval>
-    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
-    <UpdatePeriodically>false</UpdatePeriodically>
-    <UpdateRequired>false</UpdateRequired>
-    <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
     <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
-    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <ProduceReferenceAssembly>False</ProduceReferenceAssembly>
+    <RunAnalyzersDuringBuild>True</RunAnalyzersDuringBuild>
+    <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <RegisterForComInterop>false</RegisterForComInterop>
-    <Prefer32Bit>false</Prefer32Bit>
+    <IsPublishable>False</IsPublishable>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Original|AnyCPU' ">
-    <OutputPath>bin\Original\</OutputPath>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <Optimize>true</Optimize>
-    <RegisterForComInterop>true</RegisterForComInterop>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == '64Bit CPU%27s|AnyCPU' ">
-    <OutputPath>bin\64Bit CPU%27s\</OutputPath>
-    <Prefer32Bit>false</Prefer32Bit>
+    <IsPublishable>False</IsPublishable>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
-    <DebugSymbols>true</DebugSymbols>
     <OutputPath>bin\x64\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <RegisterForComInterop>true</RegisterForComInterop>
-    <DebugType>full</DebugType>
-    <PlatformTarget>x64</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
     <OutputPath>bin\x64\Release\</OutputPath>
-    <DefineConstants>TRACE</DefineConstants>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <Optimize>true</Optimize>
-    <DebugType>pdbonly</DebugType>
-    <PlatformTarget>x64</PlatformTarget>
-    <ErrorReport>prompt</ErrorReport>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Original|x64' ">
-    <OutputPath>bin\x64\Original\</OutputPath>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <Optimize>true</Optimize>
-    <RegisterForComInterop>true</RegisterForComInterop>
-    <PlatformTarget>x64</PlatformTarget>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == '64Bit CPU%27s|x64' ">
-    <OutputPath>bin\x64\64Bit CPU%27s\</OutputPath>
-    <PlatformTarget>x64</PlatformTarget>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <Prefer32Bit>false</Prefer32Bit>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Slixel Tester|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <OutputPath>bin\Slixel Tester\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <RegisterForComInterop>true</RegisterForComInterop>
-    <DebugType>full</DebugType>
-    <PlatformTarget>AnyCPU</PlatformTarget>
-    <CodeAnalysisRuleAssemblies>\rules</CodeAnalysisRuleAssemblies>
-    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
-    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
-    <ErrorReport>prompt</ErrorReport>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Slixel Tester|x64' ">
-    <DebugSymbols>true</DebugSymbols>
-    <OutputPath>bin\x64\Slixel Tester\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <RegisterForComInterop>true</RegisterForComInterop>
-    <DebugType>full</DebugType>
-    <PlatformTarget>x64</PlatformTarget>
-    <CodeAnalysisRuleAssemblies>\rules</CodeAnalysisRuleAssemblies>
-    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
-    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
-    <ErrorReport>prompt</ErrorReport>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="System.Xml" />
-  </ItemGroup>
   <ItemGroup>
-    <Compile Include="warp_3ds_Importer.cs" />
-    <Compile Include="warp_Camera.cs" />
-    <Compile Include="warp_Color.cs" />
-    <Compile Include="warp_CoreObject.cs" />
-    <Compile Include="warp_Edge.cs" />
-    <Compile Include="warp_Environment.cs" />
-    <Compile Include="warp_FXLensFlare .cs" />
-    <Compile Include="warp_FXPlugin.cs" />
-    <Compile Include="warp_Light.cs" />
-    <Compile Include="warp_Lightmap.cs" />
-    <Compile Include="warp_Material.cs" />
-    <Compile Include="warp_Math.cs" />
-    <Compile Include="warp_Matrix.cs" />
-    <Compile Include="warp_Object.cs" />
-    <Compile Include="warp_ObjectFactory.cs" />
-    <Compile Include="warp_Quaternion.cs" />
-    <Compile Include="warp_Rasterizer.cs" />
-    <Compile Include="warp_RenderPipeline.cs" />
-    <Compile Include="warp_Scene.cs" />
-    <Compile Include="warp_Screen.cs" />
-    <Compile Include="warp_Texture.cs" />
-    <Compile Include="warp_TextureFactory.cs" />
-    <Compile Include="warp_TextureProjector.cs" />
-    <Compile Include="warp_TextureSettings.cs" />
-    <Compile Include="warp_Triangle.cs" />
-    <Compile Include="warp_Vector.cs" />
-    <Compile Include="warp_Vertex.cs" />
-    <Compile Include="Warp3D.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
+    <None Remove="System.Drawing.Common.dll" />
+    <None Remove="license.txt" />
   </ItemGroup>
   <ItemGroup>
-    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
-      <Visible>False</Visible>
-      <ProductName>.NET Framework 3.5 SP1</ProductName>
-      <Install>true</Install>
-    </BootstrapperPackage>
+     <Reference Include="System.Drawing.Common">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>System.Drawing.Common.dll</HintPath>
+    </Reference>
   </ItemGroup>
-  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
\ No newline at end of file
diff --git a/trunk/managed/Warp3Dmod/warp_3ds_Importer.cs b/trunk/managed/Warp3Dmod/warp_3ds_Importer.cs
index f22f4c6..f96aadc 100644
--- a/trunk/managed/Warp3Dmod/warp_3ds_Importer.cs
+++ b/trunk/managed/Warp3Dmod/warp_3ds_Importer.cs
@@ -5,208 +5,209 @@ using System.Net;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_3ds_Importer.
-	/// </summary>
-	public class warp_3ds_Importer
-	{
-		private int currentJunkId;
-		private int nextJunkOffset;
-
-		private String currentObjectName = null;
-		private warp_Object currentObject = null;
-		private bool endOfStream = false;
-
-        private Hashtable _objects = new Hashtable();
-
-		public warp_3ds_Importer()
-		{
-		}
-
-        public Hashtable importFromFile( string name, String path )
-		{
-            Stream fs = null;
+    /// <summary>
+    /// Summary description for warp_3ds_Importer.
+    /// </summary>
+    public class warp_3ds_Importer
+    {
+        private int currentJunkId;
+        private int nextJunkOffset;
+
+        private string currentObjectName = null;
+        private warp_Object currentObject = null;
+        private bool endOfStream = false;
+
+        private readonly Hashtable _objects = new Hashtable();
+
+        public warp_3ds_Importer()
+        {
+        }
+
+        public Hashtable importFromFile(string name, String path)
+        {
+            Stream fs;
             _objects.Clear();

-            if ( path.StartsWith( "http" ) )
+            if (path.StartsWith("http"))
             {
-                WebRequest webrq = WebRequest.Create( path );
-                fs = webrq.GetResponse().GetResponseStream() ;
+                WebRequest webrq = WebRequest.Create(path);
+                fs = webrq.GetResponse().GetResponseStream();
             }
             else
             {
-                fs = new FileStream( path, FileMode.Open );
+                fs = new FileStream(path, FileMode.Open);
             }

-			BinaryReader br = new BinaryReader( fs );
-			return importFromStream( name, br );
-		}
+            BinaryReader br = new BinaryReader(fs);
+            return importFromStream(name, br);
+        }

-        public Hashtable importFromStream( string name, BinaryReader inStream )
-		{
+        public Hashtable importFromStream(string name, BinaryReader inStream)
+        {
             _objects.Clear();
-
-			readJunkHeader(inStream);
-			if (currentJunkId != 0x4D4D)
-			{
-				return null;
-			}
-
-			try
-			{
-				for (;;)
-				{
-					readNextJunk( name, inStream);
-				}
-			}
-			catch(Exception)
-			{
+
+            readJunkHeader(inStream);
+            if (currentJunkId != 0x4D4D)
+            {
+                return null;
+            }
+
+            try
+            {
+                for (; ; )
+                {
+                    readNextJunk(name, inStream);
+                }
+            }
+            catch (Exception)
+            {
                 // ignored
-			}
+            }

             inStream.Close();

             return _objects;
-		}
-
-		private void readJunkHeader(BinaryReader inStream)
-		{
-			currentJunkId = readShort(inStream);
-			nextJunkOffset = readInt(inStream);
-			endOfStream = currentJunkId < 0;
-		}
-
-		private int readInt(BinaryReader inStream)
-		{
-			return inStream.ReadByte() | (inStream.ReadByte() << 8) | (inStream.ReadByte() << 16) | (inStream.ReadByte() << 24);
-		}
-
-		private int readShort(BinaryReader inStream)
-		{
-			return (inStream.ReadByte() | (inStream.ReadByte() << 8));
-		}
-
-		private void readNextJunk(string name, BinaryReader inStream)
-		{
-			readJunkHeader(inStream);
-
-			if (currentJunkId == 0x3D3D /* mesh block */)
-			{
-				return;
-			}
-
-			if (currentJunkId == 0x4000 /* object block */)
-			{
-				currentObjectName = readString(inStream);
-				return;
-			}
-
-			if (currentJunkId == 0x4100 /* triangular polygon object */)
-			{
-				currentObject = new warp_Object();
-                _objects.Add( name+"_"+currentObjectName, currentObject );
-
-				return;
-			}
-
-			if (currentJunkId == 0x4110 /* vertex list */)
-			{
-				readVertexList(inStream);
-				return;
-			}
-
-			if (currentJunkId == 0x4120 /* point list */)
-			{
-				readPointList(inStream);
-				return;
-			}
-
-			if (currentJunkId == 0x4140 /* mapping coordinates */)
-			{
-				readMappingCoordinates(inStream);
-				return;
-			}
-
-			skipJunk(inStream);
-		}
-
-		private string readString(BinaryReader inStream)
-		{
-			string result = "";
-			byte inByte;
-			while ( (inByte = (byte) inStream.ReadByte()) != 0)
-			{
-				result += (char) inByte;
-			}
-
-			return result;
-		}
-
-		private float readFloat(BinaryReader inStream)
-		{
-			int bits = readInt(inStream);
-
-			int s = ((bits >> 31) == 0) ? 1 : -1;
-			int e = ((bits >> 23) & 0xff);
-			int m = (e == 0) ? (bits & 0x7fffff) << 1 :	(bits & 0x7fffff) | 0x800000;
-
-			double v = (double)s*(double)m*(Math.Pow(2, e-150));
-
-			return (float)v;
-		}
-
-		private void skipJunk(BinaryReader inStream)
-		{
-			try
-			{
-				for (int i = 0; (i < nextJunkOffset - 6) && (!endOfStream); i++)
-				{
-					endOfStream = inStream.ReadByte() < 0;
-				}
-			}
-			catch(Exception){endOfStream=true;};
-		}
-
-		private void readVertexList(BinaryReader inStream)
-		{
-			float x, y, z;
-			int vertices = readShort(inStream);
-			for (int i = 0; i < vertices; i++)
-			{
-				x = readFloat(inStream);
-				y = readFloat(inStream);
-				z = readFloat(inStream);
-
-				currentObject.addVertex(x, -y, z);
-			}
-		}
-
-		private void readPointList(BinaryReader inStream)
-		{
-			int v1, v2, v3;
-			int triangles = readShort(inStream);
-			for (int i = 0; i < triangles; i++)
-			{
-				v1 = readShort(inStream);
-				v2 = readShort(inStream);
-				v3 = readShort(inStream);
-
-				readShort(inStream);
-
-				currentObject.addTriangle(currentObject.vertex(v1),
-										  currentObject.vertex(v2),
-										  currentObject.vertex(v3));
-			}
-		}
-
-		private void readMappingCoordinates(BinaryReader inStream)
-		{
-			int vertices = readShort(inStream);
-			for (int i = 0; i < vertices; i++)
-			{
-				currentObject.vertex(i).u = readFloat(inStream);
-				currentObject.vertex(i).v = readFloat(inStream);
-			}
-		}
-	}
+        }
+
+        private void readJunkHeader(BinaryReader inStream)
+        {
+            currentJunkId = readShort(inStream);
+            nextJunkOffset = readInt(inStream);
+            endOfStream = currentJunkId < 0;
+        }
+
+        private int readInt(BinaryReader inStream)
+        {
+            return inStream.ReadByte() | (inStream.ReadByte() << 8) | (inStream.ReadByte() << 16) | (inStream.ReadByte() << 24);
+        }
+
+        private int readShort(BinaryReader inStream)
+        {
+            return (inStream.ReadByte() | (inStream.ReadByte() << 8));
+        }
+
+        private void readNextJunk(string name, BinaryReader inStream)
+        {
+            readJunkHeader(inStream);
+
+            if (currentJunkId == 0x3D3D /* mesh block */)
+            {
+                return;
+            }
+
+            if (currentJunkId == 0x4000 /* object block */)
+            {
+                currentObjectName = readString(inStream);
+                return;
+            }
+
+            if (currentJunkId == 0x4100 /* triangular polygon object */)
+            {
+                currentObject = new warp_Object();
+                _objects.Add(name + "_" + currentObjectName, currentObject);
+
+                return;
+            }
+
+            if (currentJunkId == 0x4110 /* vertex list */)
+            {
+                readVertexList(inStream);
+                return;
+            }
+
+            if (currentJunkId == 0x4120 /* point list */)
+            {
+                readPointList(inStream);
+                return;
+            }
+
+            if (currentJunkId == 0x4140 /* mapping coordinates */)
+            {
+                readMappingCoordinates(inStream);
+                return;
+            }
+
+            skipJunk(inStream);
+        }
+
+        private string readString(BinaryReader inStream)
+        {
+            string result = "";
+            byte inByte;
+            while ((inByte = (byte)inStream.ReadByte()) != 0)
+            {
+                result += (char)inByte;
+            }
+
+            return result;
+        }
+
+        private float readFloat(BinaryReader inStream)
+        {
+            int bits = readInt(inStream);
+
+            int s = ((bits >> 31) == 0) ? 1 : -1;
+            int e = ((bits >> 23) & 0xff);
+            int m = (e == 0) ? (bits & 0x7fffff) << 1 : (bits & 0x7fffff) | 0x800000;
+
+            double v = (double)s * (double)m * (Math.Pow(2, e - 150));
+
+            return (float)v;
+        }
+
+        private void skipJunk(BinaryReader inStream)
+        {
+            try
+            {
+                for (int i = 0; (i < nextJunkOffset - 6) && (!endOfStream); i++)
+                {
+                    endOfStream = inStream.ReadByte() < 0;
+                }
+            }
+            catch (Exception) { endOfStream = true; };
+        }
+
+        private void readVertexList(BinaryReader inStream)
+        {
+            float x, y, z;
+            int vertices = readShort(inStream);
+            for (int i = 0; i < vertices; i++)
+            {
+                x = readFloat(inStream);
+                y = readFloat(inStream);
+                z = readFloat(inStream);
+
+                currentObject.addVertex(x, -y, z);
+            }
+        }
+
+        private void readPointList(BinaryReader inStream)
+        {
+            int v1, v2, v3;
+            int triangles = readShort(inStream);
+            for (int i = 0; i < triangles; i++)
+            {
+                v1 = readShort(inStream);
+                v2 = readShort(inStream);
+                v3 = readShort(inStream);
+
+                readShort(inStream);
+
+                currentObject.addTriangle(currentObject.vertex(v1),
+                                          currentObject.vertex(v2),
+                                          currentObject.vertex(v3));
+            }
+        }
+
+        private void readMappingCoordinates(BinaryReader inStream)
+        {
+            int vertices = readShort(inStream);
+            for (int i = 0; i < vertices; i++)
+            {
+                float u = readFloat(inStream);
+                float v = readFloat(inStream);
+                currentObject.vertex(i).setUV(u, v);
+            }
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Camera.cs b/trunk/managed/Warp3Dmod/warp_Camera.cs
index 3c84045..27c33e7 100644
--- a/trunk/managed/Warp3Dmod/warp_Camera.cs
+++ b/trunk/managed/Warp3Dmod/warp_Camera.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
@@ -8,15 +9,15 @@ namespace Warp3D
     ///
     public class warp_Camera
     {
-        public warp_Matrix matrix = new warp_Matrix();
-        public warp_Matrix projmatrix = new warp_Matrix();
-        public warp_Matrix normalmatrix = new warp_Matrix();
+        public warp_Matrix matrix = new();
+        public warp_Matrix projmatrix = new();
+        public warp_Matrix normalmatrix = new();

         bool needsRebuild = true;   // Flag indicating changes on matrix

         // Camera settings
-        public warp_Vector pos = new warp_Vector(0f, 0f, 0f);
-        public warp_Vector lookat = new warp_Vector(0f, 0f, 0f);
+        public warp_Vector pos = warp_Vector.Zero;
+        public warp_Vector lookat = warp_Vector.Zero;
         public float rollfactor = 0f;

         public float fovfact;             // Field of View factor
@@ -39,12 +40,14 @@ namespace Warp3D
             setFov(fov);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Matrix getMatrix()
         {
             rebuildMatrices();
             return matrix;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Matrix getNormalMatrix()
         {
             rebuildMatrices();
@@ -59,20 +62,19 @@ namespace Warp3D

             warp_Vector forward, up, right;

-            forward = warp_Vector.sub(lookat, pos);
-            if(Math.Abs(forward.x) < 0.001f && Math.Abs(forward.z) < 0.001f)
+            forward = warp_Vector.sub(ref lookat, ref pos);
+            if(MathF.Abs(forward.x) < 0.001f && MathF.Abs(forward.z) < 0.001f)
             {
                 right = new warp_Vector(1f, 0f, 0f);
-                if(forward.y < 0)
-                    up = new warp_Vector(0f, 0f, 1f);
-                else
-                    up = new warp_Vector(0f, 0f, -1f);
+                up = new warp_Vector(0f, 0f, forward.y < 0 ? 1f : -1f);
             }
             else
             {
                 up = new warp_Vector(0f, 1f, 0f);
-                right = warp_Vector.getNormal(up, forward);
-                up = warp_Vector.getNormal(forward, right);
+                right = warp_Vector.vectorProduct(ref up, ref forward);
+                right.normalize();
+                up = warp_Vector.vectorProduct(ref forward, ref right);
+                up.normalize();
             }

             forward.normalize();
@@ -104,9 +106,10 @@ namespace Warp3D
             matrix = warp_Matrix.multiply(projmatrix, matrix);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setFov(float fov)
         {
-            fovfact = (float)Math.Tan(warp_Math.deg2rad(fov) / 2);
+            fovfact = MathF.Tan(warp_Math.deg2rad(fov) / 2);
             isOrthographic = false;
             needsRebuild = true;
         }
@@ -126,36 +129,42 @@ namespace Warp3D
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void roll(float angle)
         {
             rollfactor += angle;
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setPos(float px, float py, float pz)
         {
             pos = new warp_Vector(px, py, pz);
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setPos(warp_Vector p)
         {
             pos = p;
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void lookAt(float px, float py, float pz)
         {
             lookat = new warp_Vector(px, py, pz);
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void lookAt(warp_Vector p)
         {
             lookat = p;
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setScreensize(int w, int h)
         {
             screenwidth = w;
@@ -166,6 +175,7 @@ namespace Warp3D
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void shift(float dx, float dy, float dz)
         {
             pos.x += dx;
@@ -177,46 +187,53 @@ namespace Warp3D
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void shift(warp_Vector v)
         {
             shift(v.x, v.y, v.z);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void rotate(float dx, float dy, float dz)
         {
             pos = pos.transform(warp_Matrix.rotateMatrix(dx, dy, dz));
             needsRebuild = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void rotate(warp_Vector v)
         {
             rotate(v.x, v.y, v.z);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static warp_Camera FRONT()
         {
-            warp_Camera cam = new warp_Camera();
+            warp_Camera cam = new();
             cam.setPos(0, 0, -2f);
             return cam;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static warp_Camera LEFT()
         {
-            warp_Camera cam = new warp_Camera();
+            warp_Camera cam = new();
             cam.setPos(2f, 0, 0);
             return cam;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static warp_Camera RIGHT()
         {
-            warp_Camera cam = new warp_Camera();
+            warp_Camera cam = new();
             cam.setPos(-2f, 0, 0);
             return cam;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static warp_Camera TOP()
         {
-            warp_Camera cam = new warp_Camera();
+            warp_Camera cam = new();
             cam.setPos(0, -2f, 0);
             return cam;
         }
diff --git a/trunk/managed/Warp3Dmod/warp_Color.cs b/trunk/managed/Warp3Dmod/warp_Color.cs
index c6f4140..b68f563 100644
--- a/trunk/managed/Warp3Dmod/warp_Color.cs
+++ b/trunk/managed/Warp3Dmod/warp_Color.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;

 namespace Warp3D
@@ -8,66 +9,65 @@ namespace Warp3D
     /// </summary>
     public class warp_Color
     {
-        public static int MASKALPHA = unchecked((int)0xFF000000); // alpha mask
-        public static int MASKHALFALPHA = unchecked((int)0x7F000000); // alpha mask
-        public static int MASKRED = unchecked((int)0xFF0000);  // red mask
-        public static int MASKGREEN = unchecked((int)0xFF00);  // green mask
-        public static int MASKBLUE = unchecked((int)0xFF);  // blue mask
-        public static int MASKRB = unchecked((int)0x00FF00FF);  // mask for additive/subtractive shading
-        public static int MASKAG = unchecked((int)0xFF00FF00);  // mask for additive/subtractive shading
-        public static int RBHALF = unchecked((int)0x00800080);
-        public static int MASKRBHALF = unchecked((int)0xFF80FF80);
-        public static int MASKRBOVER = unchecked((int)0x01000100);
-        public static int MASK7Bit = unchecked((int)0x00FEFEFF);  // mask for additive/subtractive shading
-        public static int MASK6Bit = unchecked((int)0x00FCFCFC);  // mask for additive/subtractive shading
-        public static int MASK7BitA = unchecked((int)0x00FEFEFF);  // mask for additive/subtractive shading
-        public static int MASK6BitA = unchecked((int)0x00FCFCFC);  // mask for additive/subtractive shading
-        public static int MASKRGB = unchecked((int)0x00FFFFFF);  // rgb mask
-
-        public static int White = unchecked((int)0xFFFFFFFF);
-        public static int Grey = unchecked((int)0xFF7F7F7F);
-        public static int Black = unchecked((int)0xFF000000);
+        public const int MASKALPHA = unchecked((int)0xFF000000); // alpha mask
+        public const int MASKHALFALPHA = unchecked((int)0x7F000000); // alpha mask
+        public const int MASKRED = unchecked((int)0xFF0000);  // red mask
+        public const int MASKGREEN = unchecked((int)0xFF00);  // green mask
+        public const int MASKBLUE = unchecked((int)0xFF);  // blue mask
+        public const int MASKRB = unchecked((int)0x00FF00FF);  // mask for additive/subtractive shading
+        public const int MASKAG = unchecked((int)0xFF00FF00);  // mask for additive/subtractive shading
+        public const int RBHALF = unchecked((int)0x00800080);
+        public const int MASKRBHALF = unchecked((int)0xFF80FF80);
+        public const int MASKRBOVER = unchecked((int)0x01000100);
+        public const int MASK7Bit = unchecked((int)0x00FEFEFF);  // mask for additive/subtractive shading
+        public const int MASK6Bit = unchecked((int)0x00FCFCFC);  // mask for additive/subtractive shading
+        public const int MASK7BitA = unchecked((int)0x00FEFEFF);  // mask for additive/subtractive shading
+        public const int MASK6BitA = unchecked((int)0x00FCFCFC);  // mask for additive/subtractive shading
+        public const int MASKRGB = unchecked((int)0x00FFFFFF);  // rgb mask
+
+        public const int White = unchecked((int)0xFFFFFFFF);
+        public const int Grey = unchecked((int)0xFF7F7F7F);
+        public const int Black = unchecked((int)0xFF000000);

         public static int random(int color, int delta)
         {
-            Random rnd = new Random();
-
             int r = (color >> 16) & 0xff;
             int g = (color >> 8) & 0xff;
             int b = color & 0xff;

-            r += (int)(rnd.NextDouble() * (float)delta);
-            g += (int)(rnd.NextDouble() * (float)delta);
-            b += (int)(rnd.NextDouble() * (float)delta);
+            float df = delta;
+            r += (int)(Random.Shared.NextSingle() * df);
+            g += (int)(Random.Shared.NextSingle() * df);
+            b += (int)(Random.Shared.NextSingle() * df);

             return getCropColor(r, g, b);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int random()
         {
-            Random rnd = new Random();
-            return (int)(rnd.NextDouble() * 16777216);
+            return (int)(Random.Shared.NextSingle() * 16777216f);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getAlpha(int c)
         {
             return (c >> 24) & 0xff;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getRed(int c)
         {
             return (c >> 16) & 0xff;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getGreen(int c)
         {
             return (c >> 8) & 0xff;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getBlue(int c)
         {
             return c & 0xff;
@@ -77,49 +77,50 @@ namespace Warp3D
         {
             int[] pal = new int[size];
             int c1, c2, pos1, pos2, range;
-            int r, g, b, r1, g1, b1, r2, g2, b2, dr, dg, db;
-            if(colors.GetLength(0) == 1)
+            int r1, g1, b1, r2, g2, b2, dr, dg, db;
+            int clen = colors.GetLength(0) - 1;
+            if (clen == 0)
             {
                 c1 = colors[0];
-                for(int i = 0; i < size; i++)
+                for(int i = 0; i < pal.Length; i++)
                 {
                     pal[i] = c1;
                 }
                 return pal;
             }
-
-            for(int c = 0; c < colors.GetLength(0) - 1; c++)
+            ref int cref = ref MemoryMarshal.GetArrayDataReference(colors);
+            ref int palref = ref MemoryMarshal.GetArrayDataReference(pal);
+            int invclenm1 = 1 / clen;
+            for (int c = 0; c < clen; c++)
             {
-                c1 = colors[c];
-                c2 = colors[c + 1];
-                pos1 = size * c / (colors.GetLength(0) - 1);
-                pos2 = size * (c + 1) / (colors.GetLength(0) - 1);
+                c1 = Unsafe.As<int, int>(ref Unsafe.Add(ref cref, c));
+                c2 = Unsafe.As<int, int>(ref Unsafe.Add(ref cref, c + 1));
+                pos1 = size * c * invclenm1;
+                pos2 = size * (c + 1) * invclenm1;
                 range = pos2 - pos1;
+                range = 1 / range;
                 r1 = warp_Color.getRed(c1) << 16;
                 g1 = warp_Color.getGreen(c1) << 16;
                 b1 = warp_Color.getBlue(c1) << 16;
                 r2 = warp_Color.getRed(c2) << 16;
                 g2 = warp_Color.getGreen(c2) << 16;
                 b2 = warp_Color.getBlue(c2) << 16;
-                dr = (r2 - r1) / range;
-                dg = (g2 - g1) / range;
-                db = (b2 - b1) / range;
-                r = r1;
-                g = g1;
-                b = b1;
+                dr = (r2 - r1) * range;
+                dg = (g2 - g1) * range;
+                db = (b2 - b1) * range;
                 for(int i = pos1; i < pos2; i++)
                 {
-                    pal[i] = getColor(r >> 16, g >> 16, b >> 16);
-                    r += dr;
-                    g += dg;
-                    b += db;
+                    Unsafe.As<int, int>(ref Unsafe.Add(ref palref, i)) = getColor(r1 >> 16, g1 >> 16, b1 >> 16);
+                    r1 += dr;
+                    g1 += dg;
+                    b1 += db;
                 }
             }

             return pal;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int add(int color1, int color2)
         {
             int t1,t2,t3,t4;
@@ -139,57 +140,24 @@ namespace Warp3D
             return (t4 << 8) | t3;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int avg2c(int color1, int color2)
         {
-            int t1,t2,t3,t4;
-
-            t1 = color1 & MASKRB;
-            t2 = color2 & MASKRB;
-            t3 = t1 + t2 + 0x00010001;
-            t3 >>= 1;
-            t3 &= MASKRB;
+            int t1 = (color1 & MASKRB) + (color2 & MASKRB);
+            t1 >>= 1;
+            t1 &= MASKRB;

-            t1 = (color1 >> 8) & MASKRB;
-            t2 = (color2 >> 8) & MASKRB;
-            t4 = t1 + t2 + 0x00010001;
-            t4 >>= 1;
-            t4 &= MASKRB;
+            long t2 = (color1 & MASKAG) + (color2 & MASKAG);
+            t2 >>= 1;
+            t2 &= MASKAG;

-            return (t4 << 8) | t3;
+            return (int)t2 | t1;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static int avg4c(int color1, int color2, int color3, int color4)
-        {
-            int t1,t2,t3,t4;
-
-            t1 = color1 & MASKRB;
-            t2 = color2 & MASKRB;
-            t3 = t1 + t2;
-            t1 = color3 & MASKRB;
-            t2 = color4 & MASKRB;
-            t3 += t1 + t2 + 0x00020002;
-            t3 >>= 2;
-            t3 &= MASKRB;
-
-            t1 = (color1 >> 8) & MASKRB;
-            t2 = (color2 >> 8) & MASKRB;
-            t4 = t1 + t2 + 0x00020002;;
-            t1 = (color3 >> 8) & MASKRB;
-            t2 = (color4 >> 8) & MASKRB;
-            t4 += t1 + t2;
-            t4 >>= 2;
-            t4 &= MASKRB;
-
-            return (t4 << 8) | t3;
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int sub(int color1, int color2)
         // Substracts color2 from color1
         {
-
             int t1,t2,t3,t4;

             t1 = color1 & MASKRB;
@@ -205,15 +173,8 @@ namespace Warp3D
             t4 &= MASKRB;

             return (t4 << 8) | t3;
-
-/*
-            int pixel = (color1 & MASK7Bit) + (~color2 & MASK7Bit);
-            int overflow = ~pixel & 0x1010100;
-            overflow = overflow - (overflow >> 8);
-            return ALPHA | (~overflow & pixel);
-*/
         }
-/*
+        /*
         public static int subneg(int color1, int color2)
         // Substracts the negative of color2 from color1
         {
@@ -229,15 +190,15 @@ namespace Warp3D
             color = (~color) &  RGB;
             return ALPHA | color;
         }
-*/
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        */
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int mix(int color1, int color2)
         // Returns the averidge color from 2 colors
         {
             return MASKALPHA | (((color1 & MASK7Bit) >> 1) + ((color2 & MASK7Bit) >> 1));
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int scale(int color, int factor)
         {
             if(factor == 255)
@@ -256,7 +217,7 @@ namespace Warp3D
             return a | RB | b;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int multiply(int color1, int color2)
         {
             int t1, t2, t3, t4;
@@ -276,46 +237,25 @@ namespace Warp3D
             t4 = (t1 & 0xff) * (t2 & 0xff); // g on g
             t4 |= (t1 & MASKRED) * ((t2 >> 16) & 0xff); // a on a
             t4 += RBHALF; // add halfbit
-            t4 = (t4 + ((t4 >> 8) & MASKRB));
+            t4 += (t4 >> 8) & MASKRB;
             t4 &= MASKAG;

             return t3 | t4;
-/*
-            int a;
-            int r = (color1 >> 24 ) & 0xff;
-            int g = (color2 >> 24 ) & 0xff;
-            if( r == 0xff && g == 0xff)
-                a = ALPHA;
-            else
-            {
-                a = ((r * g)) & 0xff00;
-                a <<= 16;
-            }
-
-            if((color1 & RGB) == 0 && (color2 & RGB) == 0)
-                return a;
-
-            r = unchecked((((color1 >> 16) & 0xff) * ((color2 >> 16) & 0xff)) & 0xff00);
-            g = (((color1 >> 8) & 0xff) * ((color2 >> 8) & 0xff)) & 0xff00;
-            int b = ((color1 & 0xff) * (color2 & 0xff)) >> 8;
-            return a | r << 8 | g | b;
-*/
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int transparency(int bkgrd, int color, int alpha)
         {
-            if(alpha == 0)
-            {
-                return bkgrd;
-            }
-            if(alpha == 255)
-            {
-                return color;
-            }
-            if(alpha == 127)
+            switch(alpha)
             {
-                return mix(bkgrd, color);
+                case 0:
+                    return bkgrd;
+                case 255:
+                    return color;
+                case 127:
+                    return mix(bkgrd, color);
+                default:
+                    break;
             }

             int colorRB = bkgrd & 0xff00ff;
@@ -329,22 +269,21 @@ namespace Warp3D
             return MASKALPHA | colorRB | colorg;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         // blends color alpha, but result image is solid
         public static int overSolid(int bkgrd, int color)
         {
             int alpha = color & MASKALPHA;
-            if(alpha == 0)
-            {
-                return bkgrd;
-            }
-            if(alpha == Black)
-            {
-                return color;
-            }
-            if(alpha == MASKHALFALPHA)
+            switch(alpha)
             {
-                return mix(bkgrd, color);
+                case 0:
+                    return bkgrd;
+                case Black:
+                    return color;
+                case MASKHALFALPHA:
+                    return mix(bkgrd, color);
+                default:
+                    break;
             }
             alpha = (alpha >> 24) & 0xff;
             int colorRB = bkgrd & MASKRB;
@@ -358,34 +297,31 @@ namespace Warp3D
             return MASKALPHA | colorRB | colorg;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getCropColor(int r, int g, int b)
         {
             return MASKALPHA | (warp_Math.crop(r, 0, 255) << 16) | (warp_Math.crop(g, 0, 255) << 8) | warp_Math.crop(b, 0, 255);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getCropColor(int r, int g, int b, int a)
         {
-            return (warp_Math.crop(a , 0, 255) << 24) |
-                    (warp_Math.crop(r, 0, 255) << 16) |
-                    (warp_Math.crop(g, 0, 255) << 8) |
-                    warp_Math.crop(b, 0, 255);
+            return (warp_Math.crop(a, 0, 255) << 24) | (warp_Math.crop(r, 0, 255) << 16) | (warp_Math.crop(g, 0, 255) << 8) | warp_Math.crop(b, 0, 255);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getColor(int r, int g, int b)
         {
             return MASKALPHA | (r << 16) | (g << 8) | b;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getColor(int r, int g, int b, int a)
         {
             return (a << 24) | (r << 16) | (g << 8) | b;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getGray(int color)
         {
             int r = ((color & MASKRED) >> 16);
@@ -395,7 +331,7 @@ namespace Warp3D
             return (color & MASKALPHA) | (Y << 16) | (Y << 8) | Y;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int getAverage(int color)
         {
             return (((color & MASKRED) >> 16) + ((color & MASKGREEN) >> 8) + (color & MASKBLUE)) / 3;
diff --git a/trunk/managed/Warp3Dmod/warp_CoreObject.cs b/trunk/managed/Warp3Dmod/warp_CoreObject.cs
index 4f121f4..ee41d03 100644
--- a/trunk/managed/Warp3Dmod/warp_CoreObject.cs
+++ b/trunk/managed/Warp3Dmod/warp_CoreObject.cs
@@ -1,115 +1,134 @@
 using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_CoreObject.
-	/// </summary>
-	///
-
-	public class warp_CoreObject
-	{
-		public warp_Matrix matrix=new warp_Matrix();
-		public warp_Matrix normalmatrix=new warp_Matrix();
-
-		public void transform(warp_Matrix m)
-		{
-			matrix.transform(m);
-			normalmatrix.transform(m);
-		}
-
-		public void shift(float dx, float dy, float dz)
-		{
-			matrix.shift(dx,dy,dz);
-		}
+    /// <summary>
+    /// Summary description for warp_CoreObject.
+    /// </summary>
+    ///
+
+    public class warp_CoreObject
+    {
+        public warp_Matrix matrix = new();
+        public warp_Matrix normalmatrix = new();
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void transform(warp_Matrix m)
+        {
+            matrix.transform(m);
+            normalmatrix.transform(m);
+        }

-        public void shift( warp_Vector v )
-		{
-			matrix.shift(v.x,v.y,v.z);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void shift(float dx, float dy, float dz)
+        {
+            matrix.shift(dx, dy, dz);
+        }

-		public void scale(float d)
-		{
-			matrix.scale(d);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void shift(warp_Vector v)
+        {
+            matrix.shift(v.x, v.y, v.z);
+        }

-		public void scale(float dx, float dy, float dz)
-		{
-			matrix.scale(dx,dy,dz);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void scale(float d)
+        {
+            matrix.scale(d);
+        }

-		public void scaleSelf(float d)
-		{
-			matrix.scaleSelf(d);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void scale(float dx, float dy, float dz)
+        {
+            matrix.scale(dx, dy, dz);
+        }

-		public void scaleSelf(float dx, float dy, float dz)
-		{
-			matrix.scaleSelf(dx,dy,dz);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void scaleSelf(float d)
+        {
+            matrix.scaleSelf(d);
+        }

-		public void rotate(warp_Vector d)
-		{
-			rotateSelf(d.x,d.y,d.z);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void scaleSelf(float dx, float dy, float dz)
+        {
+            matrix.scaleSelf(dx, dy, dz);
+        }

-		public void rotateSelf(warp_Vector d)
-		{
-			rotateSelf(d.x,d.y,d.z);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotate(warp_Vector d)
+        {
+            rotateSelf(d.x, d.y, d.z);
+        }

-		public void rotate(float dx, float dy, float dz)
-		{
-			matrix.rotate(dx,dy,dz);
-			normalmatrix.rotate(dx,dy,dz);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotateSelf(warp_Vector d)
+        {
+            rotateSelf(d.x, d.y, d.z);
+        }

-        public void rotate( warp_Quaternion quat, float x, float y, float z )
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotate(float dx, float dy, float dz)
         {
-            matrix.rotate( quat ,  x,  y,  z);
-            normalmatrix.rotate( quat ,  x,  y,  z);
+            matrix.rotate(dx, dy, dz);
+            normalmatrix.rotate(dx, dy, dz);
         }

-        public void rotate( warp_Matrix m )
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotate(warp_Quaternion quat, float x, float y, float z)
         {
-            matrix.rotate( m );
-            normalmatrix.rotate( m );
+            matrix.rotate(quat, x, y, z);
+            normalmatrix.rotate(quat, x, y, z);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotate(warp_Matrix m)
+        {
+            matrix.rotate(m);
+            normalmatrix.rotate(m);
+        }

-		public void rotateSelf(float dx, float dy, float dz)
-		{
-			matrix.rotateSelf(dx,dy,dz);
-			normalmatrix.rotateSelf(dx,dy,dz);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotateSelf(float dx, float dy, float dz)
+        {
+            matrix.rotateSelf(dx, dy, dz);
+            normalmatrix.rotateSelf(dx, dy, dz);
+        }

-        public void rotateSelf( warp_Quaternion quat )
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotateSelf(warp_Quaternion quat)
         {
-            matrix.rotateSelf( quat );
-            normalmatrix.rotateSelf( quat );
+            matrix.rotateSelf(quat);
+            normalmatrix.rotateSelf(quat);
         }

-        public void rotateSelf( warp_Matrix m )
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void rotateSelf(warp_Matrix m)
         {
-            matrix.rotateSelf( m );
-            normalmatrix.rotateSelf( m );
+            matrix.rotateSelf(m);
+            normalmatrix.rotateSelf(m);
         }

-        public void setPos( float x, float y, float z )
-		{
-			matrix.m03=x;
-			matrix.m13=y;
-			matrix.m23=z;
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setPos(float x, float y, float z)
+        {
+            matrix.m03 = x;
+            matrix.m13 = y;
+            matrix.m23 = z;
+        }

-		public void setPos(warp_Vector v)
-		{
-			setPos(v.x,v.y,v.z);
-		}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setPos(warp_Vector v)
+        {
+            setPos(v.x, v.y, v.z);
+        }

-		public warp_Vector getPos()
-		{
-			return new warp_Vector(matrix.m03,matrix.m13,matrix.m23);
-		}
-	}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public warp_Vector getPos()
+        {
+            return new warp_Vector(matrix.m03, matrix.m13, matrix.m23);
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Edge.cs b/trunk/managed/Warp3Dmod/warp_Edge.cs
index caa0d69..fad6fe3 100644
--- a/trunk/managed/Warp3Dmod/warp_Edge.cs
+++ b/trunk/managed/Warp3Dmod/warp_Edge.cs
@@ -2,32 +2,32 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_Edge.
-	/// </summary>
-	///
-	public class warp_Edge
-	{
-		warp_Vertex a,b;
+    /// <summary>
+    /// Summary description for warp_Edge.
+    /// </summary>
+    ///
+    public class warp_Edge
+    {
+        warp_Vertex a, b;

-		public warp_Edge()
-		{
-		}
+        public warp_Edge()
+        {
+        }

-		public warp_Edge(warp_Vertex v1, warp_Vertex v2)
-		{
-			a=v1;
-			b=v2;
-		}
+        public warp_Edge(warp_Vertex v1, warp_Vertex v2)
+        {
+            a = v1;
+            b = v2;
+        }

-		public warp_Vertex start()
-		{
-			return a;
-		}
-
-		public warp_Vertex end()
-		{
-			return b;
-		}
-	}
+        public warp_Vertex start()
+        {
+            return a;
+        }
+
+        public warp_Vertex end()
+        {
+            return b;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Environment.cs b/trunk/managed/Warp3Dmod/warp_Environment.cs
index 0293199..9add65b 100644
--- a/trunk/managed/Warp3Dmod/warp_Environment.cs
+++ b/trunk/managed/Warp3Dmod/warp_Environment.cs
@@ -2,21 +2,21 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_Environment.
-	/// </summary>
-	public class warp_Environment
-	{
-		public int ambient=0;
-		public int fogcolor=0;
-		public int fogfact=0;
-		public int bgcolor= warp_Color.White;
+    /// <summary>
+    /// Summary description for warp_Environment.
+    /// </summary>
+    public class warp_Environment
+    {
+        public int ambient = 0;
+        public int fogcolor = 0;
+        public int fogfact = 0;
+        public int bgcolor = warp_Color.White;

-		public warp_Texture background=null;
+        public warp_Texture background = null;

-		public void setBackground(warp_Texture t)
-		{
-			background=t;
-		}
-	}
+        public void setBackground(warp_Texture t)
+        {
+            background = t;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_FXLensFlare .cs b/trunk/managed/Warp3Dmod/warp_FXLensFlare .cs
index b6e1b64..0b66fad 100644
--- a/trunk/managed/Warp3Dmod/warp_FXLensFlare .cs
+++ b/trunk/managed/Warp3Dmod/warp_FXLensFlare .cs
@@ -6,347 +6,346 @@ namespace Warp3D
 {
     public class warp_FXLensFlare : warp_FXPlugin
     {
-	    public warp_Object flareObject;
-
-	    private int flares=0;
-	    private bool zBufferSensitive=true;
-	    private warp_Texture[] flare;
-	    private float[] flareDist;
-
-	    private warp_FXLensFlare(warp_Scene scene) : base( scene )
-	    {
-	    }
-
-        public warp_FXLensFlare( String name, warp_Scene scene, bool zBufferSensitive ) : base( scene )
-	    {
+        public warp_Object flareObject;
+
+        private int flares = 0;
+        private bool zBufferSensitive = true;
+        private warp_Texture[] flare;
+        private float[] flareDist;
+
+        private warp_FXLensFlare(warp_Scene scene) : base(scene)
+        {
+        }
+
+        public warp_FXLensFlare(string name, warp_Scene scene, bool zBufferSensitive) : base(scene)
+        {
             this.zBufferSensitive = zBufferSensitive;

-		    flareObject=new warp_Object();
-		    flareObject.addVertex(new warp_Vertex(1f,1f,1f));
-		    flareObject.rebuild();
-
-		    scene.addObject(name, flareObject);
-	    }
-
-	    public void preset1()
-	    {
-		    clear();
-
-		    addGlow(144,0x330099);
-		    addStrike(320,48,0x003366);
-		    addStrike(48,240,0x660033);
-		    addRing(120,0x660000);
-		    addRays(320, 32, 20, 0x111111);
-		    addSecs(12,100,64,0x6633cc,64);
-	    }
-
-	    public void preset2()
-	    {
-		    clear();
-		    addGlow(144,0x995500);
-		    addStrike(640,64,0xCC0000);
-	        addStrike(32,480,0x0000FF);
-		    addStrike(64,329,0x330099);
-		    addRing(160,0x990000);
-		    addRays(320, 24, 32, 0x332211);
-		    addSecs(12,100,64,0x333333,100);
-		    addSecs(12,60,40,0x336699,80);
-	    }
-
-	    public void preset3()
-	    {
-		    clear();
-		    addGlow(144,0x993322);
-		    addStrike(400,200,0xCC00FF);
-		    addStrike(480,32,0x0000FF);
-		    addRing(180,0x990000);
-		    addRays(240, 32, 48, 0x332200);
-		    addSecs(12,80,64,0x555555,50);
-		    addSecs(12,60,40,0x336699,80);
-	    }
-
-	    public void setPos(warp_Vector pos)
-	    {
-		    flareObject.fastvertex[0].pos=pos;
-	    }
-
-	    public void clear()
-	    {
-	    	flares=0;
-	    	flare=null;
-	    	flareDist=null;
-	    }
-
-	    public void addGlow(int size, int color)
-	    {
-	    	addFlare(createGlow(size,size,color,256),0f);
-	    }
-
-	    public void addStrike(int width, int height, int color)
-	    {
-	    	addFlare(createGlow(width,height,color,48),0f);
-	    }
-
-	    public void addRing(int size, int color)
-	    {
-	    	addFlare(createRing(size,color),0f);
-	    }
-
-	    public void addRays(int size, int num, int rad, int color)
-	    {
-	    	addFlare(createRays(size, num, rad, color),0f);
-	    }
-
-        public void addSecs( int count, int averidgeSize, int sizeDelta, int averidgeColor, int colorDelta )
+            flareObject = new();
+            flareObject.addVertex(new warp_Vertex(1f, 1f, 1f));
+            flareObject.rebuild();
+
+            scene.addObject(name, flareObject);
+        }
+
+        public void preset1()
+        {
+            clear();
+
+            addGlow(144, 0x330099);
+            addStrike(320, 48, 0x003366);
+            addStrike(48, 240, 0x660033);
+            addRing(120, 0x660000);
+            addRays(320, 32, 20, 0x111111);
+            addSecs(12, 100, 64, 0x6633cc, 64);
+        }
+
+        public void preset2()
+        {
+            clear();
+            addGlow(144, 0x995500);
+            addStrike(640, 64, 0xCC0000);
+            addStrike(32, 480, 0x0000FF);
+            addStrike(64, 329, 0x330099);
+            addRing(160, 0x990000);
+            addRays(320, 24, 32, 0x332211);
+            addSecs(12, 100, 64, 0x333333, 100);
+            addSecs(12, 60, 40, 0x336699, 80);
+        }
+
+        public void preset3()
+        {
+            clear();
+            addGlow(144, 0x993322);
+            addStrike(400, 200, 0xCC00FF);
+            addStrike(480, 32, 0x0000FF);
+            addRing(180, 0x990000);
+            addRays(240, 32, 48, 0x332200);
+            addSecs(12, 80, 64, 0x555555, 50);
+            addSecs(12, 60, 40, 0x336699, 80);
+        }
+
+        public void setPos(warp_Vector pos)
+        {
+            flareObject.vertexData[0].pos = pos;
+        }
+
+        public void clear()
+        {
+            flares = 0;
+            flare = null;
+            flareDist = null;
+        }
+
+        public void addGlow(int size, int color)
+        {
+            addFlare(createGlow(size, size, color, 256), 0f);
+        }
+
+        public void addStrike(int width, int height, int color)
+        {
+            addFlare(createGlow(width, height, color, 48), 0f);
+        }
+
+        public void addRing(int size, int color)
         {
-            for ( int i = 0; i < count; i++ )
+            addFlare(createRing(size, color), 0f);
+        }
+
+        public void addRays(int size, int num, int rad, int color)
+        {
+            addFlare(createRays(size, num, rad, color), 0f);
+        }
+
+        public void addSecs(int count, int averidgeSize, int sizeDelta, int averidgeColor, int colorDelta)
+        {
+            for (int i = 0; i < count; i++)
             {
-                addFlare( createSec( averidgeSize, sizeDelta, averidgeColor, colorDelta ), warp_Math.random( -0.5f, 3f ) );
+                addFlare(createSec(averidgeSize, sizeDelta, averidgeColor, colorDelta), warp_Math.random(-0.5f, 3f));

             }
         }
-
-		override public void apply()
-		{
-            int px = flareObject.fastvertex[ 0 ].x;
-            int py = flareObject.fastvertex[ 0 ].y;

-            if ( !flareObject.fastvertex[ 0 ].visible )
+        override public void apply()
+        {
+            if (flareObject.vertexData[0].clipcode > 0)
+                return;
+
+            int px = flareObject.vertexData[0].x;
+            int py = flareObject.vertexData[0].y;
+
+            if (zBufferSensitive && (flareObject.vertexData[0].z > scene.renderPipeline.zBuffer[px + py * screen.width]))
             {
                 return;
             }
-            if ( zBufferSensitive && ( flareObject.fastvertex[ 0 ].z > scene.renderPipeline.zBuffer[ px + py * screen.width ] ) )
+
+            int cx = screen.width / 2;
+            int cy = screen.height / 2;
+
+            float dx = (float)(cx - px);
+            float dy = (float)(cy - py);
+            int posx, posy, xsize, ysize;
+            float zoom;
+
+            for (int i = 0; i < flares; i++)
             {
-                return;
+                zoom = warp_Math.pythagoras(dx, dy) / warp_Math.pythagoras(cx, cy);
+                zoom = (1 - zoom) / 2 + 1;
+                xsize = flare[i].width;
+                ysize = flare[i].height;
+                posx = px + (int)(dx * flareDist[i]);
+                posy = py + (int)(dy * flareDist[i]);
+
+                screen.add(flare[i], posx - xsize / 2, posy - ysize / 2, xsize, ysize);
             }
+        }
+
+        private void addFlare(warp_Texture texture, float relPos)
+        {
+            flares++;
+
+            if (flares == 1)
+            {
+                flare = new warp_Texture[1];
+                flareDist = new float[1];
+            }
+            else
+            {
+                warp_Texture[] temp1 = new warp_Texture[flares];
+                System.Array.Copy(flare, 0, temp1, 0, flares - 1); // check this
+                flare = temp1;

-			int cx=screen.width/2;
-			int cy=screen.height/2;
-
-			float dx=(float)(cx-px);
-			float dy=(float)(cy-py);
-			int posx,posy,xsize,ysize;
-			float zoom;
-
-			for (int i=0; i<flares;i++)
-			{
-			    zoom=warp_Math.pythagoras(dx,dy)/warp_Math.pythagoras(cx,cy);
-				zoom=(1-zoom)/2+1;
-				xsize=flare[i].width;
-				ysize=flare[i].height;
-				posx=px+(int)(dx*flareDist[i]);
-				posy=py+(int)(dy*flareDist[i]);
-
-				screen.add(flare[i],posx-xsize/2,posy-ysize/2,xsize,ysize);
-			}
-		}
-
-		private void addFlare(warp_Texture texture, float relPos)
-		{
-			flares++;
-
-			if (flares == 1)
-			{
-				flare=new warp_Texture[1];
-				flareDist=new float[1];
-			}
-			else
-			{
-				warp_Texture[] temp1=new warp_Texture[flares];
-				System.Array.Copy(flare,0,temp1,0,flares-1); // check this
-				flare=temp1;
-
-				float[] temp2=new float[flares];
-                System.Array.Copy(flareDist, 0, temp2, 0, flares - 1 );
-				flareDist=temp2;
-			}
-
-			flare[flares-1]=texture;
-			flareDist[flares-1]=relPos;
-		}
-
-		private warp_Texture createRadialTexture(int w, int h, int[] colormap, int[] alphamap)
-		{
-			int offset;
-			float relX,relY;
-			warp_Texture newTexture=new warp_Texture(w,h);
-			int[] palette=getPalette(colormap, alphamap);
-
-			for(int y=h-1;y>=0;y--)
-			{
-				offset=y*w;
-				for (int x=w-1;x>=0;x--)
-				{
-					relX=(float)(x-(w>>1))/(float)(w>>1);
-					relY=(float)(y-(h>>1))/(float)(h>>1);
-					newTexture.pixel[offset+x]=palette[warp_Math.crop((int)(255*Math.Sqrt(relX*relX+relY*relY)),0,255)];
-				}
-			}
-
-			return newTexture;
-		}
-
-		private int[] getPalette(int[] color, int[] alpha)
-		{
-			int r,g,b;
-			int[] palette=new int[256];
-			for (int i=255;i>=0;i--)
-			{
-				r=(((color[i]>>16)&255)*alpha[i])>>8;
-				g=(((color[i]>>8)&255)*alpha[i])>>8;
-				b=((color[i]&255)*alpha[i])>>8;
-				palette[i]=warp_Color.getColor(r,g,b);
-			}
-			return palette;
-		}
-
-		private warp_Texture createGlow(int w, int h, int color, int alpha)
-		{
-			return createRadialTexture(w,h,getGlowPalette(color),getConstantAlpha(alpha));
-		}
-
-		private warp_Texture createRing(int size, int color)
-		{
-			return createRadialTexture(size,size,getColorPalette(color,color),getRingAlpha(40));
-		}
-
-		private warp_Texture createSec(int size, int sizedelta, int color, int colordelta)
-		{
-			int s=(int)warp_Math.randomWithDelta(size,sizedelta);
-			int c1=warp_Color.random(color,colordelta);
-			int c2=warp_Color.random(color,colordelta);
-			return createRadialTexture(s,s,getColorPalette(c1,c2),getSecAlpha());
-		}
-
-		private warp_Texture createRays(int size, int rays, int rad, int color)
-		{
-			int pos;
+                float[] temp2 = new float[flares];
+                System.Array.Copy(flareDist, 0, temp2, 0, flares - 1);
+                flareDist = temp2;
+            }
+
+            flare[flares - 1] = texture;
+            flareDist[flares - 1] = relPos;
+        }
+
+        private warp_Texture createRadialTexture(int w, int h, int[] colormap, int[] alphamap)
+        {
+            int offset;
+            float relX, relY;
+            warp_Texture newTexture = new warp_Texture(w, h);
+            int[] palette = getPalette(colormap, alphamap);
+
+            for (int y = h - 1; y >= 0; y--)
+            {
+                offset = y * w;
+                for (int x = w - 1; x >= 0; x--)
+                {
+                    relX = (float)(x - (w >> 1)) / (float)(w >> 1);
+                    relY = (float)(y - (h >> 1)) / (float)(h >> 1);
+                    newTexture.pixel[offset + x] = palette[warp_Math.crop((int)(255 * Math.Sqrt(relX * relX + relY * relY)), 0, 255)];
+                }
+            }
+
+            return newTexture;
+        }
+
+        private int[] getPalette(int[] color, int[] alpha)
+        {
+            int r, g, b;
+            int[] palette = new int[256];
+            for (int i = 255; i >= 0; i--)
+            {
+                r = (((color[i] >> 16) & 255) * alpha[i]) >> 8;
+                g = (((color[i] >> 8) & 255) * alpha[i]) >> 8;
+                b = ((color[i] & 255) * alpha[i]) >> 8;
+                palette[i] = warp_Color.getColor(r, g, b);
+            }
+            return palette;
+        }
+
+        private warp_Texture createGlow(int w, int h, int color, int alpha)
+        {
+            return createRadialTexture(w, h, getGlowPalette(color), getConstantAlpha(alpha));
+        }
+
+        private warp_Texture createRing(int size, int color)
+        {
+            return createRadialTexture(size, size, getColorPalette(color, color), getRingAlpha(40));
+        }
+
+        private warp_Texture createSec(int size, int sizedelta, int color, int colordelta)
+        {
+            int s = (int)warp_Math.randomWithDelta(size, sizedelta);
+            int c1 = warp_Color.random(color, colordelta);
+            int c2 = warp_Color.random(color, colordelta);
+            return createRadialTexture(s, s, getColorPalette(c1, c2), getSecAlpha());
+        }
+
+        private warp_Texture createRays(int size, int rays, int rad, int color)
+        {
+            int pos;
             float relPos;
-			warp_Texture texture=new warp_Texture(size,size);
-			int[] radialMap=new int [1024];
-			warp_Math.clearBuffer(radialMap, 0);
-
-			for (int i=0;i<rays;i++)
-			{
-				pos=(int)warp_Math.random(rad,1023-rad);
-				for (int k=pos-rad; k<=pos+rad; k++)
-				{
-					relPos=(float)(k-pos+rad)/(float)(rad*2);
-					radialMap[k]+=(int)(255*(1+Math.Sin((relPos-0.25)*3.14159*2))/2);
-				}
-			}
-
-			int angle,offset,reldist;
-			float xrel,yrel;
-			for (int y=size-1;y>=0;y--)
-			{
-				offset=y*size;
-				for (int x=size-1;x>=0;x--)
-				{
-					xrel=(float)(2*x-size)/(float)size;
-					yrel=(float)(2*y-size)/(float)size;
-					angle=(int)(1023*Math.Atan2(xrel,yrel)/3.14159/2)&1023;
-					reldist=Math.Max((int)(255-255*warp_Math.pythagoras(xrel,yrel)),0);
-					texture.pixel[x+offset]=warp_Color.scale(color, radialMap[angle]*reldist/255);
-				}
-			}
-
-			return texture;
-		}
-
-		private int[] getGlowPalette(int color)
-		{
-			int r,g,b;
-			float relDist,diffuse,specular;
-			int[] palette=new int[256];
-			int cr=(color>>16)&255;
-			int cg=(color>>8)&255;
-			int cb=color&255;
-			for (int i=255;i>=0;i--)
-			{
-				relDist=(float)i/255;
-				diffuse=(float)Math.Cos(relDist*1.57);
-				specular=(float)(255/Math.Pow(2.718,relDist*2.718)-(float)i/16);
-				r=(int)((float)cr*diffuse+specular);
-				g=(int)((float)cg*diffuse+specular);
-				b=(int)((float)cb*diffuse+specular);
-				palette[i]=warp_Color.getCropColor(r,g,b);
-			}
-
+            warp_Texture texture = new warp_Texture(size, size);
+            int[] radialMap = new int[1024];
+            warp_Math.clearBuffer(radialMap, 0);
+
+            for (int i = 0; i < rays; i++)
+            {
+                pos = (int)warp_Math.random(rad, 1023 - rad);
+                for (int k = pos - rad; k <= pos + rad; k++)
+                {
+                    relPos = (float)(k - pos + rad) / (float)(rad * 2);
+                    radialMap[k] += (int)(255 * (1f + MathF.Sin((relPos - 0.25f) * 3.14159f * 2f)) / 2f);
+                }
+            }
+
+            int angle, offset, reldist;
+            float xrel, yrel;
+            for (int y = size - 1; y >= 0; y--)
+            {
+                offset = y * size;
+                for (int x = size - 1; x >= 0; x--)
+                {
+                    xrel = (float)(2 * x - size) / (float)size;
+                    yrel = (float)(2 * y - size) / (float)size;
+                    angle = (int)(1023 * MathF.Atan2(xrel, yrel) / 3.14159 / 2) & 1023;
+                    reldist = Math.Max((int)(255 - 255 * warp_Math.pythagoras(xrel, yrel)), 0);
+                    texture.pixel[x + offset] = warp_Color.scale(color, radialMap[angle] * reldist / 255);
+                }
+            }
+
+            return texture;
+        }
+
+        private int[] getGlowPalette(int color)
+        {
+            int r, g, b;
+            float relDist, diffuse, specular;
+            int[] palette = new int[256];
+            int cr = (color >> 16) & 255;
+            int cg = (color >> 8) & 255;
+            int cb = color & 255;
+            for (int i = 255; i >= 0; i--)
+            {
+                relDist = (float)i / 255f;
+                diffuse = MathF.Cos(relDist * 1.57f);
+                specular = (float)(255f / MathF.Pow(2.718f, relDist * 2.718f) - (float)i / 16f);
+                r = (int)((float)cr * diffuse + specular);
+                g = (int)((float)cg * diffuse + specular);
+                b = (int)((float)cb * diffuse + specular);
+                palette[i] = warp_Color.getCropColor(r, g, b);
+            }
+
             return palette;
-		}
-
-		private int[] getConstantAlpha(int alpha)
-		{
-			int[] alphaPalette=new int[256];
-			for (int i=255;i>=0;i--) alphaPalette[i]=alpha;
-
+        }
+
+        private int[] getConstantAlpha(int alpha)
+        {
+            int[] alphaPalette = new int[256];
+            for (int i = 255; i >= 0; i--) alphaPalette[i] = alpha;
+
             return alphaPalette;
-		}
-
-		private int[] getLinearAlpha()
-		{
-			int[] alphaPalette=new int[256];
-            for ( int i = 255; i >= 0; i-- )
+        }
+
+        private int[] getLinearAlpha()
+        {
+            int[] alphaPalette = new int[256];
+            for (int i = 255; i >= 0; i--)
             {
-                alphaPalette[ i ] = 255 - i;
+                alphaPalette[i] = 255 - i;
             }
-
+
             return alphaPalette;
-		}
-
-		private int[] getRingAlpha(int ringsize)
-		{
-			int[] alphaPalette=new int[256];
-			float angle;
-            for ( int i = 0; i < 256; i++ )
+        }
+
+        private int[] getRingAlpha(int ringsize)
+        {
+            int[] alphaPalette = new int[256];
+            float angle;
+            for (int i = 0; i < 256; i++)
+            {
+                alphaPalette[i] = 0;
+            }
+
+            for (int i = 0; i < ringsize; i++)
             {
-                alphaPalette[ i ] = 0;
+                angle = 3.14159f / 180 * (float)(180 * i / ringsize);
+                alphaPalette[255 - ringsize + i] = (int)(64 * MathF.Sin(angle));
             }
+            return alphaPalette;
+        }

-			for (int i=0;i<ringsize;i++)
-			{
-				angle=3.14159f/180*(float)(180*i/ringsize);
-				alphaPalette[255-ringsize+i]=(int)(64*Math.Sin(angle));
-			}
-			return alphaPalette;
-		}
-
-		private int[] getSecAlpha()
-		{
-			int[] alphaPalette=getRingAlpha((int)warp_Math.random(0,255));
-            for ( int i = 0; i < 256; i++ )
+        private int[] getSecAlpha()
+        {
+            int[] alphaPalette = getRingAlpha((int)warp_Math.random(0, 255));
+            for (int i = 0; i < 256; i++)
             {
-                alphaPalette[ i ] = ( alphaPalette[ i ] + 255 - i ) >> 2;
+                alphaPalette[i] = (alphaPalette[i] + 255 - i) >> 2;
             }
-
+
             return alphaPalette;
-		}
-
-
-		private int[] getColorPalette(int color1, int color2)
-		{
-			int[] palette=new int[256];
-
-            int r1=(color1>>16)&255;
-			int g1=(color1>>8)&255;
-			int b1=color1&255;
-			int r2=(color2>>16)&255;
-			int g2=(color2>>8)&255;
-			int b2=color2&255;
-			int dr=r2-r1;
-			int dg=g2-g1;
-			int db=b2-b1;
-			int r=r1<<8;
-			int g=g1<<8;
-			int b=b1<<8;
-
-			for (int i=0;i<256;i++)
-			{
-				palette[i]=warp_Color.getColor(r>>8,g>>8,b>>8);
-				r+=dr; g+=dg; b+=db;
-			}
-			return palette;
-		}
+        }
+
+
+        private int[] getColorPalette(int color1, int color2)
+        {
+            int[] palette = new int[256];
+
+            int r1 = (color1 >> 16) & 255;
+            int g1 = (color1 >> 8) & 255;
+            int b1 = color1 & 255;
+            int r2 = (color2 >> 16) & 255;
+            int g2 = (color2 >> 8) & 255;
+            int b2 = color2 & 255;
+            int dr = r2 - r1;
+            int dg = g2 - g1;
+            int db = b2 - b1;
+            int r = r1 << 8;
+            int g = g1 << 8;
+            int b = b1 << 8;
+
+            for (int i = 0; i < 256; i++)
+            {
+                palette[i] = warp_Color.getColor(r >> 8, g >> 8, b >> 8);
+                r += dr; g += dg; b += db;
+            }
+            return palette;
+        }
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_FXPlugin.cs b/trunk/managed/Warp3Dmod/warp_FXPlugin.cs
index a43febe..3fc0841 100644
--- a/trunk/managed/Warp3Dmod/warp_FXPlugin.cs
+++ b/trunk/managed/Warp3Dmod/warp_FXPlugin.cs
@@ -9,12 +9,12 @@ namespace Warp3D
         public warp_Scene scene = null;
         public warp_Screen screen = null;

-        public warp_FXPlugin( warp_Scene scene )
-		{
-			this.scene = scene;
-			screen = scene.renderPipeline.screen;
-		}
-
-		public abstract void apply();
+        public warp_FXPlugin(warp_Scene scene)
+        {
+            this.scene = scene;
+            screen = scene.renderPipeline.screen;
+        }
+
+        public abstract void apply();
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Light.cs b/trunk/managed/Warp3Dmod/warp_Light.cs
index cd5bf35..af0dbac 100644
--- a/trunk/managed/Warp3Dmod/warp_Light.cs
+++ b/trunk/managed/Warp3Dmod/warp_Light.cs
@@ -2,65 +2,65 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_Light.
-	/// </summary>
-	public class warp_Light
-	{
-		// F I E L D S
+    /// <summary>
+    /// Summary description for warp_Light.
+    /// </summary>
+    public class warp_Light
+    {
+        // F I E L D S

-		public warp_Vector v; //Light direction
-		public warp_Vector v2; //projected Light direction
-		public int diffuse = 0;
-		public int specular = 0;
-		public int highlightSheen = 0;
-		public int highlightSpread = 0;
+        public warp_Vector v; //Light direction
+        public warp_Vector v2; //projected Light direction
+        public int diffuse = 0;
+        public int specular = 0;
+        public int highlightSheen = 0;
+        public int highlightSpread = 0;

-		warp_Matrix matrix2;
+        warp_Matrix matrix2;

-		private warp_Light()
-			// Default constructor not accessible
-		{
-		}
+        private warp_Light()
+        // Default constructor not accessible
+        {
+        }

-		public warp_Light(warp_Vector direction)
-		{
-			v = direction.getClone();
-			v.normalize();
-		}
+        public warp_Light(warp_Vector direction)
+        {
+            v = direction.getClone();
+            v.normalize();
+        }

-		public warp_Light(warp_Vector direction, int diffuse)
-		{
-			v = direction.getClone();
-			v.normalize();
-			this.diffuse = diffuse;
-		}
+        public warp_Light(warp_Vector direction, int diffuse)
+        {
+            v = direction.getClone();
+            v.normalize();
+            this.diffuse = diffuse;
+        }

-		public warp_Light(warp_Vector direction, int color, int highlightSheen, int highlightSpread)
-		{
-			v = direction.getClone();
-			v.normalize();
-			this.diffuse = color;
-			this.specular = color;
-			this.highlightSheen = highlightSheen;
-			this.highlightSpread = highlightSpread;
-		}
+        public warp_Light(warp_Vector direction, int color, int highlightSheen, int highlightSpread)
+        {
+            v = direction.getClone();
+            v.normalize();
+            diffuse = color;
+            specular = color;
+            this.highlightSheen = highlightSheen;
+            this.highlightSpread = highlightSpread;
+        }

-		public warp_Light(warp_Vector direction, int diffuse, int specular,int highlightSheen, int highlightSpread)
-		{
-			v = direction.getClone();
-			v.normalize();
-			this.diffuse = diffuse;
-			this.specular = specular;
-			this.highlightSheen = highlightSheen;
-			this.highlightSpread = highlightSpread;
-		}
+        public warp_Light(warp_Vector direction, int diffuse, int specular, int highlightSheen, int highlightSpread)
+        {
+            v = direction.getClone();
+            v.normalize();
+            this.diffuse = diffuse;
+            this.specular = specular;
+            this.highlightSheen = highlightSheen;
+            this.highlightSpread = highlightSpread;
+        }

-		public void project(warp_Matrix m)
-		{
-			matrix2 = m.getClone();
-			matrix2.transform(m);
-			v2 = v.transform(matrix2);
-		}
-	}
+        public void project(warp_Matrix m)
+        {
+            matrix2 = m.getClone();
+            matrix2.transform(m);
+            v2 = v.transform(matrix2);
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Lightmap.cs b/trunk/managed/Warp3Dmod/warp_Lightmap.cs
index 0d725ab..685c9e3 100644
--- a/trunk/managed/Warp3Dmod/warp_Lightmap.cs
+++ b/trunk/managed/Warp3Dmod/warp_Lightmap.cs
@@ -1,4 +1,6 @@
 using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;

 namespace Warp3D
 {
@@ -9,21 +11,20 @@ namespace Warp3D
     {
         public int[] diffuse = new int[65536];
         public int[] specular = new int[65536];
-        private float[] sphere = new float[65536];
-        private warp_Light[] light;
-        private int lights;
-        private int ambient;
+        private readonly float[] sphere = new float[65536];
+        private readonly warp_Light[] light;
+        private readonly int ambient;
         private int pos;

-        const float inv128 = 1.0f/128f;
-        const float inv255 = 1.0f/255f;
+        const float inv128 = 1.0f / 128f;
+        const float inv255 = 1.0f / 255f;
+        const float inv4096 = 1.0f / 4096f;

         public warp_Lightmap(warp_Scene scene)
         {
             scene.rebuild();

             light = scene.light;
-            lights = scene.lights;
             ambient = scene.environment.ambient;

             buildSphereMap();
@@ -35,30 +36,36 @@ namespace Warp3D
             float fnx, fny, fnz;
             float fnySQ;
             int pos;
-            for(int ny = -128; ny < 128; ny++)
+            ref float sphereref = ref MemoryMarshal.GetArrayDataReference(sphere);
+
+            for (int ny = -128; ny < 128; ny++)
             {
                 fny = ny * inv128;
                 fnySQ = fny * fny;
                 pos = (ny + 128) << 8;
-                for(int nx = -128; nx < 128; nx++, pos++)
+                for (int nx = -128; nx < 128; nx++, pos++)
                 {
                     fnx = nx * inv128;
-                    fnz = (float)(1 - Math.Sqrt(fnx * fnx + fnySQ));
-                    sphere[pos] = (fnz > 0) ? fnz : 0;
+                    fnz = 1f - MathF.Sqrt(fnx * fnx + fnySQ);
+                    Unsafe.As<float, float>(ref Unsafe.Add(ref sphereref, pos)) = (fnz > 0) ? fnz : 0;
                 }
             }
         }

         public void rebuildLightmap()
         {
-            warp_Vector l;
             float fnx, fny, phongfact, sheen, spread;
             int diffuse, specular, cos, dr, dg, db, sr, sg, sb;
-            for(int ny = -128; ny < 128; ny++)
+
+            ref int difuseref = ref MemoryMarshal.GetArrayDataReference(this.diffuse);
+            ref int specularref = ref MemoryMarshal.GetArrayDataReference(this.specular);
+            ref float sphereref = ref MemoryMarshal.GetArrayDataReference(sphere);
+
+            for (int ny = -128; ny < 128; ny++)
             {
                 fny = ny * inv128;
                 pos = (ny + 128) << 8;
-                for(int nx = -128; nx < 128; nx++, pos++)
+                for (int nx = -128; nx < 128; nx++, pos++)
                 {
                     fnx = nx * inv128;
                     sr = sg = sb = 0;
@@ -67,26 +74,26 @@ namespace Warp3D
                     dg = warp_Color.getGreen(ambient);
                     db = warp_Color.getBlue(ambient);

-                    for(int i = 0; i < lights; i++)
+                    for (int i = 0; i < light.Length; i++)
                     {
-                        l = light[i].v;
                         diffuse = light[i].diffuse;
                         specular = light[i].specular;
-                        sheen = (float)light[i].highlightSheen * inv255;
-                        spread = (float)light[i].highlightSpread / 4096;
+                        sheen = light[i].highlightSheen * inv255;
+                        spread = light[i].highlightSpread * inv4096;
                         spread = (spread < 0.01f) ? 0.01f : spread;
-                        cos = (int)(255 * warp_Vector.vectorsCos(light[i].v, new warp_Vector(fnx, fny, sphere[pos])));
+                        warp_Vector tmp = new warp_Vector(fnx, fny, Unsafe.As<float, float>(ref Unsafe.Add(ref sphereref, pos)));
+                        cos = (int)(255 * warp_Vector.vectorsCos(ref light[i].v, ref tmp));
                         cos = (cos > 0) ? cos : 0;
                         dr += (warp_Color.getRed(diffuse) * cos) >> 8;
                         dg += (warp_Color.getGreen(diffuse) * cos) >> 8;
                         db += (warp_Color.getBlue(diffuse) * cos) >> 8;
-                        phongfact = sheen * (float)Math.Pow((float)cos  * inv255, 1 / spread);
+                        phongfact = sheen * (float)MathF.Pow((float)cos * inv255, 1 / spread);
                         sr += (int)((float)warp_Color.getRed(specular) * phongfact);
                         sg += (int)((float)warp_Color.getGreen(specular) * phongfact);
                         sb += (int)((float)warp_Color.getBlue(specular) * phongfact);
                     }
-                    this.diffuse[pos] = warp_Color.getCropColor(dr, dg, db);
-                    this.specular[pos] = warp_Color.getCropColor(sr, sg, sb);
+                    Unsafe.As<int, int>(ref Unsafe.Add(ref difuseref, pos)) = warp_Color.getCropColor(dr, dg, db);
+                    Unsafe.As<int, int>(ref Unsafe.Add(ref specularref, pos)) = warp_Color.getCropColor(sr, sg, sb);
                 }
             }
         }
diff --git a/trunk/managed/Warp3Dmod/warp_Material.cs b/trunk/managed/Warp3Dmod/warp_Material.cs
index 3191a46..3c023d7 100644
--- a/trunk/managed/Warp3Dmod/warp_Material.cs
+++ b/trunk/managed/Warp3Dmod/warp_Material.cs
@@ -1,241 +1,256 @@
 using System;
 using System.Drawing;
 using System.IO;
+using System.Runtime.CompilerServices;
+

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_Material.
-	/// </summary>
-	public class warp_Material
-	{
-		public int color = warp_Color.White;
-		public int reflectivity=255;
-		public int type=0;
-		public warp_Texture texture=null;
-		public warp_Texture envmap=null;
-		public bool flat=false;
-		public bool wireframe=false;
-		public String texturePath=null;
-		public String envmapPath=null;
-		public warp_TextureSettings textureSettings=null;
-		public warp_TextureSettings envmapSettings=null;
-		public double rwx = 500.00;
-		public double rwy = 500.00;
-		public Point pt = new Point(0,0);
-		public int offset = 0;
-
-		public warp_Material()
-		{
-			//
-			// TODO: Add constructor logic here
-			//
-		}
-		public warp_Material(int c)
-		{
-			color = c;
-		}
-
-		public warp_Material(warp_Texture t)
-		{
-			setTexture(t);
-			reflectivity=255;
-		}
-
-		public warp_Material(String path)
-		{
-            using(FileStream fs = new FileStream(path,FileMode.Open))
+    /// <summary>
+    /// Summary description for warp_Material.
+    /// </summary>
+    public class warp_Material
+    {
+        public int color = warp_Color.White;
+        public int reflectivity = 255;
+        public int type = 0;
+        public warp_Texture texture = null;
+        public warp_Texture envmap = null;
+        public bool flat = false;
+        public bool wireframe = false;
+        public string texturePath = null;
+        public string envmapPath = null;
+        public warp_TextureSettings textureSettings = null;
+        public warp_TextureSettings envmapSettings = null;
+        public double rwx = 500.00;
+        public double rwy = 500.00;
+        public Point pt = new(0, 0);
+        public int offset = 0;
+
+        public warp_Material()
+        {
+            //
+            // TODO: Add constructor logic here
+            //
+        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public warp_Material(int c)
+        {
+            color = c;
+        }
+
+        public warp_Material(warp_Texture t)
+        {
+            setTexture(t);
+            reflectivity = 255;
+        }
+
+        public warp_Material(string path)
+        {
+            using FileStream fs = new(path, FileMode.Open);
+            using BinaryReader br = new(fs);
+            importFromStream(br);
+        }
+
+        private void importFromStream(BinaryReader inStream)
+        {
+            readSettings(inStream);
+            readTexture(inStream, true);
+            readTexture(inStream, false);
+        }
+
+        private void readSettings(BinaryReader inStream)
+        {
+            setColor(readInt(inStream));
+            setReflectivity(inStream.ReadByte());
+            setFlat(inStream.ReadBoolean());
+        }
+
+        private int readInt(BinaryReader inStream)
+        {
+            return (inStream.ReadByte() << 24) | (inStream.ReadByte() << 16) | (inStream.ReadByte() << 8) | inStream.ReadByte();
+        }
+
+        private string readString(BinaryReader inStream)
+        {
+            string result = "";
+            byte inByte;
+            while ((inByte = (byte)inStream.ReadByte()) != 60)
+            {
+                result += (char)inByte;
+            }
+
+            return result;
+        }
+
+        private void readTexture(BinaryReader inStream, bool textureId)
+        {
+            warp_Texture t = null;
+            int id = inStream.ReadSByte();
+            if (id == 1)
             {
-                using(BinaryReader br = new BinaryReader(fs))
-                    importFromStream(br);
+                t = new warp_Texture("c:/source/Warp3D/materials/skymap.jpg");
+
+                if (t != null && textureId)
+                {
+                    texturePath = t.path;
+                    textureSettings = null;
+                    setTexture(t);
+                }
+                if (t != null && !textureId)
+                {
+                    envmapPath = t.path;
+                    envmapSettings = null;
+                    setEnvmap(t);
+                }
             }
-		}
-
-		private void importFromStream(BinaryReader inStream)
-		{
-			readSettings(inStream);
-			readTexture(inStream, true);
-			readTexture(inStream, false);
-		}
-
-		private void readSettings(BinaryReader inStream)
-		{
-			setColor(readInt(inStream));
-			setReflectivity(inStream.ReadByte());
-			setFlat(inStream.ReadBoolean());
-		}
-
-		private int readInt(BinaryReader inStream)
-		{
-			return (inStream.ReadByte() << 24) | (inStream.ReadByte() << 16) | (inStream.ReadByte() << 8) | inStream.ReadByte();
-		}
-
-		private string readString(BinaryReader inStream)
-		{
-			string result = "";
-			byte inByte;
-			while ( (inByte = (byte) inStream.ReadByte()) != 60)
-			{
-				result += (char) inByte;
-			}
-
-			return result;
-		}
-
-		private void readTexture(BinaryReader inStream, bool textureId)
-		{
-			warp_Texture t = null;
-			int id = inStream.ReadSByte();
-			if (id == 1)
-			{
-				t = new warp_Texture( "c:/source/Warp3D/materials/skymap.jpg" );
-
-				if (t != null && textureId)
-				{
-					texturePath = t.path;
-					textureSettings = null;
-					setTexture(t);
-				}
-				if (t != null && !textureId)
-				{
-					envmapPath = t.path;
-					envmapSettings = null;
-					setEnvmap(t);
-				}
-			}
-
-			if (id == 2)
-			{
-				int w = readInt(inStream);
-				int h = readInt(inStream);
-				int type = inStream.ReadSByte();
-
-				float persistency = readInt(inStream);
-				float density = readInt(inStream);
-
-				persistency = .5f;
-				density = .5f;
-
-				int samples = inStream.ReadByte();
-				int numColors = inStream.ReadByte();
-				int[] colors = new int[numColors];
-				for (int i = 0; i < numColors; i++)
-				{
-					colors[i] = readInt(inStream);
-
-				}
-				if (type == 1)
-				{
-					t = warp_TextureFactory.PERLIN(w, h, persistency, density, samples, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-				}
-				if (type == 2)
-				{
-					t = warp_TextureFactory.WAVE(w, h, persistency, density, samples, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-				}
-				if (type == 3)
-				{
-					t = warp_TextureFactory.GRAIN(w, h, persistency, density, samples, 20, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-
-				}
-
-				if (textureId)
-				{
-					texturePath = null;
-					textureSettings = new warp_TextureSettings(t, w, h, type, persistency, density, samples, colors);
-					setTexture(t);
-				}
-				else
-				{
-					envmapPath = null;
-					envmapSettings = new warp_TextureSettings(t, w, h, type, persistency, density, samples, colors);
-					setEnvmap(t);
-				}
-			}
-		}
-
-		public void setTexture(warp_Texture t)
-		{
-			texture=t;
-			if (texture!=null)
-                texture.resize();
-		}
-
-		public void setEnvmap(warp_Texture env)
-		{
-			envmap=env;
-			env.resize(256,256);
-		}
-
-		public void setColor(int c)
-		{
-			color = c;
-		}
-
-		public bool opaque
+
+            if (id == 2)
+            {
+                int w = readInt(inStream);
+                int h = readInt(inStream);
+                int type = inStream.ReadSByte();
+
+                float persistency = readInt(inStream);
+                float density = readInt(inStream);
+
+                persistency = .5f;
+                density = .5f;
+
+                int samples = inStream.ReadByte();
+                int numColors = inStream.ReadByte();
+                int[] colors = new int[numColors];
+                for (int i = 0; i < numColors; i++)
+                {
+                    colors[i] = readInt(inStream);
+
+                }
+                if (type == 1)
+                {
+                    t = warp_TextureFactory.PERLIN(w, h, persistency, density, samples, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+                }
+                if (type == 2)
+                {
+                    t = warp_TextureFactory.WAVE(w, h, persistency, density, samples, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+                }
+                if (type == 3)
+                {
+                    t = warp_TextureFactory.GRAIN(w, h, persistency, density, samples, 20, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+
+                }
+
+                if (textureId)
+                {
+                    texturePath = null;
+                    textureSettings = new warp_TextureSettings(t, w, h, type, persistency, density, samples, colors);
+                    setTexture(t);
+                }
+                else
+                {
+                    envmapPath = null;
+                    envmapSettings = new warp_TextureSettings(t, w, h, type, persistency, density, samples, colors);
+                    setEnvmap(t);
+                }
+            }
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setTexture(warp_Texture t)
+        {
+            texture = t;
+            texture?.resize();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setEnvmap(warp_Texture env)
+        {
+            envmap = env;
+            envmap?.resize(256, 256);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setColor(int c)
+        {
+            color = c;
+        }
+
+        public bool opaque
         {
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get
             {
-                if((color & warp_Color.MASKALPHA) != warp_Color.MASKALPHA)
+                if ((color & warp_Color.MASKALPHA) != warp_Color.MASKALPHA)
                     return false;
-                if(texture != null)
+                if (texture is not null)
                     return texture.opaque;
                 return true;
             }
         }

-		public void setReflectivity(int factor)
-		{
-			reflectivity=warp_Math.crop(factor,0,255);
-		}
-
-		public void setFlat(bool flat)
-		{
-			this.flat=flat;
-		}
-
-		public void setWireframe(bool wireframe)
-		{
-			this.wireframe=wireframe;
-		}
-
-		public void setType(int type)
-		{
-			this.type = type;
-		}
-
-		public warp_Texture getTexture()
-		{
-			return texture;
-		}
-
-		public warp_Texture getEnvmap()
-		{
-			return envmap;
-		}
-
-		public int getColor()
-		{
-			return color;
-		}
-
-		public int getReflectivity()
-		{
-			return reflectivity;
-		}
-
-		public int getType()
-		{
-			return type;
-		}
-
-		public bool isFlat()
-		{
-			return flat;
-		}
-
-		public bool isWireframe()
-		{
-			return wireframe;
-		}
-	}
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setReflectivity(int factor)
+        {
+            reflectivity = warp_Math.crop(factor, 0, 255);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setFlat(bool flat)
+        {
+            this.flat = flat;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setWireframe(bool wireframe)
+        {
+            this.wireframe = wireframe;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void setType(int type)
+        {
+            this.type = type;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public warp_Texture getTexture()
+        {
+            return texture;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public warp_Texture getEnvmap()
+        {
+            return envmap;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int getColor()
+        {
+            return color;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int getReflectivity()
+        {
+            return reflectivity;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int getType()
+        {
+            return type;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool isFlat()
+        {
+            return flat;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool isWireframe()
+        {
+            return wireframe;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Math.cs b/trunk/managed/Warp3Dmod/warp_Math.cs
index 9b7b6e5..1269cac 100644
--- a/trunk/managed/Warp3Dmod/warp_Math.cs
+++ b/trunk/managed/Warp3Dmod/warp_Math.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
@@ -7,218 +8,111 @@ namespace Warp3D
     /// </summary>
     public class warp_Math
     {
-        //		private static float[] sinus;
-        //		private static float[] cosinus;
-        //		private static bool trig=false;
-        public static float pi = 3.1415926535f;
-        //		private static float rad2scale=4096f/3.14159265f/2f;
-        //		private static float pad=256*3.14159265f;
-
-        private static int[] fastRandoms;
-        private static int fastRndPointer = 0;
-        private static bool fastRndInit = false;
-
-        private static Random _rnd = new Random();
-
-
         public warp_Math()
         {
-            //
-            // TODO: Add constructor logic here
-            //
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float interpolate(float a, float b, float d)
         {
-            float f = (1 - cos(d * pi)) * 0.5f;
+            float f = (1f - MathF.Cos(d * MathF.PI)) * 0.5f;
             return a + f * (b - a);
         }

-
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float random()
         {
-            Random rnd = new Random();
-            return (float)(rnd.NextDouble() * 2 - 1);
+            return Random.Shared.NextSingle();
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float random(float min, float max)
         {
-            //Random rnd = new Random();
-            return (float)(_rnd.NextDouble() * (max - min) + min);
+            return Random.Shared.NextSingle() * (max - min) + min;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float randomWithDelta(float averidge, float delta)
         {
             return averidge + random() * delta;
         }

-        public static int fastRnd(int bits)
-        {
-            if (bits < 1)
-            {
-                return 0;
-            }
-            fastRndPointer = (fastRndPointer + 1) & 31;
-            if (!fastRndInit)
-            {
-                fastRandoms = new int[32];
-                for (int i = 0; i < 32; i++)
-                {
-                    fastRandoms[i] = (int)random(0, 0xFFFFFF);
-                }
-                fastRndInit = true;
-            }
-            return fastRandoms[fastRndPointer] & (1 << (bits - 1));
-        }
-
-        public static int fastRndBit()
-        {
-            return fastRnd(1);
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float deg2rad(float deg)
         {
             return deg * 0.0174532925194f;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float rad2deg(float rad)
         {
             return rad * 57.295779514719f;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float sin(float angle)
         {
-            return (float)Math.Sin(angle);
-            //			if(!trig) buildTrig();
-            //			return sinus[(int)((angle+pad)*rad2scale)&0xFFF];
+            return MathF.Sin(angle);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float cos(float angle)
         {
-            return (float)Math.Cos(angle);
-            //			if(!trig) buildTrig();
-            //			return cosinus[(int)((angle+pad)*rad2scale)&0xFFF];
-        }
-        /*
-                private static void buildTrig()
-                {
-                    sinus=new float[4096];
-                    cosinus=new float[4096];
-
-                    for (int i=0;i<4096;i++)
-                    {
-                        sinus[i]=(float)Math.Sin((float)i/rad2scale);
-                        cosinus[i]=(float)Math.Cos((float)i/rad2scale);
-                    }
-
-                    trig=true;
-                }
-        */
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+            return MathF.Cos(angle);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float pythagoras(float a, float b)
         {
-            return (float)Math.Sqrt(a * a + b * b);
+            return MathF.Sqrt(a * a + b * b);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int pythagoras(int a, int b)
         {
-            return (int)Math.Sqrt(a * a + b * b);
+            return (int)MathF.Sqrt(a * a + b * b);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static int crop(int num, int min, int max)
         {
             return (num < min) ? min : (num > max) ? max : num;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float crop(float num, float min, float max)
         {
             return (num < min) ? min : (num > max) ? max : num;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static bool inrange(int num, int min, int max)
         {
             return ((num >= min) && (num < max));
         }

-        unsafe public static void clearBuffer(int[] buffer, int c)
-        {
-            /*
-            for (int idx = 0; idx < buffer.Length; idx++)
-            {
-                buffer[idx] = c;
-            }
-            */
-
-            fixed (int* pC = buffer)
-            {
-                int* pClear = pC;
-                for (int i = 0; i < buffer.GetLength(0) / 4; i++)
-                {
-                    *pClear++ = c;
-                    *pClear++ = c;
-                    *pClear++ = c;
-                    *pClear++ = c;
-                }
-            }
-        }
-
-        unsafe public static void clearBuffer(long[] buffer, int c)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void clearBuffer(int[] buffer, int c)
         {
-            /*  for (int idx = 0; idx < buffer.Length; idx++)
-             {
-                 buffer[idx] = c;
-             }*/
-            fixed (long* pC = buffer)
-            {
-                long* pClear = pC;
-                for (int i = 0; i < buffer.GetLength(0) / 4; i++)
-                {
-                    *pClear++ = c;
-                    *pClear++ = c;
-                    *pClear++ = c;
-                    *pClear++ = c;
-                }
-            }
+            if (c == 0)
+                Array.Clear(buffer);
+            else
+                Array.Fill(buffer, c);
         }

-        public static void clearBuffer(byte[] buffer, byte value)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static void clearBuffer(byte[] buffer, byte c)
         {
-            System.Array.Clear(buffer, 0, buffer.GetLength(0));
-        }
-
-        public static void cropBuffer(int[] buffer, int min, int max)
-        {
-            for (int i = buffer.GetLength(0) - 1; i >= 0; i--) buffer[i] = crop(buffer[i], min, max);
+            if (c == 0)
+                Array.Clear(buffer);
+            else
+                Array.Fill(buffer, c);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void copyBuffer(int[] source, int[] target)
         {
-            System.Array.Copy(source, 0, target, 0, crop(source.GetLength(0), 0, target.GetLength(0)));
+            Array.Copy(source, target, crop(source.GetLength(0), 0, target.GetLength(0)));
         }
-
-        /*
-		public static float random()
-		{
-			return (float)(Math.r.random()*2-1);
-		}
-
-		public static float random(float min, float max)
-		{
-			return (float)(Math.random()*(max-min)+min);
-		}
-
-		public static float randomWithDelta(float averidge, float delta)
-		{
-			return averidge+random()*delta;
-		}
-		*/
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Matrix.cs b/trunk/managed/Warp3Dmod/warp_Matrix.cs
index 7ca123b..9432bb1 100644
--- a/trunk/managed/Warp3Dmod/warp_Matrix.cs
+++ b/trunk/managed/Warp3Dmod/warp_Matrix.cs
@@ -2,57 +2,55 @@ using System;

 namespace Warp3D
 {
-	public class warp_Matrix
-	{
-		public float m00=1, m01=0, m02=0, m03=0;
-		public float m10=0, m11=1, m12=0, m13=0;
-		public float m20=0, m21=0, m22=1, m23=0;
-		public float m30=0, m31=0, m32=0, m33=1;
-
-		public warp_Matrix(warp_Vector right, warp_Vector up, warp_Vector forward)
-		{
-			m00=right.x;
-			m10=right.y;
-			m20=right.z;
-			m01=up.x;
-			m11=up.y;
-			m21=up.z;
-			m02=forward.x;
-			m12=forward.y;
-			m22=forward.z;
-		}
-
-
-
-        public float this[ int column, int row ]
+    public class warp_Matrix
+    {
+        public float m00 = 1, m01 = 0, m02 = 0, m03 = 0;
+        public float m10 = 0, m11 = 1, m12 = 0, m13 = 0;
+        public float m20 = 0, m21 = 0, m22 = 1, m23 = 0;
+        public float m30 = 0, m31 = 0, m32 = 0, m33 = 1;
+
+        public warp_Matrix(warp_Vector right, warp_Vector up, warp_Vector forward)
+        {
+            m00 = right.x;
+            m10 = right.y;
+            m20 = right.z;
+            m01 = up.x;
+            m11 = up.y;
+            m21 = up.z;
+            m02 = forward.x;
+            m12 = forward.y;
+            m22 = forward.z;
+        }
+
+        public float this[int column, int row]
         {
             get
             {
-                switch ( row )
+                switch (row)
                 {
                     case 0:
-                        if ( column == 0 ) return m00;
-                        if ( column == 1 ) return m01;
-                        if ( column == 2 ) return m02;
-                        if ( column == 3 ) return m03;
+                        if (column == 0) return m00;
+                        if (column == 1) return m01;
+                        if (column == 2) return m02;
+                        if (column == 3) return m03;
                         break;
                     case 1:
-                        if ( column == 0 ) return m11;
-                        if ( column == 1 ) return m11;
-                        if ( column == 2 ) return m12;
-                        if ( column == 3 ) return m13;
+                        if (column == 0) return m11;
+                        if (column == 1) return m11;
+                        if (column == 2) return m12;
+                        if (column == 3) return m13;
                         break;
                     case 2:
-                        if ( column == 0 ) return m20;
-                        if ( column == 1 ) return m21;
-                        if ( column == 2 ) return m22;
-                        if ( column == 3 ) return m23;
+                        if (column == 0) return m20;
+                        if (column == 1) return m21;
+                        if (column == 2) return m22;
+                        if (column == 3) return m23;
                         break;
                     case 3:
-                        if ( column == 0 ) return m30;
-                        if ( column == 1 ) return m31;
-                        if ( column == 2 ) return m32;
-                        if ( column == 3 ) return m33;
+                        if (column == 0) return m30;
+                        if (column == 1) return m31;
+                        if (column == 2) return m32;
+                        if (column == 3) return m33;
                         break;

                     default:
@@ -63,343 +61,398 @@ namespace Warp3D
             }
         }

-		public warp_Matrix()
-		{
-			//
-			// TODO: Add constructor logic here
-			//
-		}
-
-		public static warp_Matrix shiftMatrix(float dx, float dy, float dz)
-			// matrix for shifting
-		{
-			warp_Matrix m=new warp_Matrix();
-			m.m03=dx;
-			m.m13=dy;
-			m.m23=dz;
-			return m;
-		}
-
-        public static warp_Matrix quaternionMatrix( warp_Quaternion quat )
+        public warp_Matrix()
         {
-            warp_Matrix m = new warp_Matrix();
+            //
+            // TODO: Add constructor logic here
+            //
+        }

-
-            float xx = quat.X * quat.X;
-            float xy = quat.X * quat.Y;
-            float xz = quat.X * quat.Z;
-            float xw = quat.X * quat.W;
-            float yy = quat.Y * quat.Y;
-            float yz = quat.Y * quat.Z;
-            float yw = quat.Y * quat.W;
-            float zz = quat.Z * quat.Z;
-            float zw = quat.Z * quat.W;
-
-            m.m00 = 1 - 2 * ( yy + zz );
-            m.m01 = 2 * ( xy - zw) ;
-            m.m02 = 2*(xz + yw);
-            m.m10 = 2*(xy + zw);
-            m.m11 = 1 - 2* ( xx + zz );
-            m.m12 = 2*(yz - xw);
-            m.m20 = 2*(xz - yw);
-            m.m21 = 2*(yz + xw);
-            m.m22 = 1 - 2 * ( xx + yy );
-
-            m.m03 = m.m13 = m.m23 = m.m30 = m.m31 = m.m32 = 0;
-            m.m33 = 1;
-
+        public static warp_Matrix shiftMatrix(float dx, float dy, float dz)
+        // matrix for shifting
+        {
+            warp_Matrix m = new()
+            {
+                m03 = dx,
+                m13 = dy,
+                m23 = dz
+            };
             return m;
         }

-        public warp_Matrix rotateMatrix( warp_Quaternion quat )
+        public static warp_Matrix quaternionMatrix(warp_Quaternion quat)
         {
+            float x2 = quat.X + quat.X;
+            float y2 = quat.Y + quat.Y;
+            float z2 = quat.Z + quat.Z;
+
+            float wx2 = quat.W * x2;
+            float wy2 = quat.W * y2;
+            float wz2 = quat.W * z2;
+            float xx2 = quat.X * x2;
+            float xy2 = quat.X * y2;
+            float xz2 = quat.X * z2;
+            float yy2 = quat.Y * y2;
+            float yz2 = quat.Y * z2;
+            float zz2 = quat.Z * z2;
+
+            return new()
+            {
+                m00 = 1.0f - yy2 - zz2,
+                m01 = xy2 - wz2,
+                m02 = xz2 + wy2,
+                m03 = 0f,
+
+                m10 = xy2 + wz2,
+                m11 = 1.0f - xx2 - zz2,
+                m12 = yz2 - wx2,
+                m13 = 0f,
+
+                m20 = xz2 - wy2,
+                m21 = yz2 + wx2,
+                m22 = 1.0f - xx2 - yy2,
+                m23 = 0f,
+
+                m30 = 0f,
+                m31 = 0f,
+                m32 = 0f,
+                m33 = 1f
+            };
+        }

+        public warp_Matrix rotateMatrix(warp_Quaternion quat)
+        {
             reset();

-            warp_Matrix temp = warp_Matrix.quaternionMatrix( quat );
-            warp_Matrix result = warp_Matrix.multiply( this, temp );
+            warp_Matrix temp = warp_Matrix.quaternionMatrix(quat);
+            warp_Matrix result = warp_Matrix.multiply(this, temp);
+
+            return result;
+        }
+
+        public static warp_Matrix scaleMatrix(float dx, float dy, float dz)
+        {
+            warp_Matrix m = new()
+            {
+                m00 = dx,
+                m11 = dy,
+                m22 = dz
+            };
+
+            return m;
+        }
+
+        public static warp_Matrix scaleMatrix(float d)
+        {
+            return warp_Matrix.scaleMatrix(d, d, d);
+        }
+
+        public static warp_Matrix rotateMatrix(float dx, float dy, float dz)
+        {
+            warp_Matrix res = new warp_Matrix();
+
+            float SIN;
+            float COS;
+
+            if (dx != 0)
+            {
+                warp_Matrix m = new warp_Matrix();
+                SIN = warp_Math.sin(dx);
+                COS = warp_Math.cos(dx);
+                m.m11 = COS;
+                m.m12 = SIN;
+                m.m21 = -SIN;
+                m.m22 = COS;
+
+                res.transform(m);
+            }
+            if (dy != 0)
+            {
+                warp_Matrix m = new warp_Matrix();
+                SIN = warp_Math.sin(dy);
+                COS = warp_Math.cos(dy);
+                m.m00 = COS;
+                m.m02 = SIN;
+                m.m20 = -SIN;
+                m.m22 = COS;
+
+                res.transform(m);
+            }
+            if (dz != 0)
+            {
+                warp_Matrix m = new warp_Matrix();
+                SIN = warp_Math.sin(dz);
+                COS = warp_Math.cos(dz);
+                m.m00 = COS;
+                m.m01 = SIN;
+                m.m10 = -SIN;
+                m.m11 = COS;
+
+                res.transform(m);
+            }
+
+            return res;
+        }
+
+        public void shift(float dx, float dy, float dz)
+        {
+            m03 += dx;
+            m13 += dy;
+            m23 += dz;
+        }
+
+        public void scale(float dx, float dy, float dz)
+        {
+            //			transform(scaleMatrix(dx,dy,dz));
+
+            m00 *= dx;
+            m01 *= dx;
+            m02 *= dx;
+            m03 *= dx;
+            m10 *= dy;
+            m11 *= dy;
+            m12 *= dy;
+            m13 *= dy;
+            m20 *= dz;
+            m21 *= dz;
+            m22 *= dz;
+            m23 *= dz;
+        }
+
+        public void scale(float d)
+        {
+            m00 *= d;
+            m01 *= d;
+            m02 *= d;
+            m03 *= d;
+            m10 *= d;
+            m11 *= d;
+            m12 *= d;
+            m13 *= d;
+            m20 *= d;
+            m21 *= d;
+            m22 *= d;
+            m23 *= d;
+        }
+
+        public void rotate(float dx, float dy, float dz)
+        {
+            transform(rotateMatrix(dx, dy, dz));
+        }

-			return result;
+        public void rotate(warp_Quaternion quat, float x, float y, float z)
+        {
+            transform(rotateMatrix(quat));
         }

-		public static warp_Matrix scaleMatrix(float dx, float dy, float dz)
-		{
-			warp_Matrix m=new warp_Matrix();
-
-			m.m00=dx;
-			m.m11=dy;
-			m.m22=dz;
-
-			return m;
-		}
-
-		public static warp_Matrix scaleMatrix(float d)
-		{
-			return warp_Matrix.scaleMatrix(d,d,d);
-		}
-
-		public static warp_Matrix rotateMatrix(float dx, float dy, float dz)
-		{
-			warp_Matrix res=new warp_Matrix();
-
-			float SIN;
-			float COS;
-
-			if (dx!=0)
-			{
-				warp_Matrix m = new warp_Matrix();
-				SIN=warp_Math.sin(dx);
-				COS=warp_Math.cos(dx);
-				m.m11=COS;
-				m.m12=SIN;
-				m.m21=-SIN;
-				m.m22=COS;
-
-				res.transform(m);
-			}
-			if (dy!=0)
-			{
-				warp_Matrix m =new warp_Matrix();
-				SIN=warp_Math.sin(dy);
-				COS=warp_Math.cos(dy);
-				m.m00=COS;
-				m.m02=SIN;
-				m.m20=-SIN;
-				m.m22=COS;
-
-				res.transform(m);
-			}
-			if (dz!=0)
-			{
-				warp_Matrix m =new warp_Matrix();
-				SIN=warp_Math.sin(dz);
-				COS=warp_Math.cos(dz);
-				m.m00=COS;
-				m.m01=SIN;
-				m.m10=-SIN;
-				m.m11=COS;
-
-				res.transform(m);
-			}
-
-			return res;
-		}
-
-		public void shift(float dx, float dy, float dz)
-		{
-			m03 += dx;
-			m13 += dy;
-			m23 += dz;
-		}
-
-		public void scale(float dx, float dy, float dz)
-		{
-//			transform(scaleMatrix(dx,dy,dz));
-
-			m00 *= dx;
-			m01 *= dx;
-			m02 *= dx;
-			m03 *= dx;
-			m10 *= dy;
-			m11 *= dy;
-			m12 *= dy;
-			m13 *= dy;
-			m20 *= dz;
-			m21 *= dz;
-			m22 *= dz;
-			m23 *= dz;
-		}
-
-		public void scale(float d)
-		{
-			m00 *= d;
-			m01 *= d;
-			m02 *= d;
-			m03 *= d;
-			m10 *= d;
-			m11 *= d;
-			m12 *= d;
-			m13 *= d;
-			m20 *= d;
-			m21 *= d;
-			m22 *= d;
-			m23 *= d;
-		}
-
-		public void rotate(float dx, float dy, float dz)
-		{
-			transform(rotateMatrix(dx,dy,dz));
-		}
-
-        public void rotate( warp_Quaternion quat, float x, float y, float z )
+        public void rotate(warp_Matrix m)
         {
-            transform( rotateMatrix( quat ) );
+            transform(m);
         }

-        public void rotate( warp_Matrix m )
+        public void scaleSelf(float dx, float dy, float dz)
         {
-            transform( m );
+            m00 *= dx;
+            m01 *= dy;
+            m02 *= dz;
+            m10 *= dx;
+            m11 *= dy;
+            m12 *= dz;
+            m20 *= dx;
+            m21 *= dy;
+            m22 *= dz;
         }

-        public void scaleSelf( float dx, float dy, float dz )
-		{
-			m00 *= dx;
-			m01 *= dy;
-			m02 *= dz;
-			m10 *= dx;
-			m11 *= dy;
-			m12 *= dz;
-			m20 *= dx;
-			m21 *= dy;
-			m22 *= dz;
-		}
-
-		public void scaleSelf(float d)
-		{
-			m00 *= d;
-			m01 *= d;
-			m02 *= d;
-			m10 *= d;
-			m11 *= d;
-			m12 *= d;
-			m20 *= d;
-			m21 *= d;
-			m22 *= d;
-		}
-
-        public void shiftSelf( float dx, float dy, float dz )
+        public void scaleSelf(float d)
         {
-			m03 += m00 * dx + m01 * dy + m02 * dz;
-			m13 += m10 * dx + m11 * dy + m12 * dz;
-			m23 += m20 * dx + m21 * dx + m22 * dx;
+            m00 *= d;
+            m01 *= d;
+            m02 *= d;
+            m10 *= d;
+            m11 *= d;
+            m12 *= d;
+            m20 *= d;
+            m21 *= d;
+            m22 *= d;
         }

-        public void rotateSelf( float dx, float dy, float dz )
+        public void shiftSelf(float dx, float dy, float dz)
         {
-            preTransform( rotateMatrix( dx, dy, dz ) );
+            m03 += m00 * dx + m01 * dy + m02 * dz;
+            m13 += m10 * dx + m11 * dy + m12 * dz;
+            m23 += m20 * dx + m21 * dx + m22 * dx;
         }
-        public void rotateSelf( warp_Matrix m  )
-		{
-			preTransform( m );
-		}

-        public void rotateSelf( warp_Quaternion quat )
+        public void rotateSelf(float dx, float dy, float dz)
         {
-           preTransform(rotateMatrix( quat) );
+            preTransform(rotateMatrix(dx, dy, dz));
+        }
+        public void rotateSelf(warp_Matrix m)
+        {
+            preTransform(m);
         }

+        public void rotateSelf(warp_Quaternion quat)
+        {
+            preTransform(rotateMatrix(quat));
+        }

-		public void transform(warp_Matrix n)
-		{
-			warp_Matrix m=this.getClone();
-
-			m00 = n.m00*m.m00 + n.m01*m.m10 + n.m02*m.m20;
-			m01 = n.m00*m.m01 + n.m01*m.m11 + n.m02*m.m21;
-			m02 = n.m00*m.m02 + n.m01*m.m12 + n.m02*m.m22;
-			m03 = n.m00*m.m03 + n.m01*m.m13 + n.m02*m.m23 + n.m03;
-			m10 = n.m10*m.m00 + n.m11*m.m10 + n.m12*m.m20;
-			m11 = n.m10*m.m01 + n.m11*m.m11 + n.m12*m.m21;
-			m12 = n.m10*m.m02 + n.m11*m.m12 + n.m12*m.m22;
-			m13 = n.m10*m.m03 + n.m11*m.m13 + n.m12*m.m23 + n.m13;
-			m20 = n.m20*m.m00 + n.m21*m.m10 + n.m22*m.m20;
-			m21 = n.m20*m.m01 + n.m21*m.m11 + n.m22*m.m21;
-			m22 = n.m20*m.m02 + n.m21*m.m12 + n.m22*m.m22;
-			m23 = n.m20*m.m03 + n.m21*m.m13 + n.m22*m.m23 + n.m23;
-		}
-
-		public void preTransform(warp_Matrix n)
-		{
-			warp_Matrix m=this.getClone();
-
-			m00 = m.m00*n.m00 + m.m01*n.m10 + m.m02*n.m20;
-			m01 = m.m00*n.m01 + m.m01*n.m11 + m.m02*n.m21;
-			m02 = m.m00*n.m02 + m.m01*n.m12 + m.m02*n.m22;
-			m03 = m.m00*n.m03 + m.m01*n.m13 + m.m02*n.m23 + m.m03;
-			m10 = m.m10*n.m00 + m.m11*n.m10 + m.m12*n.m20;
-			m11 = m.m10*n.m01 + m.m11*n.m11 + m.m12*n.m21;
-			m12 = m.m10*n.m02 + m.m11*n.m12 + m.m12*n.m22;
-			m13 = m.m10*n.m03 + m.m11*n.m13 + m.m12*n.m23 + m.m13;
-			m20 = m.m20*n.m00 + m.m21*n.m10 + m.m22*n.m20;
-			m21 = m.m20*n.m01 + m.m21*n.m11 + m.m22*n.m21;
-			m22 = m.m20*n.m02 + m.m21*n.m12 + m.m22*n.m22;
-			m23 = m.m20*n.m03 + m.m21*n.m13 + m.m22*n.m23 + m.m23;
-		}
-
-		public static warp_Matrix multiply(warp_Matrix m1, warp_Matrix m2)
-		{
-			warp_Matrix m=new warp_Matrix();
-
-			m.m00 = m1.m00*m2.m00 + m1.m01*m2.m10 + m1.m02*m2.m20;
-			m.m01 = m1.m00*m2.m01 + m1.m01*m2.m11 + m1.m02*m2.m21;
-			m.m02 = m1.m00*m2.m02 + m1.m01*m2.m12 + m1.m02*m2.m22;
-			m.m03 = m1.m00*m2.m03 + m1.m01*m2.m13 + m1.m02*m2.m23 + m1.m03;
-			m.m10 = m1.m10*m2.m00 + m1.m11*m2.m10 + m1.m12*m2.m20;
-			m.m11 = m1.m10*m2.m01 + m1.m11*m2.m11 + m1.m12*m2.m21;
-			m.m12 = m1.m10*m2.m02 + m1.m11*m2.m12 + m1.m12*m2.m22;
-			m.m13 = m1.m10*m2.m03 + m1.m11*m2.m13 + m1.m12*m2.m23 + m1.m13;
-			m.m20 = m1.m20*m2.m00 + m1.m21*m2.m10 + m1.m22*m2.m20;
-			m.m21 = m1.m20*m2.m01 + m1.m21*m2.m11 + m1.m22*m2.m21;
-			m.m22 = m1.m20*m2.m02 + m1.m21*m2.m12 + m1.m22*m2.m22;
-			m.m23 = m1.m20*m2.m03 + m1.m21*m2.m13 + m1.m22*m2.m23 + m1.m23;
-
-			return m;
-		}
-
-/*
-		public string toString()
-		{
-			// todo
-		}
-*/
-		public warp_Matrix getClone()
-		{
-			warp_Matrix m=new warp_Matrix();
-
-			m.m00=m00;  m.m01=m01;  m.m02=m02;  m.m03=m03;
-			m.m10=m10;  m.m11=m11;  m.m12=m12;  m.m13=m13;
-			m.m20=m20;  m.m21=m21;  m.m22=m22;  m.m23=m23;
-			m.m30=m30;  m.m31=m31;  m.m32=m32;  m.m33=m33;
-
-			return m;
-		}
-
-		public warp_Matrix inverse()
-		{
-			warp_Matrix m=new warp_Matrix();
-
-			float q1 = m12;  float q6 = m10*m01;  float q7 = m10*m21;  float q8 = m02;
-			float q13 = m20*m01;  float q14 = m20*m11;  float q21 = m02*m21;  float q22 = m03*m21;
-			float q25 = m01*m12;  float q26 = m01*m13;  float q27 = m02*m11;  float q28 = m03*m11;
-			float q29 = m10*m22;  float q30 = m10*m23;  float q31 = m20*m12;  float q32 = m20*m13;
-			float q35 = m00*m22;  float q36 = m00*m23;  float q37 = m20*m02;  float q38 = m20*m03;
-			float q41 = m00*m12;  float q42 = m00*m13;  float q43 = m10*m02;  float q44 = m10*m03;
-			float q45 = m00*m11;  float q48 = m00*m21;
-			float q49 = q45*m22-q48*q1-q6*m22+q7*q8;
-			float q50 = q13*q1-q14*q8;
-			float q51 = 1/(q49+q50);
-
-			m.m00 = (m11*m22*m33-m11*m23*m32-m21*m12*m33+m21*m13*m32+m31*m12*m23-m31*m13*m22)*q51;
-			m.m01 = -(m01*m22*m33-m01*m23*m32-q21*m33+q22*m32)*q51;
-			m.m02 = (q25*m33-q26*m32-q27*m33+q28*m32)*q51;
-			m.m03 = -(q25*m23-q26*m22-q27*m23+q28*m22+q21*m13-q22*m12)*q51;
-			m.m10 = -(q29*m33-q30*m32-q31*m33+q32*m32)*q51;
-			m.m11 = (q35*m33-q36*m32-q37*m33+q38*m32)*q51;
-			m.m12 = -(q41*m33-q42*m32-q43*m33+q44*m32)*q51;
-			m.m13 = (q41*m23-q42*m22-q43*m23+q44*m22+q37*m13-q38*m12)*q51;
-			m.m20 = (q7*m33-q30*m31-q14*m33+q32*m31)*q51;
-			m.m21 = -(q48*m33-q36*m31-q13*m33+q38*m31)*q51;
-			m.m22 = (q45*m33-q42*m31-q6*m33+q44*m31)*q51;
-			m.m23 = -(q45*m23-q42*m21-q6*m23+q44*m21+q13*m13-q38*m11)*q51;
-
-			return m;
-		}
-
-		public void reset()
-		{
-			m00=1; m01=0; m02=0; m03=0;
-			m10=0; m11=1; m12=0; m13=0;
-			m20=0; m21=0; m22=1; m23=0;
-			m30=0; m31=0; m32=0; m33=1;
-		}
-	}
+        public void transform(warp_Matrix n)
+        {
+            warp_Matrix m = getClone();
+
+            m00 = n.m00 * m.m00 + n.m01 * m.m10 + n.m02 * m.m20;
+            m01 = n.m00 * m.m01 + n.m01 * m.m11 + n.m02 * m.m21;
+            m02 = n.m00 * m.m02 + n.m01 * m.m12 + n.m02 * m.m22;
+            m03 = n.m00 * m.m03 + n.m01 * m.m13 + n.m02 * m.m23 + n.m03;
+            m10 = n.m10 * m.m00 + n.m11 * m.m10 + n.m12 * m.m20;
+            m11 = n.m10 * m.m01 + n.m11 * m.m11 + n.m12 * m.m21;
+            m12 = n.m10 * m.m02 + n.m11 * m.m12 + n.m12 * m.m22;
+            m13 = n.m10 * m.m03 + n.m11 * m.m13 + n.m12 * m.m23 + n.m13;
+            m20 = n.m20 * m.m00 + n.m21 * m.m10 + n.m22 * m.m20;
+            m21 = n.m20 * m.m01 + n.m21 * m.m11 + n.m22 * m.m21;
+            m22 = n.m20 * m.m02 + n.m21 * m.m12 + n.m22 * m.m22;
+            m23 = n.m20 * m.m03 + n.m21 * m.m13 + n.m22 * m.m23 + n.m23;
+        }
+
+        public static warp_Matrix transform(warp_Matrix m, warp_Matrix n)
+        {
+            return new warp_Matrix
+            {
+                m00 = n.m00 * m.m00 + n.m01 * m.m10 + n.m02 * m.m20,
+                m01 = n.m00 * m.m01 + n.m01 * m.m11 + n.m02 * m.m21,
+                m02 = n.m00 * m.m02 + n.m01 * m.m12 + n.m02 * m.m22,
+                m03 = n.m00 * m.m03 + n.m01 * m.m13 + n.m02 * m.m23 + n.m03,
+                m10 = n.m10 * m.m00 + n.m11 * m.m10 + n.m12 * m.m20,
+                m11 = n.m10 * m.m01 + n.m11 * m.m11 + n.m12 * m.m21,
+                m12 = n.m10 * m.m02 + n.m11 * m.m12 + n.m12 * m.m22,
+                m13 = n.m10 * m.m03 + n.m11 * m.m13 + n.m12 * m.m23 + n.m13,
+                m20 = n.m20 * m.m00 + n.m21 * m.m10 + n.m22 * m.m20,
+                m21 = n.m20 * m.m01 + n.m21 * m.m11 + n.m22 * m.m21,
+                m22 = n.m20 * m.m02 + n.m21 * m.m12 + n.m22 * m.m22,
+                m23 = n.m20 * m.m03 + n.m21 * m.m13 + n.m22 * m.m23 + n.m23,
+            };
+        }
+
+        public void SetFromtransform(warp_Matrix m, warp_Matrix n)
+        {
+            m00 = n.m00 * m.m00 + n.m01 * m.m10 + n.m02 * m.m20;
+            m01 = n.m00 * m.m01 + n.m01 * m.m11 + n.m02 * m.m21;
+            m02 = n.m00 * m.m02 + n.m01 * m.m12 + n.m02 * m.m22;
+            m03 = n.m00 * m.m03 + n.m01 * m.m13 + n.m02 * m.m23 + n.m03;
+            m10 = n.m10 * m.m00 + n.m11 * m.m10 + n.m12 * m.m20;
+            m11 = n.m10 * m.m01 + n.m11 * m.m11 + n.m12 * m.m21;
+            m12 = n.m10 * m.m02 + n.m11 * m.m12 + n.m12 * m.m22;
+            m13 = n.m10 * m.m03 + n.m11 * m.m13 + n.m12 * m.m23 + n.m13;
+            m20 = n.m20 * m.m00 + n.m21 * m.m10 + n.m22 * m.m20;
+            m21 = n.m20 * m.m01 + n.m21 * m.m11 + n.m22 * m.m21;
+            m22 = n.m20 * m.m02 + n.m21 * m.m12 + n.m22 * m.m22;
+            m23 = n.m20 * m.m03 + n.m21 * m.m13 + n.m22 * m.m23 + n.m23;
+        }
+
+        public void preTransform(warp_Matrix n)
+        {
+            warp_Matrix m = this.getClone();
+
+            m00 = m.m00 * n.m00 + m.m01 * n.m10 + m.m02 * n.m20;
+            m01 = m.m00 * n.m01 + m.m01 * n.m11 + m.m02 * n.m21;
+            m02 = m.m00 * n.m02 + m.m01 * n.m12 + m.m02 * n.m22;
+            m03 = m.m00 * n.m03 + m.m01 * n.m13 + m.m02 * n.m23 + m.m03;
+            m10 = m.m10 * n.m00 + m.m11 * n.m10 + m.m12 * n.m20;
+            m11 = m.m10 * n.m01 + m.m11 * n.m11 + m.m12 * n.m21;
+            m12 = m.m10 * n.m02 + m.m11 * n.m12 + m.m12 * n.m22;
+            m13 = m.m10 * n.m03 + m.m11 * n.m13 + m.m12 * n.m23 + m.m13;
+            m20 = m.m20 * n.m00 + m.m21 * n.m10 + m.m22 * n.m20;
+            m21 = m.m20 * n.m01 + m.m21 * n.m11 + m.m22 * n.m21;
+            m22 = m.m20 * n.m02 + m.m21 * n.m12 + m.m22 * n.m22;
+            m23 = m.m20 * n.m03 + m.m21 * n.m13 + m.m22 * n.m23 + m.m23;
+        }
+
+        public static warp_Matrix multiply(warp_Matrix m1, warp_Matrix m2)
+        {
+            return new warp_Matrix
+            {
+                m00 = m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20,
+                m01 = m1.m00 * m2.m01 + m1.m01 * m2.m11 + m1.m02 * m2.m21,
+                m02 = m1.m00 * m2.m02 + m1.m01 * m2.m12 + m1.m02 * m2.m22,
+                m03 = m1.m00 * m2.m03 + m1.m01 * m2.m13 + m1.m02 * m2.m23 + m1.m03,
+                m10 = m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20,
+                m11 = m1.m10 * m2.m01 + m1.m11 * m2.m11 + m1.m12 * m2.m21,
+                m12 = m1.m10 * m2.m02 + m1.m11 * m2.m12 + m1.m12 * m2.m22,
+                m13 = m1.m10 * m2.m03 + m1.m11 * m2.m13 + m1.m12 * m2.m23 + m1.m13,
+                m20 = m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20,
+                m21 = m1.m20 * m2.m01 + m1.m21 * m2.m11 + m1.m22 * m2.m21,
+                m22 = m1.m20 * m2.m02 + m1.m21 * m2.m12 + m1.m22 * m2.m22,
+                m23 = m1.m20 * m2.m03 + m1.m21 * m2.m13 + m1.m22 * m2.m23 + m1.m23
+            };
+        }
+
+        /*
+                public string toString()
+                {
+                    // todo
+                }
+        */
+        public warp_Matrix getClone()
+        {
+            return new warp_Matrix()
+            {
+                m00 = m00,
+                m01 = m01,
+                m02 = m02,
+                m03 = m03,
+                m10 = m10,
+                m11 = m11,
+                m12 = m12,
+                m13 = m13,
+                m20 = m20,
+                m21 = m21,
+                m22 = m22,
+                m23 = m23,
+                m30 = m30,
+                m31 = m31,
+                m32 = m32,
+                m33 = m33
+            };
+        }
+
+        public warp_Matrix inverse()
+        {
+            warp_Matrix m = new warp_Matrix();
+
+            float q1 = m12; float q6 = m10 * m01; float q7 = m10 * m21; float q8 = m02;
+            float q13 = m20 * m01; float q14 = m20 * m11; float q21 = m02 * m21; float q22 = m03 * m21;
+            float q25 = m01 * m12; float q26 = m01 * m13; float q27 = m02 * m11; float q28 = m03 * m11;
+            float q29 = m10 * m22; float q30 = m10 * m23; float q31 = m20 * m12; float q32 = m20 * m13;
+            float q35 = m00 * m22; float q36 = m00 * m23; float q37 = m20 * m02; float q38 = m20 * m03;
+            float q41 = m00 * m12; float q42 = m00 * m13; float q43 = m10 * m02; float q44 = m10 * m03;
+            float q45 = m00 * m11; float q48 = m00 * m21;
+            float q49 = q45 * m22 - q48 * q1 - q6 * m22 + q7 * q8;
+            float q50 = q13 * q1 - q14 * q8;
+            float q51 = 1 / (q49 + q50);
+
+            m.m00 = (m11 * m22 * m33 - m11 * m23 * m32 - m21 * m12 * m33 + m21 * m13 * m32 + m31 * m12 * m23 - m31 * m13 * m22) * q51;
+            m.m01 = -(m01 * m22 * m33 - m01 * m23 * m32 - q21 * m33 + q22 * m32) * q51;
+            m.m02 = (q25 * m33 - q26 * m32 - q27 * m33 + q28 * m32) * q51;
+            m.m03 = -(q25 * m23 - q26 * m22 - q27 * m23 + q28 * m22 + q21 * m13 - q22 * m12) * q51;
+            m.m10 = -(q29 * m33 - q30 * m32 - q31 * m33 + q32 * m32) * q51;
+            m.m11 = (q35 * m33 - q36 * m32 - q37 * m33 + q38 * m32) * q51;
+            m.m12 = -(q41 * m33 - q42 * m32 - q43 * m33 + q44 * m32) * q51;
+            m.m13 = (q41 * m23 - q42 * m22 - q43 * m23 + q44 * m22 + q37 * m13 - q38 * m12) * q51;
+            m.m20 = (q7 * m33 - q30 * m31 - q14 * m33 + q32 * m31) * q51;
+            m.m21 = -(q48 * m33 - q36 * m31 - q13 * m33 + q38 * m31) * q51;
+            m.m22 = (q45 * m33 - q42 * m31 - q6 * m33 + q44 * m31) * q51;
+            m.m23 = -(q45 * m23 - q42 * m21 - q6 * m23 + q44 * m21 + q13 * m13 - q38 * m11) * q51;
+
+            return m;
+        }
+
+        public void reset()
+        {
+            m00 = 1f; m01 = 0f; m02 = 0f; m03 = 0f;
+            m10 = 0f; m11 = 1f; m12 = 0f; m13 = 0f;
+            m20 = 0f; m21 = 0f; m22 = 1f; m23 = 0f;
+            m30 = 0f; m31 = 0f; m32 = 0f; m33 = 1f;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Object.cs b/trunk/managed/Warp3Dmod/warp_Object.cs
index 109a75f..8723c68 100644
--- a/trunk/managed/Warp3Dmod/warp_Object.cs
+++ b/trunk/managed/Warp3Dmod/warp_Object.cs
@@ -1,60 +1,49 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
     /// <summary>
     /// Summary description for warp_Object.
     /// </summary>
-    public class warp_Object: warp_CoreObject
+    public class warp_Object : warp_CoreObject
     {
-        public Object userData = null;  // Can be freely used
-        public String user = null;      // Can be freely used
-
-        public List<warp_Vertex> vertexData = new List<warp_Vertex>(1024);
-        public List<warp_Triangle> triangleData = new List<warp_Triangle>(1024);
+        public List<warp_Vertex> vertexData;
+        public List<warp_Triangle> triangleData;

         public int id;  // This object's index
-        public String name = "";  // This object's name
+        public string name = "";  // This object's name
         public bool visible = true; // Visibility tag
         public warp_Scene parent = null;
         private bool dirty = true;  // Flag for dirty handling

-        public warp_Vertex[] fastvertex;
-        public warp_Triangle[] fasttriangle;
-
-        public int vertices = 0;
-        public int triangles = 0;
+        public warp_Vector fastMin;
+        public warp_Vector fastMax;

         public warp_Material material = null;
         public int projectedmaxMips = 0;

-        public int fastcolor;
-        public int fastreflectivity;
-        public int[] fastenvmappixels;
-        public warp_Texture fasttexture;
-        public int[] fasttpixels;
-        public int fasttw;
-        public int fastth;
-        public int fasttbitw;
-        public int fasttbith;
-        public int fastmode;
-
         public warp_Object()
         {
+            vertexData = new List<warp_Vertex>(256);
+            triangleData = new(256);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vertex vertex(int id)
         {
-            return (warp_Vertex)vertexData[id];
+            return vertexData[id];
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Triangle triangle(int id)
         {
-            return (warp_Triangle)triangleData[id];
+            return triangleData[id];
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addVertex(warp_Vertex newVertex)
         {
             newVertex.parent = this;
@@ -62,6 +51,7 @@ namespace Warp3D
             dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addTriangle(warp_Triangle newTriangle)
         {
             newTriangle.parent = this;
@@ -69,31 +59,42 @@ namespace Warp3D
             dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addTriangle(int v1, int v2, int v3)
         {
             addTriangle(vertex(v1), vertex(v2), vertex(v3));
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void removeVertex(warp_Vertex v)
         {
             vertexData.Remove(v);
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void removeTriangle(warp_Triangle t)
         {
             triangleData.Remove(t);
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void removeVertexAt(int pos)
         {
             vertexData.RemoveAt(pos);
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void removeTriangleAt(int pos)
         {
             triangleData.RemoveAt(pos);
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setMaterial(warp_Material m)
         {
             material = m;
@@ -101,27 +102,46 @@ namespace Warp3D

         public void rebuild()
         {
-            if(!dirty)
+            if (!dirty)
                 return;
-            dirty = false;
-
-            vertices = vertexData.Count;
-            fastvertex = vertexData.ToArray();

-            // Generate faster structure for triangles
-            triangles = triangleData.Count;
-            fasttriangle = triangleData.ToArray();
+            float minX = 0;
+            float maxX = minX;
+            float minY = 0;
+            float maxY = minY;
+            float minZ = 0;
+            float maxZ = minZ;
+            float t;

-            for(int i = vertices - 1; i >= 0; i--)
+            for (int i = 0; i < vertexData.Count; i++)
             {
-                fastvertex[i].id = i;
-                fastvertex[i].resetNeighbors();
+                vertexData[i].id = i;
+                vertexData[i].resetNeighbors();
+
+                t = vertexData[i].pos.x;
+                if (t < minX)
+                    minX = t;
+                if (t > maxX)
+                    maxX = t;
+
+                t = vertexData[i].pos.y;
+                if (t < minY)
+                    minY = t;
+                if (t > maxY)
+                    maxY = t;
+
+                t = vertexData[i].pos.z;
+                if (t < minZ)
+                    minZ = t;
+                if (t > maxZ)
+                    maxZ = t;
             }
+            fastMin = new warp_Vector(minX, minY, minZ);
+            fastMax = new warp_Vector(maxX, maxY, maxZ);

-            warp_Triangle tri;
-            for(int i = triangles - 1; i >= 0; i--)
+            for (int i = 0; i < triangleData.Count; i++)
             {
-                tri = fasttriangle[i];
+                warp_Triangle tri = triangleData[i];
                 tri.id = i;
                 tri.p1.registerNeighbor(tri);
                 tri.p2.registerNeighbor(tri);
@@ -129,92 +149,54 @@ namespace Warp3D
             }

             regenerate();
+            dirty = false;
         }

-        /*
-		public void rebuild()
-		{
-			if (!dirty) return;
-			dirty=false;
-
-			Enumeration enum;
-
-			// Generate faster structure for vertices
-			vertices=vertexData.size();
-			vertex=new warp_Vertex[vertices];
-			enum=vertexData.elements();
-			for (int i=vertices-1;i>=0;i--) vertex[i]=(warp_Vertex)enum.nextElement();
-
-			// Generate faster structure for triangles
-			triangles=triangleData.size();
-			triangle=new warp_Triangle[triangles];
-			enum=triangleData.elements();
-			for (int i=triangles-1;i>=0;i--)
-			{
-				triangle[i]=(warp_Triangle)enum.nextElement();
-				triangle[i].id=i;
-			}
-
-			for (int i=vertices-1;i>=0;i--)
-			{
-				vertex[i].id=i;
-				vertex[i].resetNeighbors();
-			}
-
-			warp_Triangle tri;
-			for (int i=triangles-1;i>=0;i--)
-			{
-				tri=triangle[i];
-				tri.p1.registerNeighbor(tri);
-				tri.p2.registerNeighbor(tri);
-				tri.p3.registerNeighbor(tri);
-			}
-
-			regenerate();
-		}
-		*/
-
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addVertex(float x, float y, float z)
         {
-            addVertex(new warp_Vertex(x, y, z));
+            addVertex(new(x, y, z));
+            dirty = true;
         }

-
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addVertex(float x, float y, float z, float u, float v)
         {
-            warp_Vertex vert = new warp_Vertex(x, y, z);
-            vert.setUV(u, v);
-            addVertex(vert);
+            addVertex(new warp_Vertex(x, y, z, u, v));
+            dirty = true;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void addTriangle(warp_Vertex a, warp_Vertex b, warp_Vertex c)
         {
             addTriangle(new warp_Triangle(a, b, c));
+            dirty = true;
         }

         public void regenerate()
         // Regenerates the vertex normals
         {
-            for(int i = 0; i < triangles; i++)
-                fasttriangle[i].regenerateNormal();
-            for(int i = 0; i < vertices; i++)
-                fastvertex[i].regenerateNormal();
+            for (int i = 0; i < triangleData.Count; i++)
+                triangleData[i].regenerateNormal();
+            for (int i = 0; i < vertexData.Count; i++)
+                vertexData[i].regenerateNormal();
         }

+        /*
         public void remapUV(int w, int h, float sx, float sy)
         {
             rebuild();
-            for(int j = 0, p = 0; j < h; j++)
+            for (int j = 0, p = 0; j < h; j++)
             {
                 float v = ((float)j / (float)(h - 1)) * sy;
-                for(int i = 0; i < w; i++)
+                for (int i = 0; i < w; i++)
                 {
                     float u = ((float)i / (float)(w - 1)) * sx;
-                    fastvertex[p++].setUV(u, v);
+                    vertexData[p++].setUV(u, v);
                 }
             }
         }
-
+        */
         /*
 		public void tilt(float fact)
 		{
@@ -226,46 +208,6 @@ namespace Warp3D
 		}
 		*/

-        public warp_Vector minimum()
-        {
-            if(vertices == 0)
-                return new warp_Vector(0f, 0f, 0f);
-            float minX = fastvertex[0].pos.x;
-            float minY = fastvertex[0].pos.y;
-            float minZ = fastvertex[0].pos.z;
-            for(int i = 1; i < vertices; i++)
-            {
-                if(fastvertex[i].pos.x < minX)
-                    minX = fastvertex[i].pos.x;
-                if(fastvertex[i].pos.y < minY)
-                    minY = fastvertex[i].pos.y;
-                if(fastvertex[i].pos.z < minZ)
-                    minZ = fastvertex[i].pos.z;
-            }
-
-            return new warp_Vector(minX, minY, minZ);
-        }
-
-        public warp_Vector maximum()
-        {
-            if(vertices == 0)
-                return new warp_Vector(0f, 0f, 0f);
-            float maxX = fastvertex[0].pos.x;
-            float maxY = fastvertex[0].pos.y;
-            float maxZ = fastvertex[0].pos.z;
-            for(int i = 1; i < vertices; i++)
-            {
-                if(fastvertex[i].pos.x > maxX)
-                    maxX = fastvertex[i].pos.x;
-                if(fastvertex[i].pos.y > maxY)
-                    maxY = fastvertex[i].pos.y;
-                if(fastvertex[i].pos.z > maxZ)
-                    maxZ = fastvertex[i].pos.z;
-            }
-            return new warp_Vector(maxX, maxY, maxZ);
-        }
-
-
         public void detach()
         // Centers the object in its coordinate system
         // The offset from origin to object center will be transfered to the matrix,
@@ -274,11 +216,11 @@ namespace Warp3D
         {
             warp_Vector center = getCenter();

-            for(int i = 0; i < vertices; i++)
+            for (int i = 0; i < vertexData.Count; i++)
             {
-                fastvertex[i].pos.x -= center.x;
-                fastvertex[i].pos.y -= center.y;
-                fastvertex[i].pos.z -= center.z;
+                vertexData[i].pos.x -= center.x;
+                vertexData[i].pos.y -= center.y;
+                vertexData[i].pos.z -= center.z;
             }

             shift(center);
@@ -287,19 +229,13 @@ namespace Warp3D
         public warp_Vector getCenter()
         // Returns the center of this object
         {
-            warp_Vector max = maximum();
-            warp_Vector min = minimum();
-
-            return new warp_Vector((max.x + min.x) / 2, (max.y + min.y) / 2, (max.z + min.z) / 2);
+            return new warp_Vector((fastMax.x + fastMin.x) / 2, (fastMax.y + fastMin.y) / 2, (fastMax.z + fastMin.z) / 2);
         }

         public warp_Vector getDimension()
         // Returns the x,y,z - Dimension of this object
         {
-            warp_Vector max = maximum();
-            warp_Vector min = minimum();
-
-            return new warp_Vector(max.x - min.x, max.y - min.y, max.z - min.z);
+            return new warp_Vector(fastMax.x - fastMin.x, fastMax.y - fastMin.y, fastMax.z - fastMin.z);
         }

         public void matrixMeltdown()
@@ -307,14 +243,13 @@ namespace Warp3D
         // and resets the matrix to untransformed.
         {
             rebuild();
-            for(int i = vertices - 1; i >= 0; i--)
-                fastvertex[i].pos = fastvertex[i].pos.transform(matrix);
+            for (int i = 0; i < vertexData.Count; i++)
+                vertexData[i].pos = vertexData[i].pos.transform(matrix);

             regenerate();
             matrix.reset();
             normalmatrix.reset();
         }
-
         public void destroy()
         {
             name = null;
@@ -323,22 +258,17 @@ namespace Warp3D
             normalmatrix = null;
             parent = null;

-            fastvertex = null;
-            fasttriangle = null;
-            vertexData.Clear();
-            triangleData.Clear();
             vertexData = null;
             triangleData = null;
         }
-
         public warp_Object getClone()
         {
-            warp_Object obj = new warp_Object();
+            warp_Object obj = new();
             rebuild();
-            for(int i = 0; i < vertices; i++)
-                obj.addVertex(fastvertex[i].getClone());
-            for(int i = 0; i < triangles; i++)
-                obj.addTriangle(fasttriangle[i].getClone());
+            for (int i = 0; i < vertexData.Count; i++)
+                obj.addVertex(vertexData[i].getClone());
+            for (int i = 0; i < triangleData.Count; i++)
+                obj.addTriangle(triangleData[i].getClone());
             obj.name = name + " [cloned]";
             obj.material = material;
             obj.matrix = matrix.getClone();
@@ -347,66 +277,6 @@ namespace Warp3D
             return obj;
         }

-        private const int F = 0;      // FLAT
-        private const int W = 1;  // WIREFRAME
-        private const int P = 2;      // PHONG
-        private const int E = 4;      // ENVMAP
-        private const int T = 8;  // TEXTURED
-
-        public void cacheMaterialData()
-        {
-            fastcolor = material.color;
-            fastreflectivity = material.reflectivity;
-            fasttexture = material.texture;
-            if(material.envmap != null)
-                fastenvmappixels = material.envmap.pixel;
-            else
-                fastenvmappixels = null;
-
-            if(fasttexture != null)
-            {
-                if(projectedmaxMips < 2)
-                {
-                    fastcolor = warp_Color.multiply(fastcolor, fasttexture.averageColor);
-                    fasttexture = null;
-                }
-                else
-                {
-                    int mip = projectedmaxMips - 2;
-//                    int mip = fasttexture.maxmips;
-                    if(mip < fasttexture.maxmips)
-                    {
-                        if(!fasttexture.hasmips)
-                            fasttexture.GenMips();
-
-                        fasttpixels = fasttexture.mips[mip];
-                        fasttbitw = fasttexture.mipsBitWidth[mip];
-                        fasttbith = fasttexture.mipsBitHeight[mip];
-                        fasttw = fasttexture.mipstw[mip] - 1;
-                        fastth = fasttexture.mipsth[mip] - 1;
-                    }
-                    else
-                    {
-                        fasttpixels = fasttexture.pixel;
-                        fasttw = fasttexture.width - 1;
-                        fastth = fasttexture.height - 1;
-                        fasttbitw = fasttexture.bitWidth;
-                        fasttbith = fasttexture.bitHeight;
-                    }
-                }
-            }
-
-            int m = 0;
-            if(!material.flat)
-                m |= P;
-            if(fastenvmappixels != null)
-                m |= E;
-            if(fasttexture != null)
-                m |= T;
-            if(material.wireframe)
-                m |= W;
-            fastmode = m;
-        }

         /*
 				public void removeDuplicateVertices()
diff --git a/trunk/managed/Warp3Dmod/warp_ObjectFactory.cs b/trunk/managed/Warp3Dmod/warp_ObjectFactory.cs
index 4a66e51..1ff1701 100644
--- a/trunk/managed/Warp3Dmod/warp_ObjectFactory.cs
+++ b/trunk/managed/Warp3Dmod/warp_ObjectFactory.cs
@@ -2,308 +2,311 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_ObjectFactory.
-	/// </summary>
-	public class warp_ObjectFactory
-	{
-		public static double pi = 3.1415926535;
-		public static double deg2rad = pi / 180;
-
-		public static warp_Object SIMPLEPLANE(float size, bool doubleSided)
-		{
-			warp_Object newObject = new warp_Object();
-
-            newObject.addVertex( new warp_Vertex( -size, 0f, size, 0, 0 ) );
-            newObject.addVertex( new warp_Vertex( size, 0f, size, 1f, 0 ) );
-            newObject.addVertex( new warp_Vertex( size, 0f, -size, 1f, 1f ) );
-            newObject.addVertex( new warp_Vertex( -size, 0f, -size, 0, 1f ) );
-
-			newObject.addTriangle(0, 3, 2);
-			newObject.addTriangle(0, 2, 1);
-
-			if(doubleSided)
-			{
-				newObject.addTriangle(0, 2, 3);
-				newObject.addTriangle(0, 1, 2);
-			}
-
-			return newObject;
-		}
-
-		public static warp_Object CUBE(float size)
-		{
-			return BOX(size, size, size);
-		}
-
-		public static warp_Object BOX(warp_Vector size)
-		{
-			return BOX(size.x, size.y, size.z);
-		}
-
-		public static warp_Object BOX(float xsize, float ysize, float zsize)
-		{
-			float x = (float) Math.Abs(xsize / 2);
-			float y = (float) Math.Abs(ysize / 2);
-			float z = (float) Math.Abs(zsize / 2);
-
-			float xx, yy, zz;
-
-			warp_Object n = new warp_Object();
-			int[] xflag = new int[6];
-			int[] yflag = new int[6];
-			int[] zflag = new int[6];
-
-			xflag[0] = 10;
-			yflag[0] = 3;
-			zflag[0] = 0;
-			xflag[1] = 10;
-			yflag[1] = 15;
-			zflag[1] = 3;
-			xflag[2] = 15;
-			yflag[2] = 3;
-			zflag[2] = 10;
-			xflag[3] = 10;
-			yflag[3] = 0;
-			zflag[3] = 12;
-			xflag[4] = 0;
-			yflag[4] = 3;
-			zflag[4] = 5;
-			xflag[5] = 5;
-			yflag[5] = 3;
-			zflag[5] = 15;
-
-			for (int side = 0; side < 6; side++)
-			{
-				for (int i = 0; i < 4; i++)
-				{
-					xx = ( (xflag[side] & (1 << i)) > 0) ? x : -x;
-					yy = ( (yflag[side] & (1 << i)) > 0) ? y : -y;
-					zz = ( (zflag[side] & (1 << i)) > 0) ? z : -z;
-					n.addVertex(xx, yy, zz, i & 1, (i & 2) >> 1);
-				}
-				int t = side << 2;
-				n.addTriangle(t, t + 2, t + 3);
-				n.addTriangle(t, t + 3, t + 1);
-			}
-
-			return n;
-		}
-
-		public static warp_Object CONE(float height, float radius, int segments)
-		{
-			warp_Vector[] path = new warp_Vector[4];
-			float h = height / 2;
-			path[0] = new warp_Vector(0, h, 0);
-			path[1] = new warp_Vector(radius, -h, 0);
-			path[2] = new warp_Vector(radius, -h, 0);
-			path[3] = new warp_Vector(0, -h, 0);
-
-			return ROTATIONOBJECT(path, segments);
-		}
-
-		public static warp_Object CYLINDER(float height, float radius,int segments)
-		{
-			warp_Vector[] path = new warp_Vector[6];
-			float h = height / 2;
-			path[0] = new warp_Vector(0, h, 0);
-			path[1] = new warp_Vector(radius, h, 0);
-			path[2] = new warp_Vector(radius, h, 0);
-			path[3] = new warp_Vector(radius, -h, 0);
-			path[4] = new warp_Vector(radius, -h, 0);
-			path[5] = new warp_Vector(0, -h, 0);
-
-			return ROTATIONOBJECT(path, segments);
-		}
-
-		public static warp_Object SPHERE(float radius, int segments)
-		{
-			warp_Vector[] path = new warp_Vector[segments];
-
-			float x, y, angle;
-
-			path[0] = new warp_Vector(0, radius, 0);
-			path[segments - 1] = new warp_Vector(0, -radius, 0);
-
-			for (int i = 1; i < segments - 1; i++)
-			{
-				angle = - ( ( (float) i / (float) (segments - 2)) - 0.5f) *
-					3.14159265f;
-				x = (float) Math.Cos(angle) * radius;
-				y = (float) Math.Sin(angle) * radius;
-				path[i] = new warp_Vector(x, y, 0);
-			}
-
-			return ROTATIONOBJECT(path, segments);
-		}
-
-		public static warp_Object ROTATIONOBJECT(warp_Vector[] path, int sides)
-		{
-			int steps = sides + 1;
-			warp_Object newObject = new warp_Object();
-			double alpha = 2 * pi / ( (double) steps - 1);
-			float qx, qz;
-			int nodes = path.GetLength(0);
-			warp_Vertex vertex = null;
-			float u, v; // Texture coordinates
-
-			for (int j = 0; j < steps; j++)
-			{
-				u = (float) (steps - j - 1) / (float) (steps - 1);
-				for (int i = 0; i < nodes; i++)
-				{
-					v = (float) i / (float) (nodes - 1);
-					qx = (float) (path[i].x * Math.Cos(j * alpha) +
-						path[i].z * Math.Sin(j * alpha));
-					qz = (float) (path[i].z * Math.Cos(j * alpha) -
-						path[i].x * Math.Sin(j * alpha));
-					vertex = new warp_Vertex(qx, path[i].y, qz);
-					vertex.u = u;
-					vertex.v = v;
-					newObject.addVertex(vertex);
-				}
-			}
-
-			for (int j = 0; j < steps - 1; j++)
-			{
-				for (int i = 0; i < nodes - 1; i++)
-				{
-					newObject.addTriangle(i + nodes * j, i + nodes * (j + 1),
-						i + 1 + nodes * j);
-					newObject.addTriangle(i + nodes * (j + 1),
-						i + 1 + nodes * (j + 1),
-						i + 1 + nodes * j);
-
-				}
-			}
-
-			for (int i = 0; i < nodes - 1; i++)
-			{
-				newObject.addTriangle(i + nodes * (steps - 1), i,
-					i + 1 + nodes * (steps - 1));
-				newObject.addTriangle(i, i + 1, i + 1 + nodes * (steps - 1));
-			}
-			return newObject;
-
-		}
-
-		public static warp_Object TORUSKNOT(float p, float q, float r_tube,float r_out, float r_in, float h,int segments, int steps)
-		{
-			float x, y, z, r, t, theta;
-
-			warp_Vector[] path = new warp_Vector[segments + 1];
-			for (int i = 0; i < segments + 1; i++)
-			{
-				t = 2 * 3.14159265f * i / (float) segments;
-				r = r_out + r_in * warp_Math.cos(p * t);
-				z = h * warp_Math.sin(p * t);
-				theta = q * t;
-				x = r * warp_Math.cos(theta);
-				y = r * warp_Math.sin(theta);
-				path[i] = new warp_Vector(x, y, z);
-			}
-			return TUBE(path, r_tube, steps, true);
-		}
-
-		public static warp_Object SPIRAL(float h, float r_out, float r_in,
-			float r_tube, float w, float f,
-			int segments, int steps)
-		{
-			float x, y, z, r, t, theta;
-
-			warp_Vector[] path = new warp_Vector[segments + 1];
-			for (int i = 0; i < segments + 1; i++)
-			{
-				t = (float) i / (float) segments;
-				r = r_out + r_in * warp_Math.sin(2 * 3.14159265f * f * t);
-				z = (h / 2) + h * t;
-				theta = 2 * 3.14159265f * w * t;
-				x = r * warp_Math.cos(theta);
-				y = r * warp_Math.sin(theta);
-				path[i] = new warp_Vector(x, y, z);
-			}
-			return TUBE(path, r_tube, steps, false);
-		}
-
-		public static warp_Object TUBE(warp_Vector[] path, float r, int steps, bool closed)
-		{
-			warp_Vector[] circle = new warp_Vector[steps];
-			float angle;
-			for (int i = 0; i < steps; i++)
-			{
-				angle = 2 * 3.14159265f * (float) i / (float) steps;
-				circle[i] = new warp_Vector(r * warp_Math.cos(angle),
-					r * warp_Math.sin(angle), 0f);
-			}
-
-			warp_Object newObject = new warp_Object();
-			int segments = path.GetLength(0);
-			warp_Vector forward, up, right;
-			warp_Matrix frenetmatrix;
-			warp_Vertex tempvertex;
-			float relx, rely;
-			int a, b, c, d;
-
-			for (int i = 0; i < segments; i++)
-			{
-				// Calculate frenet frame matrix
-
-				if (i != segments - 1)
-				{
-					forward = warp_Vector.sub(path[i + 1], path[i]);
-				}
-				else
-				{
-					if (!closed)
-					{
-						forward = warp_Vector.sub(path[i], path[i - 1]);
-					}
-					else
-					{
-						forward = warp_Vector.sub(path[1], path[0]);
-					}
-				}
-
-				forward.normalize();
-				up = new warp_Vector(0f, 0f, 1f);
-				right = warp_Vector.getNormal(forward, up);
-				up = warp_Vector.getNormal(forward, right);
-				frenetmatrix = new warp_Matrix(right, up, forward);
-				frenetmatrix.shift(path[i].x, path[i].y, path[i].z);
-
-				// Add nodes
-
-				relx = (float) i / (float) (segments - 1);
-				for (int k = 0; k < steps; k++)
-				{
-					rely = (float) k / (float) steps;
-					tempvertex = new warp_Vertex(circle[k].transform(frenetmatrix));
-					tempvertex.u = relx;
-					tempvertex.v = rely;
-					newObject.addVertex(tempvertex);
-				}
-			}
-
-			for (int i = 0; i < segments - 1; i++)
-			{
-				for (int k = 0; k < steps - 1; k++)
-				{
-					a = i * steps + k;
-					b = a + 1;
-					c = a + steps;
-					d = b + steps;
-					newObject.addTriangle(a, c, b);
-					newObject.addTriangle(b, c, d);
-				}
-				a = (i + 1) * steps - 1;
-				b = a + 1 - steps;
-				c = a + steps;
-				d = b + steps;
-				newObject.addTriangle(a, c, b);
-				newObject.addTriangle(b, c, d);
-			}
-
-			return newObject;
-		}
-	}
+    /// <summary>
+    /// Summary description for warp_ObjectFactory.
+    /// </summary>
+    public class warp_ObjectFactory
+    {
+        public static warp_Object SIMPLEPLANE(float size, bool doubleSided)
+        {
+            warp_Object newObject = new();
+
+            newObject.addVertex(new(-size, 0f, size, 0, 0));
+            newObject.addVertex(new(size, 0f, size, 1f, 0));
+            newObject.addVertex(new(size, 0f, -size, 1f, 1f));
+            newObject.addVertex(new(-size, 0f, -size, 0, 1f));
+
+            newObject.addTriangle(0, 3, 2);
+            newObject.addTriangle(0, 2, 1);
+
+            if (doubleSided)
+            {
+                newObject.addTriangle(0, 2, 3);
+                newObject.addTriangle(0, 1, 2);
+            }
+
+            return newObject;
+        }
+
+        public static warp_Object CUBE(float size)
+        {
+            return BOX(size, size, size);
+        }
+
+        public static warp_Object BOX(warp_Vector size)
+        {
+            return BOX(size.x, size.y, size.z);
+        }
+
+        public static warp_Object BOX(float xsize, float ysize, float zsize)
+        {
+            float x = MathF.Abs(xsize) * 0.5f;
+            float y = MathF.Abs(ysize) * 0.5f;
+            float z = MathF.Abs(zsize) * 0.5f;
+
+            float xx, yy, zz;
+
+            warp_Object n = new();
+            int[] xflag = new int[6];
+            int[] yflag = new int[6];
+            int[] zflag = new int[6];
+
+            xflag[0] = 10;
+            yflag[0] = 3;
+            zflag[0] = 0;
+            xflag[1] = 10;
+            yflag[1] = 15;
+            zflag[1] = 3;
+            xflag[2] = 15;
+            yflag[2] = 3;
+            zflag[2] = 10;
+            xflag[3] = 10;
+            yflag[3] = 0;
+            zflag[3] = 12;
+            xflag[4] = 0;
+            yflag[4] = 3;
+            zflag[4] = 5;
+            xflag[5] = 5;
+            yflag[5] = 3;
+            zflag[5] = 15;
+
+            for (int side = 0; side < 6; side++)
+            {
+                for (int i = 0; i < 4; i++)
+                {
+                    xx = ((xflag[side] & (1 << i)) > 0) ? x : -x;
+                    yy = ((yflag[side] & (1 << i)) > 0) ? y : -y;
+                    zz = ((zflag[side] & (1 << i)) > 0) ? z : -z;
+                    n.addVertex(xx, yy, zz, i & 1, (i & 2) >> 1);
+                }
+                int t = side << 2;
+                n.addTriangle(t, t + 2, t + 3);
+                n.addTriangle(t, t + 3, t + 1);
+            }
+
+            return n;
+        }
+
+        public static warp_Object CONE(float height, float radius, int segments)
+        {
+            warp_Vector[] path = new warp_Vector[4];
+            float h = height * 0.5f;
+            path[0] = new warp_Vector(0, h, 0);
+            path[1] = new warp_Vector(radius, -h, 0);
+            path[2] = new warp_Vector(radius, -h, 0);
+            path[3] = new warp_Vector(0, -h, 0);
+
+            return ROTATIONOBJECT(path, segments);
+        }
+
+        public static warp_Object CYLINDER(float height, float radius, int segments)
+        {
+            warp_Vector[] path = new warp_Vector[6];
+            float h = height * 0.5f;
+            path[0] = new warp_Vector(0, h, 0);
+            path[1] = new warp_Vector(radius, h, 0);
+            path[2] = new warp_Vector(radius, h, 0);
+            path[3] = new warp_Vector(radius, -h, 0);
+            path[4] = new warp_Vector(radius, -h, 0);
+            path[5] = new warp_Vector(0, -h, 0);
+
+            return ROTATIONOBJECT(path, segments);
+        }
+
+        public static warp_Object SPHERE(float radius, int segments)
+        {
+            warp_Vector[] path = new warp_Vector[segments];
+
+            float x, y, angle;
+
+            path[0] = new warp_Vector(0, radius, 0);
+            path[segments - 1] = new warp_Vector(0, -radius, 0);
+
+            for (int i = 1; i < segments - 1; i++)
+            {
+                angle = (((float)i / (float)(segments - 2)) - 0.5f) * -3.14159265f;
+                x = MathF.Cos(angle) * radius;
+                y = MathF.Sin(angle) * radius;
+                path[i] = new warp_Vector(x, y, 0);
+            }
+
+            return ROTATIONOBJECT(path, segments);
+        }
+
+        public static warp_Object ROTATIONOBJECT(warp_Vector[] path, int sides)
+        {
+            int steps = sides + 1;
+            warp_Object newObject = new();
+            double alpha = 2 * Math.PI / ((double)steps - 1);
+            float qx, qz;
+            int nodes = path.GetLength(0);
+            warp_Vertex vertex;
+            float u, v; // Texture coordinates
+
+            for (int j = 0; j < steps; j++)
+            {
+                u = (float)(steps - j - 1) / (float)(steps - 1);
+                for (int i = 0; i < nodes; i++)
+                {
+                    v = (float)i / (float)(nodes - 1);
+                    qx = (float)(path[i].x * Math.Cos(j * alpha) +
+                        path[i].z * Math.Sin(j * alpha));
+                    qz = (float)(path[i].z * Math.Cos(j * alpha) -
+                        path[i].x * Math.Sin(j * alpha));
+                    vertex = new warp_Vertex(qx, path[i].y, qz)
+                    {
+                        u = u,
+                        v = v
+                    };
+                    newObject.addVertex(vertex);
+                }
+            }
+
+            for (int j = 0; j < steps - 1; j++)
+            {
+                for (int i = 0; i < nodes - 1; i++)
+                {
+                    newObject.addTriangle(i + nodes * j, i + nodes * (j + 1),
+                        i + 1 + nodes * j);
+                    newObject.addTriangle(i + nodes * (j + 1),
+                        i + 1 + nodes * (j + 1),
+                        i + 1 + nodes * j);
+                }
+            }
+
+            for (int i = 0; i < nodes - 1; i++)
+            {
+                newObject.addTriangle(i + nodes * (steps - 1), i,
+                    i + 1 + nodes * (steps - 1));
+                newObject.addTriangle(i, i + 1, i + 1 + nodes * (steps - 1));
+            }
+            return newObject;
+
+        }
+
+        /*
+        public static warp_Object TORUSKNOT(float p, float q, float r_tube, float r_out, float r_in, float h, int segments, int steps)
+        {
+            float x, y, z, r, t, theta;
+
+            warp_Vector[] path = new warp_Vector[segments + 1];
+            for (int i = 0; i < segments + 1; i++)
+            {
+                t = 2f * 3.14159265f * i / (float)segments;
+                r = r_out + r_in * MathF.Cos(p * t);
+                z = h * MathF.Sin(p * t);
+                theta = q * t;
+                x = r * MathF.Cos(theta);
+                y = r * MathF.Sin(theta);
+                path[i] = new warp_Vector(x, y, z);
+            }
+            return TUBE(path, r_tube, steps, true);
+        }
+        */
+        /*
+        public static warp_Object SPIRAL(float h, float r_out, float r_in,
+            float r_tube, float w, float f,
+            int segments, int steps)
+        {
+            float x, y, z, r, t, theta;
+
+            warp_Vector[] path = new warp_Vector[segments + 1];
+            for (int i = 0; i < segments + 1; i++)
+            {
+                t = (float)i / (float)segments;
+                r = r_out + r_in * MathF.Sin(2f * 3.14159265f * f * t);
+                z = (h * 0.5f) + h * t;
+                theta = 2f * 3.14159265f * w * t;
+                x = r * MathF.Cos(theta);
+                y = r * MathF.Sin(theta);
+                path[i] = new warp_Vector(x, y, z);
+            }
+            return TUBE(path, r_tube, steps, false);
+        }
+        */
+
+        /*
+        public static warp_Object TUBE(warp_Vector[] path, float r, int steps, bool closed)
+        {
+            warp_Vector[] circle = new warp_Vector[steps];
+            float angle;
+            for (int i = 0; i < steps; i++)
+            {
+                angle = 2f * 3.14159265f * (float)i / (float)steps;
+                circle[i] = new warp_Vector(r * MathF.Cos(angle), r * MathF.Sin(angle), 0f);
+            }
+
+            warp_Object newObject = new();
+            int segments = path.GetLength(0);
+            warp_Vector forward, up, right;
+            warp_Matrix frenetmatrix;
+            warp_Vertex tempvertex;
+            float relx, rely;
+            int a, b, c, d;
+
+            for (int i = 0; i < segments; i++)
+            {
+                // Calculate frenet frame matrix
+
+                if (i != segments - 1)
+                {
+                    forward = warp_Vector.sub(ref path[i + 1], ref path[i]);
+                }
+                else
+                {
+                    if (!closed)
+                    {
+                        forward = warp_Vector.sub(ref path[i], ref path[i - 1]);
+                    }
+                    else
+                    {
+                        forward = warp_Vector.sub(ref path[1], ref path[0]);
+                    }
+                }
+
+                forward.normalize();
+                up = new warp_Vector(0f, 0f, 1f);
+                right = warp_Vector.getPlaneNormal(ref forward, ref up);
+                up = warp_Vector.getPlaneNormal(ref forward, ref right);
+                frenetmatrix = new warp_Matrix(right, up, forward);
+                frenetmatrix.shift(path[i].x, path[i].y, path[i].z);
+
+                // Add nodes
+
+                relx = (float)i / (float)(segments - 1);
+                for (int k = 0; k < steps; k++)
+                {
+                    rely = (float)k / (float)steps;
+                    tempvertex = new warp_Vertex(circle[k].transform(frenetmatrix))
+                    {
+                        u = relx,
+                        v = rely
+                    };
+                    newObject.addVertex(tempvertex);
+                }
+            }
+
+            for (int i = 0; i < segments - 1; i++)
+            {
+                for (int k = 0; k < steps - 1; k++)
+                {
+                    a = i * steps + k;
+                    b = a + 1;
+                    c = a + steps;
+                    d = b + steps;
+                    newObject.addTriangle(a, c, b);
+                    newObject.addTriangle(b, c, d);
+                }
+                a = (i + 1) * steps - 1;
+                b = a + 1 - steps;
+                c = a + steps;
+                d = b + steps;
+                newObject.addTriangle(a, c, b);
+                newObject.addTriangle(b, c, d);
+            }
+
+            return newObject;
+        }
+        */
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Quaternion.cs b/trunk/managed/Warp3Dmod/warp_Quaternion.cs
index c560855..fa8b14b 100644
--- a/trunk/managed/Warp3Dmod/warp_Quaternion.cs
+++ b/trunk/managed/Warp3Dmod/warp_Quaternion.cs
@@ -1,49 +1,44 @@
 using System;
 using System.Collections;
 using System.Text;
-using System.Diagnostics;
+using System.Diagnostics;

 namespace Warp3D
 {
-    public class warp_Quaternion
+    public struct warp_Quaternion
     {
-        public float X;
-        public float Y;
-        public float Z;
-        public float W;
+        public float X = 0;
+        public float Y = 0;
+        public float Z = 0;
+        public float W = 1;

         public warp_Quaternion()
         {
         }

-        public warp_Quaternion( float x, float y, float z, float w )
+        public warp_Quaternion(float x, float y, float z, float w)
         {
-            this.X = x;
-            this.Y = y;
-            this.Z = z;
-            this.W = w;
+            X = x;
+            Y = y;
+            Z = z;
+            W = w;
         }

-        public warp_Quaternion getClone()
+        static public warp_Quaternion matrix(warp_Matrix xfrm)
         {
-            return new warp_Quaternion( this.X, this.Y, this.Z, this.W );
-        }
-
-        static public warp_Quaternion matrix( warp_Matrix xfrm )
-        {
-            warp_Quaternion quat = new warp_Quaternion();
+            warp_Quaternion quat = new();
             // Check the sum of the diagonal
-            float tr = xfrm[ 0, 0 ] + xfrm[ 1, 1 ] + xfrm[ 2, 2 ];
-            if ( tr > 0.0f )
+            float tr = xfrm[0, 0] + xfrm[1, 1] + xfrm[2, 2];
+            if (tr > 0.0f)
             {
                 // The sum is positive
                 // 4 muls, 1 div, 6 adds, 1 trig function call
-                float s = ( float )Math.Sqrt( tr + 1.0f );
+                float s = MathF.Sqrt(tr + 1.0f);
                 quat.W = s * 0.5f;
                 s = 0.5f / s;
-                quat.X = ( xfrm[ 1, 2 ] - xfrm[ 2, 1 ] ) * s;
-                quat.Y = ( xfrm[ 2, 0 ] - xfrm[ 0, 2 ] ) * s;
-                quat.Z = ( xfrm[ 0, 1 ] - xfrm[ 1, 0 ] ) * s;
+                quat.X = (xfrm[1, 2] - xfrm[2, 1]) * s;
+                quat.Y = (xfrm[2, 0] - xfrm[0, 2]) * s;
+                quat.Z = (xfrm[0, 1] - xfrm[1, 0]) * s;
             }
             else
             {
@@ -52,70 +47,57 @@ namespace Warp3D
                 int[] nIndex = { 1, 2, 0 };
                 int i, j, k;
                 i = 0;
-                if ( xfrm[ 1, 1 ] > xfrm[ i, i ] )
+                if (xfrm[1, 1] > xfrm[i, i])
                     i = 1;
-                if ( xfrm[ 2, 2 ] > xfrm[ i, i ] )
+                if (xfrm[2, 2] > xfrm[i, i])
                     i = 2;
-                j = nIndex[ i ];
-                k = nIndex[ j ];
+                j = nIndex[i];
+                k = nIndex[j];

-                float s = ( float )Math.Sqrt( ( xfrm[ i, i ] - ( xfrm[ j, j ] + xfrm[ k, k ] ) ) + 1.0f );
-                quat[ i ] = s * 0.5f;
-                if ( s != 0.0 )
+                float s = MathF.Sqrt((xfrm[i, i] - (xfrm[j, j] + xfrm[k, k])) + 1.0f);
+                quat[i] = s * 0.5f;
+                if (s != 0.0)
                 {
                     s = 0.5f / s;
                 }
-                quat[ j ] = ( xfrm[ i, j ] + xfrm[ j, i ] ) * s;
-                quat[ k ] = ( xfrm[ i, k ] + xfrm[ k, i ] ) * s;
-                quat[ 3 ] = ( xfrm[ j, k ] - xfrm[ k, j ] ) * s;
+                quat[j] = (xfrm[i, j] + xfrm[j, i]) * s;
+                quat[k] = (xfrm[i, k] + xfrm[k, i]) * s;
+                quat[3] = (xfrm[j, k] - xfrm[k, j]) * s;
             }

             return quat;
         }

-        public float this[ int index ]
+        public float this[int index]
         {
             get
             {
-                Debug.Assert( 0 <= index && index <= 3 );
-                if ( index <= 1 )
-                {
-                    if ( index == 0 )
-                    {
-                        return this.X;
-                    }
-                    return this.Y;
-                }
-                if ( index == 2 )
+                Debug.Assert(0 <= index && index <= 3);
+                return index switch
                 {
-                    return this.Z;
-                }
-                return this.W;
+                    0 => X,
+                    1 => Y,
+                    2 => Z,
+                    _ => W,
+                };
             }
             set
             {
-                Debug.Assert( 0 <= index && index <= 3 );
-                if ( index <= 1 )
-                {
-                    if ( index == 0 )
-                    {
-                        this.X = value;
-                    }
-                    else
-                    {
-                        this.Y = value;
-                    }
-                }
-                else
+                Debug.Assert(0 <= index && index <= 3);
+                switch (index)
                 {
-                    if ( index == 2 )
-                    {
-                        this.Z = value;
-                    }
-                    else
-                    {
-                        this.W = value;
-                    }
+                    case 0:
+                        X = value;
+                        break;
+                    case 1:
+                        Y = value;
+                        break;
+                    case 2:
+                        Z = value;
+                        break;
+                    case 3:
+                        W = value;
+                        break;
                 }
             }
         }
diff --git a/trunk/managed/Warp3Dmod/warp_Rasterizer.cs b/trunk/managed/Warp3Dmod/warp_Rasterizer.cs
index 9ccac13..8a3ac34 100644
--- a/trunk/managed/Warp3Dmod/warp_Rasterizer.cs
+++ b/trunk/managed/Warp3Dmod/warp_Rasterizer.cs
@@ -1,4 +1,6 @@
 using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;

 namespace Warp3D
 {
@@ -32,15 +34,14 @@ namespace Warp3D
         private const int P = 2;      // PHONG
         private const int E = 4;      // ENVMAP
         private const int T = 8;  // TEXTURED
-        private int SHADED = 0;
+        private const int OPAQUE = 16;  // opace

         private int
             y, z, dx, dy, dz, offset,
             xL, xR, xBase, zBase, xMax, dxL, dxR, dzBase,
             nxBase, nyBase,
             dnx, dny, nx, ny,
-            dnxBase, dnyBase,
-            shademode;
+            dnxBase, dnyBase;

         private float
             txBase, tyBase,
@@ -56,8 +57,6 @@ namespace Warp3D
         // Constructor
         public warp_Rasterizer(warp_RenderPipeline pipeline)
         {
-            SHADED = P | E | T;
-
             rebuildReferences(pipeline);
             loadLightmap(pipeline.lightmap);
         }
@@ -75,6 +74,10 @@ namespace Warp3D
         {
             screen = null;
             zBuffer = null;
+            tpixels = null;
+            envmap = null;
+            diffuse = null;
+            specular = null;
         }

         // Lightmap loader
@@ -95,12 +98,9 @@ namespace Warp3D
             color = material.color;
             reflectivity = material.reflectivity;
             texture = material.texture;
-            if (material.envmap != null)
-                envmap = material.envmap.pixel;
-            else
-                envmap = null;
+            envmap = material.envmap is null ? null : envmap = material.envmap.pixel;

-            if (texture != null)
+            if (texture is not null)
             {
                 if (obj.projectedmaxMips < 2)
                 {
@@ -109,12 +109,12 @@ namespace Warp3D
                 }
                 else
                 {
-                    int mip = obj.projectedmaxMips - 1;
-                    if (mip > texture.maxmips)
-                        mip = texture.maxmips;
-
-                    if (texture.mips[mip] != null)
+                    int mip = obj.projectedmaxMips - 2;
+                    if (mip < texture.maxmips)
                     {
+                        if (!texture.hasmips)
+                            texture.GenMips();
+
                         tpixels = texture.mips[mip];
                         tbitW = texture.mipsBitWidth[mip];
                         tbitH = texture.mipsBitHeight[mip];
@@ -135,43 +135,22 @@ namespace Warp3D
             mode = 0;
             if (!material.flat)
                 mode |= P;
-            if (envmap != null)
+            if (envmap is not null)
                 mode |= E;
-            if (texture != null)
+            if (texture is not null)
                 mode |= T;
             if (material.wireframe)
                 mode |= W;
+            if (material.opaque)
+                mode |= OPAQUE;

-            shademode = mode & SHADED;
-            materialLoaded = true;
-            ready = lightmapLoaded;
-        }
-
-        public void loadFastMaterial(warp_Object obj)
-        {
-            color = obj.fastcolor;
-            reflectivity = obj.fastreflectivity;
-            texture = obj.fasttexture;
-            envmap = obj.fastenvmappixels;
-
-            if (texture != null)
-            {
-                tpixels = obj.fasttpixels;
-                tw = obj.fasttw;
-                th = obj.fastth;
-                tbitW = obj.fasttbitw;
-                tbitH = obj.fasttbith;
-            }
-
-            mode = obj.fastmode;
-            shademode = mode & SHADED;
             materialLoaded = true;
             ready = lightmapLoaded;
         }

         public void render(warp_Triangle tri)
         {
-            if (!ready || tri.parent == null)
+            if (!ready || tri.parent is null)
                 return;

             if ((mode & W) != 0)
@@ -183,30 +162,34 @@ namespace Warp3D
                 }
             }

+            warp_Vertex p1;
+            warp_Vertex p2;

-            warp_Vertex p1 = tri.p1;
-            warp_Vertex p2 = tri.p2;
-            warp_Vertex p3 = tri.p3;
-            warp_Vertex tempVertex;
-
-            if (p1.y > p2.y)
+            if (tri.p1.y > tri.p2.y)
             {
-                tempVertex = p1;
-                p1 = p2;
-                p2 = tempVertex;
+                p1 = tri.p2;
+                p2 = tri.p1;
             }
-            if (p2.y > p3.y)
+            else
             {
-                tempVertex = p2;
-                p2 = p3;
-                p3 = tempVertex;
+                p1 = tri.p1;
+                p2 = tri.p2;
             }
-            if (p1.y > p2.y)
+
+            warp_Vertex p3;
+            if (p2.y > tri.p3.y)
             {
-                tempVertex = p1;
-                p1 = p2;
-                p2 = tempVertex;
+                p3 = p2;
+                if (p1.y > tri.p3.y)
+                {
+                    p2 = p1;
+                    p1 = tri.p3;
+                }
+                else
+                    p2 = tri.p3;
             }
+            else
+                p3 = tri.p3;

             if (p1.y >= height)
                 return;
@@ -217,7 +200,7 @@ namespace Warp3D
             if (p1.y == p3.y)
                 return;

-            if (mode == F)
+            if ((mode & 0x0f) == F)
             {
                 int lutID = (int)(tri.n2.x * 127 + 127) + ((int)(tri.n2.y * 127 + 127) << 8);
                 int c = warp_Color.multiply(color, diffuse[lutID]);
@@ -236,6 +219,7 @@ namespace Warp3D
             int dy31 = y3 - y1;

             float tf = (float)dy / dy31;
+
             int x4 = x1 + (int)((x3 - x1) * tf);

             dx = (x4 - x2) >> 8;
@@ -270,29 +254,28 @@ namespace Warp3D
             int ny2 = p2.ny;
             dny = (ny4 - ny2) / dx;

-            float tx1 = p1.tx * tw;
-            float tx3 = p3.tx * tw;
+            float sw1 = p1.invZ;
+            float sw3 = p3.invZ;
+            float sw4 = sw1 + ((sw3 - sw1) * tf);
+            float sw2 = p2.invZ;
+            dsw = (sw4 - sw2) / dx;
+
+            float tx1 = sw1 * p1.u * tw;
+            float tx3 = sw3 * p3.u * tw;
             float tx4 = tx1 + ((tx3 - tx1) * tf);
-            float tx2 = p2.tx * tw;
+            float tx2 = sw2 * p2.u * tw;
             dtx = (tx4 - tx2) / dx;

-            float ty1 = p1.ty * th;
-            float ty3 = p3.ty * th;
+            float ty1 = sw1 * p1.v * th;
+            float ty3 = sw3 * p3.v * th;
             float ty4 = ty1 + ((ty3 - ty1) * tf);
-            float ty2 = p2.ty * th;
+            float ty2 = sw2 * p2.v * th;
             dty = (ty4 - ty2) / dx;

-            float sw1 = p1.invZ;
-            float sw3 = p3.invZ;
-            float sw4 = sw1 + ((sw3 - sw1) * tf);
-            float sw2 = p2.invZ;
-            dsw = (sw4 - sw2) / dx;

             if (dx < 0)
             {
-                int temp = x2;
-                x2 = x4;
-                x4 = temp;
+                (x4, x2) = (x2, x4);
                 z2 = z4;
                 tx2 = tx4;
                 ty2 = ty4;
@@ -336,11 +319,8 @@ namespace Warp3D

                 if (y2 > height)
                     y2 = height;
-                offset = y1 * width;
-                for (y = y1; y < y2; y++)
-                {
-                    renderLine();
-                }
+
+                renderLines(y1 * width, y2 * width);
             }

             dy = y3 - y2;
@@ -379,144 +359,297 @@ namespace Warp3D

                 if (y3 > height)
                     y3 = height;
-                offset = y2 * width;

-                for (y = y2; y < y3; y++)
-                {
-                    renderLine();
-                }
+                renderLines(y2 * width, y3 * width);
             }
-        }

-        private void renderLine()
-        {
-            xL = xBase >> 16;
-            xR = xMax >> 16;
-            z = zBase;
-            nx = nxBase;
-            ny = nyBase;
-            tx = txBase;
-            ty = tyBase;
-            sw = swBase;
-
-            if (xL < 0)
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            void renderLines(int offsetStart, int offsetEnd)
             {
-                z -= xL * dz;
-                nx -= xL * dnx;
-                ny -= xL * dny;
-                tx -= xL * dtx;
-                ty -= xL * dty;
-                sw -= xL * dsw;
-                xL = 0;
-            }
-            if (xR > width)
-                xR = width;
+                ref int rpixels = ref MemoryMarshal.GetArrayDataReference(screen.pixels);
+                ref int rzbuf = ref MemoryMarshal.GetArrayDataReference(zBuffer);
+                ref int rdifuse = ref MemoryMarshal.GetArrayDataReference(diffuse);
+                ref int rspecular = ref MemoryMarshal.GetArrayDataReference(specular);
+                ref int rtpixels = ref MemoryMarshal.GetArrayDataReference(tpixels);

-            if (mode == F)
-                renderLineF();
-            else
-            {
-                switch(shademode)
+                for (offset = offsetStart; offset < offsetEnd; offset += width)
                 {
-                    case P:
-                        renderLineP();
-                        break;
-                    case E:
-                        renderLineE();
-                        break;
-                    case T:
-                        renderLineT();
-                        break;
-                    case P | E:
-                        renderLinePE();
-                        break;
-                    case P | T:
-                        renderLinePT();
-                        break;
-                    case P | E | T:
-                        renderLinePET();
-                        break;
-                }
-            }
+                    xL = xBase >> 16;
+                    xR = xMax >> 16;
+                    z = zBase;
+                    nx = nxBase;
+                    ny = nyBase;
+                    tx = txBase;
+                    ty = tyBase;
+                    sw = swBase;
+
+                    if (xL < 0)
+                    {
+                        z -= xL * dz;
+                        nx -= xL * dnx;
+                        ny -= xL * dny;
+                        tx -= xL * dtx;
+                        ty -= xL * dty;
+                        sw -= xL * dsw;
+                        xL = 0;
+                    }
+                    if (xR > width)
+                        xR = width;

-            offset += width;
-            xBase += dxL;
-            xMax += dxR;
-            zBase += dzBase;
-            nxBase += dnxBase;
-            nyBase += dnyBase;
-            txBase += dtxBase;
-            tyBase += dtyBase;
-            swBase += dswBase;
-        }
+                    int posEnd = xR + offset;
+                    switch (mode)
+                    {
+                        case F:
+                            {
+                                //renderLineF;
+                                for (int pos = xL + offset; pos < posEnd; pos++)
+                                {
+                                    if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                    {
+                                        Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+                                        int bkgrd = Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos));
+                                        Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.overSolid(bkgrd, currentColor);
+                                    }
+                                    z += dz;
+                                }
+                                break;
+                            }

-        // Fast scanline rendering
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLineF()
-        {
-            int bkgrd;
-            int c;
-            int pos;
+                        case F | OPAQUE:
+                            {
+                                //renderLineFO
+                                for (int pos = xL + offset; pos < posEnd; pos++)
+                                {
+                                    if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                    {
+                                        Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+                                        Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = currentColor;
+                                    }
+                                    z += dz;
+                                }
+                                break;
+                            }
+                        case P:
+                            //renderLineP();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    int c = warp_Color.multiply(color, Unsafe.As<int, int>(ref Unsafe.Add(ref rdifuse, lutID)));
+                                    int s = warp_Color.scale(Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID)), reflectivity);
+                                    int bkgrd = Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos));
+                                    c = warp_Color.overSolid(bkgrd, c);
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.add(c, s);
+                                }
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                            }
+                            break;
+                        case P | OPAQUE:
+                            //renderLinePO();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;

-            fixed (int* sp = screen.pixels, zB = zBuffer)
-            {
-                for (int x = xL; x < xR; x++)
-                {
-                    pos = x + offset;
-                    if (z < zBuffer[pos])
-                    {
-                        bkgrd = sp[pos];
-                        c = warp_Color.overSolid(bkgrd, currentColor);
-                        sp[pos] = c;
-                        zB[pos] = z;
-                    }
-                    z += dz;
-                }
-            }
-        }
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    int c = warp_Color.multiply(color, Unsafe.As<int, int>(ref Unsafe.Add(ref rdifuse, lutID)));
+                                    int s = warp_Color.scale(Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID)), reflectivity);
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.add(c, s);
+                                }
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                            }
+                            break;
+                        case E:
+                            //renderLineE();
+                            ref int renvmap = ref MemoryMarshal.GetArrayDataReference(envmap);
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLineP()
-        {
-            int bkgrd;
-            int c;
-            int s;
-            int lutID;
-            int pos;
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    int s = Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID));
+                                    s = warp_Color.add(s, Unsafe.As<int, int>(ref Unsafe.Add(ref renvmap, lutID)));
+                                    s = warp_Color.scale(s, reflectivity);

-            fixed (int* sp = screen.pixels, zB = zBuffer, df = diffuse, spc = specular)
-            {
-                for (int x = xL; x < xR; x++)
-                {
-                    pos = x + offset;
-                    if (z < zB[pos])
-                    {
-                        lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
-                        bkgrd = sp[pos];
-                        c = warp_Color.multiply(color, df[lutID]);
-                        s = spc[lutID];
-                        s = warp_Color.scale(s, reflectivity);
-                        c = warp_Color.overSolid(bkgrd, c);
-                        c = warp_Color.add(c, s);
-                        sp[pos] = c;
-                        zB[pos] = z;
-                    }
-                    z += dz;
-                    nx += dnx;
-                    ny += dny;
+                                    int bkgrd = Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos));
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.overSolid(bkgrd, s);
+                                }
+
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                            }
+                            break;
+
+                        case E | OPAQUE:
+                            //renderLineEO();
+                            renvmap = ref MemoryMarshal.GetArrayDataReference(envmap);
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    int s = Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID));
+                                    s = warp_Color.add(s, Unsafe.As<int, int>(ref Unsafe.Add(ref renvmap, lutID)));
+                                    s = warp_Color.scale(s, reflectivity);
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.scale(s, reflectivity);
+                                }
+
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                            }
+                            break;
+                        case T:
+                            //renderLineT();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int tpindx = (((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW);
+                                    int c = Unsafe.As<int, int>(ref Unsafe.Add(ref rtpixels, tpindx));
+                                    c = warp_Color.multiply(color, c);
+
+                                    int bkgrd = Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos));
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.overSolid(bkgrd, c);
+                                }
+
+                                z += dz;
+                                tx += dtx;
+                                ty += dty;
+                                sw += dsw;
+                            }
+                            break;
+
+                        case T | OPAQUE:
+                            //renderLineTO();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int tpindx = (((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW);
+                                    int c = Unsafe.As<int, int>(ref Unsafe.Add(ref rtpixels, tpindx));
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.multiply(color, c);
+                                }
+
+                                z += dz;
+                                tx += dtx;
+                                ty += dty;
+                                sw += dsw;
+                            }
+                            break;
+                        case P | E:
+                            renderLinePE();
+                            break;
+                        case P | E | OPAQUE:
+                            renderLinePEO();
+                            break;
+
+                        case P | T:
+                            //renderLinePT();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int tpindx = (((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW);
+                                    int c = Unsafe.As<int, int>(ref Unsafe.Add(ref rtpixels, tpindx));
+                                    c = warp_Color.multiply(color, c);
+
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    c = warp_Color.multiply(c, Unsafe.As<int, int>(ref Unsafe.Add(ref rdifuse, lutID)));
+                                    int s = warp_Color.scale(Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID)), reflectivity);
+
+                                    int bkgrd = Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos));
+                                    c = warp_Color.overSolid(bkgrd, c);
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.add(c, s);
+                                }
+
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                                tx += dtx;
+                                ty += dty;
+                                sw += dsw;
+                            }
+                            break;
+
+                        case P | T | OPAQUE:
+                            //renderLinePTO();
+                            for (int pos = xL + offset; pos < posEnd; pos++)
+                            {
+                                if (z < Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)))
+                                {
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rzbuf, pos)) = z;
+
+                                    int tpindx = (((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW);
+                                    int c = Unsafe.As<int, int>(ref Unsafe.Add(ref rtpixels, tpindx));
+                                    c = warp_Color.multiply(color, c);
+
+                                    int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                                    c = warp_Color.multiply(c, Unsafe.As<int, int>(ref Unsafe.Add(ref rdifuse, lutID)));
+                                    int s = warp_Color.scale(Unsafe.As<int, int>(ref Unsafe.Add(ref rspecular, lutID)), reflectivity);
+                                    Unsafe.As<int, int>(ref Unsafe.Add(ref rpixels, pos)) = warp_Color.add(c, s);
+                                }
+
+                                z += dz;
+                                nx += dnx;
+                                ny += dny;
+                                tx += dtx;
+                                ty += dty;
+                                sw += dsw;
+                            }
+                            break;
+
+                        case P | E | T:
+                            renderLinePET();
+                            break;
+                        case P | E | T | OPAQUE:
+                            renderLinePETO();
+                            break;
+                        default:
+                            return;
+                    };
+
+                    xBase += dxL;
+                    xMax += dxR;
+                    zBase += dzBase;
+                    nxBase += dnxBase;
+                    nyBase += dnyBase;
+                    txBase += dtxBase;
+                    tyBase += dtyBase;
+                    swBase += dswBase;
                 }
             }
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLineE()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe void renderLinePE()
         {
             int bkgrd;
+            int c;
             int s;
             int lutID;
             int pos;

-            fixed (int* sp = screen.pixels, zB = zBuffer, spc = specular, env = envmap)
+            fixed (int* sp = screen.pixels, zB = zBuffer, df = diffuse, spc = specular, env = envmap)
             {
                 for (int x = xL; x < xR; x++)
                 {
@@ -524,10 +657,13 @@ namespace Warp3D
                     if (z < zB[pos])
                     {
                         lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+
                         bkgrd = sp[pos];
                         s = warp_Color.add(spc[lutID], env[lutID]);
                         s = warp_Color.scale(s, reflectivity);
-                        sp[pos] = warp_Color.overSolid(bkgrd, s);;
+                        c = warp_Color.multiply(color, df[lutID]);
+                        c = warp_Color.overSolid(bkgrd, c);
+                        sp[pos] = warp_Color.add(c, s);
                         zB[pos] = z;
                     }
                     z += dz;
@@ -537,39 +673,9 @@ namespace Warp3D
             }
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLineT()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe void renderLinePEO()
         {
-            int bkgrd;
-            int c;
-            int pos;
-
-            fixed (int* sp = screen.pixels, zB = zBuffer, tp = tpixels)
-            {
-                for (int x = xL; x < xR; x++)
-                {
-                    pos = x + offset;
-                    if (z < zB[pos])
-                    {
-                        bkgrd = sp[pos];
-                        c = tp[(((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW)];
-                        c = warp_Color.multiply(color, c);
-                        c = warp_Color.overSolid(bkgrd, c);
-                        sp[pos] = c;
-                        zB[pos] = z;
-                    }
-                    z += dz;
-                    tx += dtx;
-                    ty += dty;
-                    sw += dsw;
-                }
-            }
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLinePE()
-        {
-            int bkgrd;
             int c;
             int s;
             int lutID;
@@ -584,13 +690,10 @@ namespace Warp3D
                     {
                         lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);

-                        bkgrd = sp[pos];
                         s = warp_Color.add(spc[lutID], env[lutID]);
                         s = warp_Color.scale(s, reflectivity);
                         c = warp_Color.multiply(color, df[lutID]);
-                        c = warp_Color.overSolid(bkgrd, c);
-                        c = warp_Color.add(c, s);
-                        sp[pos] = c;
+                        sp[pos] = warp_Color.add(c, s);
                         zB[pos] = z;
                     }
                     z += dz;
@@ -600,35 +703,27 @@ namespace Warp3D
             }
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLinePT()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe void renderLinePET()
         {
-            int bkgrd;
-            int c;
-            int s;
-            int lutID;
-            int pos;
-
-            fixed (int* sp = screen.pixels, zB = zBuffer, df = diffuse, spc = specular, tp = tpixels)
+            fixed (int* sp = screen.pixels, zB = zBuffer, df = diffuse, spc = specular, tp = tpixels, env = envmap)
             {
                 for (int x = xL; x < xR; x++)
                 {
-                    pos = x + offset;
+                    int pos = x + offset;
                     if (z < zB[pos])
                     {
-                        lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
-
-                        bkgrd = sp[pos];
-                        s = warp_Color.scale(spc[lutID], reflectivity);
-                        c = tp[(((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW)];
+                        int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                        int bkgrd = sp[pos];
+                        int s = warp_Color.add(spc[lutID], env[lutID]);
+                        s = warp_Color.scale(s, reflectivity);
+                        int c = tp[(((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW)];
                         c = warp_Color.multiply(color, c);
                         c = warp_Color.multiply(c, df[lutID]);
                         c = warp_Color.overSolid(bkgrd, c);
-                        c = warp_Color.add(c, s);
-                        sp[pos] = c;
+                        sp[pos] = warp_Color.add(c, s);
                         zB[pos] = z;
                     }
-
                     z += dz;
                     nx += dnx;
                     ny += dny;
@@ -638,34 +733,23 @@ namespace Warp3D
                 }
             }
         }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe void renderLinePET()
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private unsafe void renderLinePETO()
         {
-            int bkgrd;
-            int c;
-            int s;
-            int lutID;
-            int pos;
-
             fixed (int* sp = screen.pixels, zB = zBuffer, df = diffuse, spc = specular, tp = tpixels, env = envmap)
             {
                 for (int x = xL; x < xR; x++)
                 {
-                    pos = x + offset;
+                    int pos = x + offset;
                     if (z < zB[pos])
                     {
-                        lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
-                        bkgrd = sp[pos];
-                        s = warp_Color.add(spc[lutID], env[lutID]);
+                        int lutID = ((nx >> 16) & 255) + (((ny >> 16) & 255) << 8);
+                        int s = warp_Color.add(spc[lutID], env[lutID]);
                         s = warp_Color.scale(s, reflectivity);
-                        c = tp[(((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW)];
+                        int c = tp[(((int)(tx / sw)) & tw) + ((((int)(ty / sw)) & th) << tbitW)];
                         c = warp_Color.multiply(color, c);
                         c = warp_Color.multiply(c, df[lutID]);
-                        c = warp_Color.overSolid(bkgrd, c);
-                        c = warp_Color.add(c, s);
-
-                        sp[pos] = c;
+                        sp[pos] = warp_Color.add(c, s);
                         zB[pos] = z;
                     }
                     z += dz;
@@ -692,8 +776,8 @@ namespace Warp3D
             if ((a.clipcode & b.clipcode) != 0)
                 return;

-            dx = (int)Math.Abs(a.x - b.x);
-            dy = (int)Math.Abs(a.y - b.y);
+            dx = (int)MathF.Abs(a.x - b.x);
+            dy = (int)MathF.Abs(a.y - b.y);
             dz = 0;

             fixed (int* sp = screen.pixels, zB = zBuffer)
diff --git a/trunk/managed/Warp3Dmod/warp_RenderPipeline.cs b/trunk/managed/Warp3Dmod/warp_RenderPipeline.cs
index 2de4eb6..f8a4552 100644
--- a/trunk/managed/Warp3Dmod/warp_RenderPipeline.cs
+++ b/trunk/managed/Warp3Dmod/warp_RenderPipeline.cs
@@ -1,24 +1,22 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
     /// <summary>
     /// Summary description for warp_RenderPipeline.
     /// </summary>
-    public class warp_RenderPipeline: IDisposable
+    public class warp_RenderPipeline
     {
         public warp_Screen screen;
-        warp_Scene scene;
+        readonly warp_Scene scene;
         public warp_Lightmap lightmap;

         public bool useId = false;

         warp_Rasterizer rasterizer;
-
-        ArrayList transparentQueue = new ArrayList(16384);
-
         int zFar = int.MaxValue;

         public int[] zBuffer;
@@ -34,7 +32,7 @@ namespace Warp3D

         public void buildLightMap()
         {
-            if(lightmap == null)
+            if (lightmap == null)
             {
                 lightmap = new warp_Lightmap(scene);
             }
@@ -51,9 +49,8 @@ namespace Warp3D
             rasterizer.rebuildReferences(this);

             warp_Math.clearBuffer(zBuffer, zFar);
-            //System.Array.Copy(screen.zBuffer,0,zBuffer,0,zBuffer.Length);

-            if(scene.environment.background != null)
+            if (scene.environment.background is not null)
             {
                 screen.drawBackground(scene.environment.background, 0, 0, screen.width, screen.height);
             }
@@ -64,17 +61,17 @@ namespace Warp3D

             cam.setScreensize(screen.width, screen.height);
             scene.prepareForRendering();
-            emptyQueues();

             // Project
             warp_Matrix m = warp_Matrix.multiply(cam.getMatrix(), scene.matrix);
             warp_Matrix nm = warp_Matrix.multiply(cam.getNormalMatrix(), scene.normalmatrix);
-            warp_Matrix vertexProjection, normalProjection;
+            warp_Matrix vertexProjection = new warp_Matrix();
+            warp_Matrix normalProjection = new warp_Matrix();
             warp_Object obj;
             warp_Triangle t;
             warp_Vertex v;
             warp_Material objmaterial;
-            const double log2inv = 1.4426950408889634073599246810019;
+
             int w = screen.width;
             int h = screen.height;
             int minx;
@@ -82,55 +79,53 @@ namespace Warp3D
             int maxx;
             int maxy;

-            for(int id = 0 ; id < scene.objects; ++id)
+            List<warp_Triangle> transparentQueue = new List<warp_Triangle>(4 * scene.wobject.Length);
+
+            for (int id = 0; id < scene.wobject.Length; ++id)
             {
                 obj = scene.wobject[id];
-                objmaterial = obj.material;
-                if(objmaterial == null)
+                if (!obj.visible)
                     continue;
-                if(!obj.visible)
+                objmaterial = obj.material;
+                if (objmaterial is null)
                     continue;
-                if(objmaterial.opaque && objmaterial.reflectivity == 0)
+                if (objmaterial.opaque && objmaterial.reflectivity == 0)
                     continue;

-                vertexProjection = obj.matrix.getClone();
-                normalProjection = obj.normalmatrix.getClone();
-                vertexProjection.transform(m);
-                normalProjection.transform(nm);
+                vertexProjection.SetFromtransform(obj.matrix, m);
+                normalProjection.SetFromtransform(obj.normalmatrix, nm);
+
                 minx = int.MaxValue;
                 miny = int.MaxValue;
                 maxx = int.MinValue;
                 maxy = int.MinValue;

-                for(int i = 0; i < obj.vertices; ++i)
+                for (int i = 0; i < obj.vertexData.Count; ++i)
                 {
-                    v = obj.fastvertex[i];
+                    v = obj.vertexData[i];
                     v.project(vertexProjection, normalProjection, cam);
                     v.clipFrustrum(w, h);
-                    if(minx > v.x)
+                    if (minx > v.x)
                         minx = v.x;
-                    if(maxx < v.x)
+                    if (maxx < v.x)
                         maxx = v.x;
-                    if(miny > v.y)
+                    if (miny > v.y)
                         miny = v.y;
-                    if(maxy < v.y)
+                    if (maxy < v.y)
                         maxy = v.y;
                 }
-                maxx -= minx;
-                maxy -= miny;
-                if(maxy > maxx)
-                    maxx = maxy + 1;
-                else
-                    maxx++;
+                maxx = Math.Abs(maxx - minx);
+                maxy = Math.Abs(maxy - miny);
+                if (maxy > maxx)
+                    maxx = maxy;

-                obj.projectedmaxMips = (int)Math.Ceiling((Math.Log(maxx) * log2inv));
-                obj.cacheMaterialData();
+                obj.projectedmaxMips = System.Numerics.BitOperations.Log2((uint)maxx + 1);
                 if (objmaterial.opaque)
                 {
-                    rasterizer.loadFastMaterial(obj);
-                    for (int i = 0; i < obj.triangles; ++i)
+                    rasterizer.loadMaterial(obj);
+                    for (int i = 0; i < obj.triangleData.Count; ++i)
                     {
-                        t = obj.fasttriangle[i];
+                        t = obj.triangleData[i];
                         t.project(normalProjection);
                         if (t.clipFrustrum(w, h))
                             rasterizer.render(t);
@@ -138,9 +133,9 @@ namespace Warp3D
                 }
                 else
                 {
-                    for (int i = 0; i < obj.triangles; ++i)
+                    for (int i = 0; i < obj.triangleData.Count; ++i)
                     {
-                        t = obj.fasttriangle[i];
+                        t = obj.triangleData[i];
                         t.project(normalProjection);
                         if (t.clipFrustrum(w, h))
                             transparentQueue.Add(t);
@@ -149,122 +144,27 @@ namespace Warp3D
             }

             //screen.lockImage();
-
-            warp_Triangle[] tri;
             obj = null;
-            tri = getTransparentQueue();
-            if(tri != null)
+            if (transparentQueue.Count > 0)
             {
-                transparentQueue.Clear();
-                for (int i = 0; i < tri.GetLength(0); i++)
+                transparentQueue.Sort(CompareTrisDistance);
+                for (int i = 0; i < transparentQueue.Count; i++)
                 {
-                    if(obj != tri[i].parent)
+                    if (obj != transparentQueue[i].parent)
                     {
-                        obj = tri[i].parent;
-                        rasterizer.loadFastMaterial(obj);
+                        obj = transparentQueue[i].parent;
+                        rasterizer.loadMaterial(obj);
                     }
-                    rasterizer.render(tri[i]);
+                    rasterizer.render(transparentQueue[i]);
                 }
             }
+            transparentQueue = null;

-            //screen.unlockImage();
-        }
-
-        private void performResizing()
-        {
-            //screen.resize(requestedWidth, requestedHeight);
-            zBuffer = new int[screen.width * screen.height];
-        }
-
-        // Triangle sorting
-        private void emptyQueues()
-        {
-            transparentQueue.Clear();
-        }
-
-        private warp_Triangle[] getTransparentQueue()
-        {
-            if(transparentQueue.Count == 0)
-                return null;
-
-            IComparer comp = new tridistZDescCompare();
-            transparentQueue.Sort(comp);
-            warp_Triangle[] tri = new warp_Triangle[transparentQueue.Count];
-            int id = 0;
-            for(int i = 0; i < transparentQueue.Count; ++i)
-                tri[id++] = (warp_Triangle)transparentQueue[i];
-
-            //return sortTriangles(tri, 0, tri.GetLength(0) - 1);
-            return tri;
-        }
-
-        private warp_Triangle[] sortTriangles(warp_Triangle[] tri, int L, int R)
-        {
-            //FIX: Added Index bounds checking. (Was causing random exceptions) - Created by: X
-            if(L < 0)
-                L = 0;
-            if(L > tri.GetLength(0))
-                L = tri.GetLength(0);
-            if(R < 0)
-                R = 0;
-            if(R > tri.GetLength(0))
-                R = tri.GetLength(0);
-            // - Created by: X
-
-            float m = (tri[L].distZ + tri[R].distZ) / 2;
-            int i = L;
-            int j = R;
-            warp_Triangle temp;
-
-            do
+            [MethodImpl(MethodImplOptions.AggressiveInlining)]
+            int CompareTrisDistance(warp_Triangle x, warp_Triangle y)
             {
-                while(tri[i].distZ > m)
-                    i++;
-                while(tri[j].distZ < m)
-                    j--;
-
-                if(i <= j)
-                {
-                    temp = tri[i];
-                    tri[i] = tri[j];
-                    tri[j] = temp;
-                    i++;
-                    j--;
-                }
+                return y.minDistZ.CompareTo(x.minDistZ);
             }
-            while(j >= i);
-
-            if(L < j)
-                sortTriangles(tri, L, j);
-            if(R > i)
-                sortTriangles(tri, i, R);
-
-            return tri;
-        }
-
-        public void Dispose()
-        {
-            if(screen != null)
-                screen.Dispose();
-            screen = null;
-            zBuffer = null;
-            rasterizer.clean();
-            rasterizer = null;
-            transparentQueue.Clear();
-            transparentQueue = null;
-        }
-    }
-
-    public class tridistZDescCompare : IComparer
-    {
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        int IComparer.Compare(object x, object y)
-        {
-            float a = ((warp_Triangle)x).distZ;
-            float b = ((warp_Triangle)y).distZ;
-            if( a == b )
-                return 0;
-            return a < b ? 1 : -1;
         }
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Scene.cs b/trunk/managed/Warp3Dmod/warp_Scene.cs
index f16c88c..9a4707f 100644
--- a/trunk/managed/Warp3Dmod/warp_Scene.cs
+++ b/trunk/managed/Warp3Dmod/warp_Scene.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Drawing;
 using System.Timers;

@@ -10,33 +11,30 @@ namespace Warp3D
     /// </summary>
     public class warp_Scene : warp_CoreObject
     {
-        public static String version = "1.0.0";
-        public static String release = "0010";
+        public static string version = "1.0.1";
+        public static string release = "0010";

         public warp_RenderPipeline renderPipeline;
         public int width, height;

-        public warp_Environment environment = new warp_Environment();
+        public warp_Environment environment = new();
         public warp_Camera defaultCamera = warp_Camera.FRONT();

         public warp_Object[] wobject;
         public warp_Light[] light;

-        public int objects = 0;
-        public int lights = 0;
-
         private bool objectsNeedRebuild = true;
         private bool lightsNeedRebuild = true;

         protected bool preparedForRendering = false;

-        public warp_Vector normalizedOffset = new warp_Vector(0f, 0f, 0f);
+        public warp_Vector normalizedOffset = new(0f, 0f, 0f);
         public float normalizedScale = 1f;

-        public Hashtable objectData = new Hashtable();
-        public Hashtable lightData = new Hashtable();
-        public Hashtable materialData = new Hashtable();
-        public Hashtable cameraData = new Hashtable();
+        public Dictionary<string, warp_Object> objectData = new();
+        public Dictionary<string, warp_Light> lightData = new();
+        public Dictionary<string, warp_Material> materialData = new();
+        public Dictionary<string, warp_Camera> cameraData = new();

         public warp_Scene()
         {
@@ -52,16 +50,13 @@ namespace Warp3D

         public void destroy()
         {
-            objects = objectData.Count;
             foreach (warp_Object o in objectData.Values)
                 o.destroy();

-            objectData.Clear();
-            lightData.Clear();
-            materialData.Clear();
-            cameraData.Clear();
-            if (renderPipeline != null)
-                renderPipeline.Dispose();
+            objectData = null;
+            lightData = null;
+            materialData = null;
+            cameraData = null;
             renderPipeline = null;
             environment = null;
             defaultCamera = null;
@@ -70,8 +65,7 @@ namespace Warp3D

         public void removeAllObjects()
         {
-
-            objectData = new Hashtable();
+            objectData = new Dictionary<string, warp_Object>();
             objectsNeedRebuild = true;
             rebuild();
         }
@@ -82,54 +76,53 @@ namespace Warp3D
             {
                 objectsNeedRebuild = false;

-                objects = objectData.Count;
-                wobject = new warp_Object[objects];
-                IDictionaryEnumerator enumerator = objectData.GetEnumerator();
+                wobject = new warp_Object[objectData.Count];

-                for (int i = 0; i < objects; ++i)
+                int i = 0;
+                foreach (warp_Object o in objectData.Values)
                 {
-                    enumerator.MoveNext();
-                    wobject[i] = (warp_Object)enumerator.Value;
-
+                    wobject[i] = o;
                     wobject[i].id = i;
                     wobject[i].rebuild();
+                    i++;
                 }
             }

             if (lightsNeedRebuild)
             {
                 lightsNeedRebuild = false;
-                lights = lightData.Count;
-                light = new warp_Light[lights];
-                IDictionaryEnumerator enumerator = lightData.GetEnumerator();
-                for (int i = lights - 1; i >= 0; i--)
-                {
-                    enumerator.MoveNext();
-                    light[i] = (warp_Light)enumerator.Value;
-
-                }
+                light = new warp_Light[lightData.Count];
+                lightData.Values.CopyTo(light, 0);
             }
         }

-        public warp_Object sceneobject(String key)
+        public warp_Object sceneobject(string key)
         {
-            return (warp_Object)objectData[key];
+            if (objectData.TryGetValue(key, out warp_Object obj))
+                return obj;
+            return null;
+        }
+        public bool TryGetSceneObject(string key, out warp_Object obj)
+        {
+            return objectData.TryGetValue(key, out obj);
         }

-        public warp_Material material(String key)
+        public bool TryGetMaterial(string key, out warp_Material material)
         {
-            return (warp_Material)materialData[key];
+            return materialData.TryGetValue(key, out material);
         }

-        public warp_Camera camera(String key)
+        public warp_Camera camera(string key)
         {
-            return (warp_Camera)cameraData[key];
+            if (cameraData.TryGetValue(key, out warp_Camera camera))
+                return camera;
+            return null;
         }

-        public void addObject(String key, warp_Object obj)
+        public void addObject(string key, warp_Object obj)
         {
             obj.name = key;
-            objectData.Add(key, obj);
+            objectData[key] = obj;
             obj.parent = this;
             objectsNeedRebuild = true;
             preparedForRendering = false;
@@ -142,19 +135,19 @@ namespace Warp3D
             preparedForRendering = false;
         }

-        public void addMaterial(String key, warp_Material m)
+        public void addMaterial(string key, warp_Material m)
         {
-            materialData.Add(key, m);
+            materialData[key] = m;
         }

-        public void removeMaterial(String key)
+        public void removeMaterial(string key)
         {
             materialData.Remove(key);
         }

         public void addCamera(String key, warp_Camera c)
         {
-            cameraData.Add(key, c);
+            cameraData[key] = c;
         }

         public void removeCamera(String key)
@@ -162,9 +155,9 @@ namespace Warp3D
             cameraData.Remove(key);
         }

-        public void addLight(String key, warp_Light l)
+        public void addLight(string key, warp_Light l)
         {
-            lightData.Add(key, l);
+            lightData[key] = l;
             lightsNeedRebuild = true;
         }

@@ -213,14 +206,16 @@ namespace Warp3D
         public int countVertices()
         {
             int counter = 0;
-            for (int i = 0; i < objects; i++) counter += wobject[i].vertices;
+            for (int i = 0; i < wobject.Length; i++)
+                counter += wobject[i].vertexData.Count;
             return counter;
         }

         public int countTriangles()
         {
             int counter = 0;
-            for (int i = 0; i < objects; i++) counter += wobject[i].triangles;
+            for (int i = 0; i < wobject.Length; i++)
+                counter += wobject[i].triangleData.Count;
             return counter;
         }

@@ -229,46 +224,30 @@ namespace Warp3D
             objectsNeedRebuild = true;
             rebuild();

-            warp_Vector min, max, tempmax, tempmin;
-            if (objects == 0)
-            {
+            if (wobject.Length == 0)
                 return;
-            }

             matrix = new warp_Matrix();
             normalmatrix = new warp_Matrix();

-            max = wobject[0].maximum();
-            min = wobject[0].maximum();
-
-            for (int i = 0; i < objects; i++)
+            warp_Vector min = wobject[0].fastMin;
+            warp_Vector max = wobject[0].fastMax;
+            for (int i = 0; i < wobject.Length; i++)
             {
-                tempmax = wobject[i].maximum();
-                tempmin = wobject[i].maximum();
+                warp_Vector tempmin = wobject[i].fastMin;
+                warp_Vector tempmax = wobject[i].fastMax;
                 if (tempmax.x > max.x)
-                {
                     max.x = tempmax.x;
-                }
                 if (tempmax.y > max.y)
-                {
                     max.y = tempmax.y;
-                }
                 if (tempmax.z > max.z)
-                {
                     max.z = tempmax.z;
-                }
                 if (tempmin.x < min.x)
-                {
                     min.x = tempmin.x;
-                }
                 if (tempmin.y < min.y)
-                {
                     min.y = tempmin.y;
-                }
                 if (tempmin.z < min.z)
-                {
                     min.z = tempmin.z;
-                }
             }
             float xdist = max.x - min.x;
             float ydist = max.y - min.y;
@@ -289,7 +268,7 @@ namespace Warp3D

         public float EstimateBoxProjectedArea(warp_Vector pos, warp_Vector size, warp_Matrix rotation)
         {
-            warp_Matrix om = new warp_Matrix();
+            warp_Matrix om = new();
             om.scale(size.x, size.y, size.z);
             om.transform(rotation);

@@ -316,14 +295,12 @@ namespace Warp3D
             warp_Matrix m = warp_Matrix.multiply(defaultCamera.getMatrix(), matrix);
             om.transform(m);

-            float zmin;
             side = new warp_Vector(-1f, -1f, -1f);
             v = side.transform(om);
             xmin = v.x;
             xmax = xmin;
             ymin = v.y;
             ymax = ymin;
-            zmin = v.z;

             side.x = 1f;
             v = side.transform(om);
@@ -335,8 +312,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = -1f;
             side.y = 1f;
@@ -349,8 +324,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = 1f;
             v = side.transform(om);
@@ -362,8 +335,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = -1f;
             side.y = -1f;
@@ -377,8 +348,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = 1f;
             v = side.transform(om);
@@ -390,8 +359,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = -1f;
             side.y = 1f;
@@ -404,8 +371,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;

             side.x = 1f;
             v = side.transform(om);
@@ -417,9 +382,6 @@ namespace Warp3D
                 ymin = v.y;
             else if (ymax < v.y)
                 ymax = v.y;
-            if (zmin > v.z)
-                zmin = v.z;
-

             xmax -= xmin;
             ymax -= ymin;
diff --git a/trunk/managed/Warp3Dmod/warp_Screen.cs b/trunk/managed/Warp3Dmod/warp_Screen.cs
index a7864b8..01db82c 100644
--- a/trunk/managed/Warp3Dmod/warp_Screen.cs
+++ b/trunk/managed/Warp3Dmod/warp_Screen.cs
@@ -2,20 +2,18 @@ using System;
 using System.Drawing;
 using System.Drawing.Imaging;
 using System.Runtime.InteropServices;
+using static System.Net.Mime.MediaTypeNames;

 namespace Warp3D
 {
     /// <summary>
     /// Summary description for warp_Screen.
     /// </summary>
-    unsafe public class warp_Screen : IDisposable
+    unsafe public class warp_Screen
     {
         public int width;
         public int height;
-
-        Bitmap image = null;
         public int[] pixels;
-        private GCHandle handle;

         public warp_Screen(int w, int h)
         {
@@ -23,11 +21,6 @@ namespace Warp3D
             height = h;

             pixels = new int[w * h];
-
-            handle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
-            IntPtr pointer = Marshal.UnsafeAddrOfPinnedArrayElement(pixels, 0);
-
-            image = new Bitmap(w, h, w * 4, PixelFormat.Format32bppPArgb, pointer);
         }

         public void clear(int c)
@@ -47,12 +40,18 @@ namespace Warp3D

         public Bitmap getImage()
         {
-            return new Bitmap(image);
+            GCHandle handle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
+            IntPtr pointer = Marshal.UnsafeAddrOfPinnedArrayElement(pixels, 0);
+            Bitmap image = new Bitmap(width, height, width * 4, PixelFormat.Format32bppPArgb, pointer);
+            Bitmap ret = new Bitmap(image); //duhhhh
+            image.Dispose();
+            handle.Free();
+            return ret;
         }

         private unsafe void draw(int width, int height, warp_Texture texture, int posx, int posy, int xsize, int ysize)
         {
-            if (texture == null)
+            if (texture is null)
             {
                 return;
             }
@@ -74,7 +73,7 @@ namespace Warp3D
             xBase = warp_Math.crop(xBase, 0, width);
             yBase = warp_Math.crop(yBase, 0, height);

-            fixed(int* px = pixels, txp = texture.pixel)
+            fixed (int* px = pixels, txp = texture.pixel)
             {
                 ty = tyBase;
                 for (int j = yBase; j < yend; j++)
@@ -99,7 +98,7 @@ namespace Warp3D

         private void add(int width, int height, warp_Texture texture, int posx, int posy, int xsize, int ysize)
         {
-            if (texture == null)
+            if (texture is null)
             {
                 return;
             }
@@ -138,16 +137,5 @@ namespace Warp3D
                 }
             }
         }
-
-        public void Dispose()
-        {
-            if (image != null)
-            {
-                handle.Free();
-                image.Dispose();
-                image = null;
-                pixels = null;
-            }
-        }
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Texture.cs b/trunk/managed/Warp3Dmod/warp_Texture.cs
index 7751513..53ad8b7 100644
--- a/trunk/managed/Warp3Dmod/warp_Texture.cs
+++ b/trunk/managed/Warp3Dmod/warp_Texture.cs
@@ -1,7 +1,11 @@
 using System;
 using System.Drawing;
 using System.Drawing.Imaging;
+using System.Globalization;
 using System.Net;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;

 namespace Warp3D
 {
@@ -16,7 +20,7 @@ namespace Warp3D
         public int bitWidth;
         public int bitHeight;
         public int[] pixel;
-        public String path = null;
+        public string path = null;
         public int averageColor;
         public bool hasAlpha;
         public bool opaque;
@@ -38,59 +42,66 @@ namespace Warp3D
             cls();
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Texture(int w, int h, int[] data)
         {
             height = h;
             width = w;
             pixel = new int[width * height];

-            System.Array.Copy(data, pixel, pixel.Length);
+            Array.Copy(data, pixel, pixel.Length);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Texture(Bitmap map, int maxBitSize = -1)
         {
             loadTexture(map, maxBitSize);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Texture(string path, int maxBitSize = -1)
         {
-            using(Bitmap map = new Bitmap(path, false))
-                loadTexture(map, maxBitSize);
+            using Bitmap map = new(path, false);
+            loadTexture(map, maxBitSize);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void resize()
         {
-            double log2inv = 1 / Math.Log(2);
-
-            int w = (int)Math.Pow(2, bitWidth = (int)Math.Ceiling((Math.Log(width) * log2inv)));
-            int h = (int)Math.Pow(2, bitHeight = (int)Math.Ceiling((Math.Log(height) * log2inv)));
+            int w = (int)Math.Pow(2, bitWidth = (int)Math.Ceiling(MathF.Log2(width)));
+            int h = (int)Math.Pow(2, bitHeight = (int)Math.Ceiling(MathF.Log2(height)));

-            if(!(w == width && h == height))
+            if (w != width || h != height)
                 resize(w, h);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void resize(int w, int h)
         {
             setSize(w, h);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void cls()
         {
             warp_Math.clearBuffer(pixel, 0);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Texture toAverage()
         {
-            for(int i = width * height - 1; i >= 0; i--)
-                pixel[i] = warp_Color.getAverage(pixel[i]);
+            ref int rpixel = ref MemoryMarshal.GetArrayDataReference(pixel);
+            for (int i = 0; i < pixel.Length; i++)
+                Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)) = warp_Color.getAverage(Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)));

             return this;
         }

         public warp_Texture toGray()
         {
-            for(int i = width * height - 1; i >= 0; i--)
-                pixel[i] = warp_Color.getGray(pixel[i]);
+            ref int rpixel = ref MemoryMarshal.GetArrayDataReference(pixel);
+            for (int i = 0; i < pixel.Length; i++)
+                Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)) = warp_Color.getGray(Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)));

             return this;
         }
@@ -98,10 +109,11 @@ namespace Warp3D
         public warp_Texture valToGray()
         {
             int intensity;
-            for(int i = width * height - 1; i >= 0; i--)
+            ref int rpixel = ref MemoryMarshal.GetArrayDataReference(pixel);
+            for (int i = 0; i < pixel.Length; i++)
             {
-                intensity = warp_Math.crop(pixel[i], 0, 255);
-                pixel[i] = warp_Color.getColor(intensity, intensity, intensity);
+                intensity = warp_Math.crop(Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)), 0, 255);
+                Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)) = warp_Color.getColor(intensity, intensity, intensity);
             }

             return this;
@@ -110,8 +122,10 @@ namespace Warp3D
         public warp_Texture colorize(int[] pal)
         {
             int range = pal.GetLength(0) - 1;
-            for(int i = width * height - 1; i >= 0; i--)
-                pixel[i] = pal[warp_Math.crop(pixel[i], 0, range)];
+            ref int rpixel = ref MemoryMarshal.GetArrayDataReference(pixel);
+            for (int i = 0; i < pixel.Length; i++)
+                Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)) =
+                    pal[warp_Math.crop(Unsafe.As<int, int>(ref Unsafe.Add(ref rpixel, i)), 0, range)];

             return this;
         }
@@ -126,30 +140,23 @@ namespace Warp3D
             height = map.Height;

             PixelFormat format = pmap.PixelFormat;
-            PixelFormat targetformat;
-
-            switch(format)
+            PixelFormat targetformat = format switch
             {
-                case PixelFormat.Format16bppArgb1555:
-                case PixelFormat.Format32bppArgb:
-                case PixelFormat.Format32bppPArgb:
-                case PixelFormat.Format64bppArgb:
-                case PixelFormat.Format64bppPArgb:
-                    targetformat = PixelFormat.Format32bppArgb;
-                    break;
-                default:
-                    targetformat = PixelFormat.Format24bppRgb;
-                    break;
-            }
-
-           // make sure sizes are power of 2
-            const double log2inv = 1.4426950408889634073599246810019;
-            bitWidth = (int)Math.Ceiling((Math.Log(width) * log2inv));
-            bitHeight = (int)Math.Ceiling((Math.Log(height) * log2inv));
-
-            if(maxBitSize > 3)
+                PixelFormat.Format16bppArgb1555 => PixelFormat.Format32bppArgb,
+                PixelFormat.Format32bppArgb => PixelFormat.Format32bppArgb,
+                PixelFormat.Format32bppPArgb => PixelFormat.Format32bppArgb,
+                PixelFormat.Format64bppArgb => PixelFormat.Format32bppArgb,
+                PixelFormat.Format64bppPArgb => PixelFormat.Format32bppArgb,
+                _ => PixelFormat.Format24bppRgb
+            };
+
+            // make sure sizes are power of 2
+            bitWidth = (int)MathF.Ceiling(MathF.Log2(width));
+            bitHeight = (int)MathF.Ceiling(MathF.Log2(height));
+
+            if (maxBitSize > 3)
             {
-                if(bitWidth > bitHeight)
+                if (bitWidth > bitHeight)
                 {
                     if (bitWidth > maxBitSize)
                     {
@@ -173,10 +180,10 @@ namespace Warp3D
                 }
             }

-            int w = (int)Math.Pow(2, bitWidth);
-            int h = (int)Math.Pow(2, bitHeight);
+            int w = (int)MathF.Pow(2, bitWidth);
+            int h = (int)MathF.Pow(2, bitHeight);

-            if(width != w || height != h || format != targetformat)
+            if (width != w || height != h || format != targetformat)
             {
                 map = ResizeBitmap(pmap, w, h, targetformat);
                 width = w;
@@ -193,7 +200,7 @@ namespace Warp3D
             byte green;
             byte red;
             byte alpha;
-
+
             pixel = new int[width * height];
             hasAlpha = targetformat == PixelFormat.Format32bppArgb;

@@ -202,26 +209,26 @@ namespace Warp3D
             unsafe
             {
                 byte* p = (byte*)bmData.Scan0;
-                fixed(int* px = pixel)
+                fixed (int* px = pixel)
                 {
                     int nPixel = 0;
-                    if(hasAlpha)
+                    if (hasAlpha)
                     {
                         int nOffset = bmData.Stride - width * 4;
-                        for(int i = 0; i < height; i++)
+                        for (int i = 0; i < height; i++)
                         {
-                            for(int j = 0; j < width; j++)
+                            for (int j = 0; j < width; j++)
                             {
                                 blue = *(p++);
-                                avgB += blue;
+                                avgB += blue;
                                 green = *(p++);
-                                avgG += green;
+                                avgG += green;
                                 red = *(p++);
                                 avgR += red;
                                 alpha = *(p++);
                                 avgA += alpha;

-                                if(opaque && alpha != 0xff)
+                                if (opaque && alpha != 0xff)
                                     opaque = false;
                                 px[nPixel++] = alpha << 24 | red << 16 | green << 8 | blue;
                             }
@@ -231,9 +238,9 @@ namespace Warp3D
                     else
                     {
                         int nOffset = bmData.Stride - width * 3;
-                        for(int i = 0; i < height; i++)
+                        for (int i = 0; i < height; i++)
                         {
-                            for(int j = 0; j < width; j++)
+                            for (int j = 0; j < width; j++)
                             {
                                 blue = *(p++);
                                 avgB += blue;
@@ -251,7 +258,7 @@ namespace Warp3D
             }

             map.UnlockBits(bmData);
-            if(disposemap)
+            if (disposemap)
                 map.Dispose();

             ulong np = (ulong)(width * height);
@@ -259,16 +266,16 @@ namespace Warp3D
             blue = (byte)(avgB / np);
             green = (byte)(avgG / np);
             red = (byte)(avgR / np);
-            if(hasAlpha)
+            if (hasAlpha)
             {
-                alpha= (byte)(avgA / np);
+                alpha = (byte)(avgA / np);
                 averageColor = alpha << 24 | red << 16 | green << 8 | blue;
             }
             else
                 averageColor = ALPHA | red << 16 | green << 8 | blue;

             maxmips = bitHeight;
-            if(maxmips > bitWidth)
+            if (maxmips > bitWidth)
                 maxmips = bitWidth;

             maxmips -= 3; // less 1x1 2x2 and max
@@ -285,51 +292,33 @@ namespace Warp3D
             mipsBitHeight = new int[maxmips + 1];
             mipstw = new int[maxmips + 1];
             mipsth = new int[maxmips + 1];
-
+
             int w = width;
             int h = height;
             int bw = bitWidth;
             int bh = bitHeight;

             int[] src;
-            int[] dst = null;
-            for(int n = maxmips; n >= 0; --n)
+            int[] dst = mips[maxmips + 1];
+            for (int n = maxmips; n >= 0; --n)
             {
-                src = mips[n + 1];
-                if(w > 1)
-                {
-                    w >>= 1;
-                    --bw;
-                    if(h > 1)
-                    {
-                        h >>= 1;
-                        --bh;
-                        dst = dec2XY(src, w, h);
-                    }
-                    else
-                        dst = dec2X(src, w, h);
-                }
-                else
-                {
-                    if(h > 1)
-                    {
-                        h >>= 1;
-                        --bh;
-                        dst = dec2Y(src, w, h);
-                    }
-                }
+                src = dst;
+                w >>= 1;
+                h >>= 1;
+                dst = dec2XY(src, w, h);
                 mips[n] = dst;
-                mipsBitWidth[n] = bw;
-                mipsBitHeight[n] = bh;
+                mipsBitWidth[n] = --bw;
+                mipsBitHeight[n] = --bh;
                 mipstw[n] = w;
                 mipsth[n] = h;
             }
             hasmips = true;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private unsafe int[] dec2XY(int[] src, int w, int h)
         {
+            /*
             int[] dst = new int[w * h];
             int sw = 2 * w;
             int stot = 2 * h * sw;
@@ -341,9 +330,9 @@ namespace Warp3D
             int dx = 0;
             fixed (int* s = src, d = dst)
             {
-                for (int sx = 0 ; sx < stot; sx += sw, sxl2 += sw)
+                for (int sx = 0; sx < stot; sx += sw, sxl2 += sw)
                 {
-                    for(int i = 0; i < w ; i++, sx += 2, sxl2 += 2)
+                    for (int i = 0; i < w; i++, sx += 2, sxl2 += 2)
                     {
                         c1 = s[sx];
                         c2 = s[sx + 1];
@@ -354,48 +343,37 @@ namespace Warp3D
                 }
             }
             return dst;
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private int[] dec2X(int[] src, int w, int h)
-        {
-            int dstsize = w * h;
-            int[] dst = new int[dstsize];
-            int c1;
-            int c2;
-            int sx = 0;
+            */
+            int[] dst = new int[w * h];
+            int sw = 8 * w; // 4 bytes * 2 * w

-            for(int dx = 0 ; dx < dstsize; ++dx)
+            fixed (int* si = src, di = dst)
             {
-                c1 = src[sx];
-                c2 = src[sx + 1];
+                byte* d = (byte*)di;
+                byte* s = (byte*)si;
+                byte* s2 = s + sw;
+                for (int y = 0; y < h; y++)
+                {
+                    for (int x = 0; x < w; x++)
+                    {
+                        int t = s[0] + s[4] + s2[0] + s2[4] + 2;
+                        d[0] = (byte)(t >> 2);

-                dst[dx] = warp_Color.avg2c(c1, c2);
-                sx += 2;
-            }
+                        t = s[1] + s[5] + s2[1] + s2[5] + 2;
+                        d[1] = (byte)(t >> 2);

-            return dst;
-        }
+                        t = s[2] + s[6] + s2[2] + s2[6] + 2;
+                        d[2] = (byte)(t >> 2);

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        private unsafe int[] dec2Y(int[] src, int w, int h)
-        {
-            int[] dst = new int[w * h];
-            int stot = 2 * h * w;
-            int c1;
-            int c2;
-            int sxl2 = w;
-            int dx = 0;
-            fixed (int* s = src, d = dst)
-            {
-                for (int sx = 0 ; sx < stot; sx += w, sxl2 += w)
-                {
-                    for(int i = 0; i < w ; i++, ++sx, ++sxl2)
-                    {
-                        c1 = s[sx];
-                        c2 = s[sxl2];
-                        d[dx++] = warp_Color.avg2c(c1, c2);
+                        t = s[3] + s[7] + s2[3] + s2[7] + 2;
+                        d[3] = (byte)(t >> 2);
+
+                        d += 4;
+                        s += 8;
+                        s2 += 8;
                     }
+                    s += sw;
+                    s2 += sw;
                 }
             }
             return dst;
@@ -405,16 +383,16 @@ namespace Warp3D
         {
             int offset = w * h;
             int offset2;
-            if(w * h != 0)
+            if (w * h != 0)
             {
                 int[] newpixels = new int[w * h];
-                fixed(int* np = newpixels, p = pixel)
+                fixed (int* np = newpixels, p = pixel)
                 {
-                    for(int j = h - 1; j >= 0; j--)
+                    for (int j = h - 1; j >= 0; j--)
                     {
                         offset -= w;
                         offset2 = (j * height / h) * width;
-                        for(int i = w - 1; i >= 0; i--)
+                        for (int i = w - 1; i >= 0; i--)
                             np[i + offset] = p[(i * width / w) + offset2];
                     }
                 }
@@ -424,7 +402,7 @@ namespace Warp3D
             }
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private bool inrange(int a, int b, int c)
         {
             return (a >= b) & (a < c);
@@ -432,16 +410,16 @@ namespace Warp3D

         public warp_Texture getClone()
         {
-            warp_Texture t = new warp_Texture(width, height);
+            warp_Texture t = new(width, height);
             warp_Math.copyBuffer(pixel, t.pixel);
             return t;
         }

         public static Bitmap ResizeBitmap(Image image, int width, int height, PixelFormat format)
         {
-            Bitmap result = new Bitmap(width, height, format);
+            Bitmap result = new(width, height, format);

-            using (ImageAttributes atrib = new ImageAttributes())
+            using (ImageAttributes atrib = new())
             using (Graphics graphics = Graphics.FromImage(result))
             {
                 atrib.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
@@ -451,7 +429,7 @@ namespace Warp3D
                 graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                 graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;

-                graphics.DrawImage(image,new Rectangle(0,0, result.Width, result.Height),
+                graphics.DrawImage(image, new Rectangle(0, 0, result.Width, result.Height),
                     0, 0, image.Width, image.Height, GraphicsUnit.Pixel, atrib);
             }

diff --git a/trunk/managed/Warp3Dmod/warp_TextureFactory.cs b/trunk/managed/Warp3Dmod/warp_TextureFactory.cs
index ce1c924..b700012 100644
--- a/trunk/managed/Warp3Dmod/warp_TextureFactory.cs
+++ b/trunk/managed/Warp3Dmod/warp_TextureFactory.cs
@@ -2,231 +2,231 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_TextureFactory.
-	/// </summary>
-	public class warp_TextureFactory
-	{
-		public  static float pi = 3.1415926535f;
-		public  static float deg2rad = pi / 180;
-		private static float[,] noiseBuffer;
-		private static bool noiseBufferInitialized = false;
-		public static int ALPHA = unchecked((int)0xFF000000); // alpha mask
-
-		private warp_TextureFactory()
-		{
-		}
-
-		public static warp_Texture SKY(int w, int h, float density)
-		{
-			int[] colors = new int[2];
-			colors[0] = 0x003399;
-			colors[1] = 0xFFFFFF;
-			return PERLIN(w, h, 0.5f, 2.8f * density, 8, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-		}
-
-		public static warp_Texture MARBLE(int w, int h, float density)
-		{
-			int[] colors = new int[3];
-			colors[0] = 0x111111;
-			colors[1] = 0x696070;
-			colors[2] = 0xFFFFFF;
-			return WAVE(w, h, 0.5f, 0.64f * density, 6, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-		}
-
-		public static warp_Texture WOOD(int w, int h, float density)
-		{
-			int[] colors = new int[3];
-			colors[0] = 0x332211;
-			colors[1] = 0x523121;
-			colors[2] = 0x996633;
-
-			return GRAIN(w, h, 0.5f, 3f * density, 3, 8, 1024).colorize(warp_Color.makeGradient(colors, 1024));
-		}
-
-		public static warp_Texture PERLIN(int w, int h, float persistency,
-			float density, int samples, int scale)
-		{
-			initNoiseBuffer();
-			warp_Texture t = new warp_Texture(w, h);
-			int pos = 0;
-			float wavelength = (float) ( (w > h) ? w : h) / density;
-
-			for (int y = 0; y < h; y++)
-			{
-				for (int x = 0; x < w; x++)
-				{
-					t.pixel[pos++] = (int) ( (float) scale *
-						perlin2d(x, y, wavelength, persistency,
-						samples));
-				}
-			}
-			return t;
-		}
-
-		public static warp_Texture WAVE(int w, int h, float persistency,
-			float density, int samples, int scale)
-		{
-			initNoiseBuffer();
-			warp_Texture t = new warp_Texture(w, h);
-			int pos = 0;
-			float wavelength = (float) ( (w > h) ? w : h) / density;
-
-			for (int y = 0; y < h; y++)
-			{
-				for (int x = 0; x < w; x++)
-				{
-					t.pixel[pos++] = (int) ( (double) scale *
-						(Math.Sin(32 *
-						perlin2d(x, y, wavelength,
-						persistency, samples)) * 0.5 + 0.5));
-				}
-			}
-			return t;
-		}
-
-		public static warp_Texture GRAIN(int w, int h, float persistency,
-			float density, int samples, int levels,
-			int scale)
-			// TIP: For wooden textures
-		{
-			initNoiseBuffer();
-			warp_Texture t = new warp_Texture(w, h);
-			int pos = 0;
-			float wavelength = (float) ( (w > h) ? w : h) / density;
-			float perlin;
-
-			for (int y = 0; y < h; y++)
-			{
-				for (int x = 0; x < w; x++)
-				{
-					perlin = (float) levels *
-						perlin2d(x, y, wavelength, persistency, samples);
-					t.pixel[pos++] = (int) ( (float) scale *
-						(perlin - (float) (int) perlin));
-				}
-			}
-			return t;
-		}
-
-		// Perlin noise functions
-
-		private static float perlin2d(float x, float y, float wavelength,
-			float persistence, int samples)
-		{
-			float sum = 0;
-			float freq = 1f / wavelength;
-			float amp = persistence;
-			float range = 0;
-
-			for (int i = 0; i < samples; i++)
-			{
-				sum += amp * interpolatedNoise(x * freq, y * freq, i);
-				range += amp;
-				amp *= persistence;
-				freq *= 2;
-			}
-			return warp_Math.crop(sum / persistence * 0.5f + 0.5f, 0, 1);
-		}
-
-		// Helper methods
-
-		private static float interpolatedNoise(float x, float y, int octave)
-		{
-			int intx = (int) x;
-			int inty = (int) y;
-			float fracx = x - (float) intx;
-			float fracy = y - (float) inty;
-
-			float i1 = warp_Math.interpolate(noise(intx, inty, octave),
-				noise(intx + 1, inty, octave), fracx);
-			float i2 = warp_Math.interpolate(noise(intx, inty + 1, octave),
-				noise(intx + 1, inty + 1, octave),
-				fracx);
-
-			return warp_Math.interpolate(i1, i2, fracy);
-		}
-
-		private static float smoothNoise(int x, int y, int o)
-		{
-			return (noise(x - 1, y - 1, o) + noise(x + 1, y - 1, o) +
-				noise(x - 1, y + 1, o) + noise(x + 1, y + 1, o)) / 16
-				+
-				(noise(x - 1, y, o) + noise(x + 1, y, o) + noise(x, y - 1, o) +
-				noise(x, y + 1, o)) / 8
-				+ noise(x, y, o) / 4;
-		}
-
-		private static float noise(int x, int y, int octave)
-		{
-			return noiseBuffer[octave & 3, (x + y * 57) & 8191];
-		}
-
-		private static float noise(int seed, int octave)
-		{
-			int id = octave & 3;
-			int n = (seed << 13) ^ seed;
-
-			if (id == 0)
-			{
-				return (float) (1f -
-					( (n * (n * n * 15731 + 789221) + 1376312589) &
-					0x7FFFFFFF) *
-					0.000000000931322574615478515625f);
-			}
-			if (id == 1)
-			{
-				return (float) (1f -
-					( (n * (n * n * 12497 + 604727) + 1345679039) &
-					0x7FFFFFFF) *
-					0.000000000931322574615478515625f);
-			}
-			if (id == 2)
-			{
-				return (float) (1f -
-					( (n * (n * n * 19087 + 659047) + 1345679627) &
-					0x7FFFFFFF) *
-					0.000000000931322574615478515625f);
-			}
-			return (float) (1f -
-				( (n * (n * n * 16267 + 694541) + 1345679501) &
-				0x7FFFFFFF) *
-				0.000000000931322574615478515625f);
-		}
-
-		private static void initNoiseBuffer()
-		{
-			if (noiseBufferInitialized)
-			{
-				return;
-			}
-
-			noiseBuffer = new float[4,8192];
-			for (int octave = 0; octave < 4; octave++)
-			{
-				for (int i = 0; i < 8192; i++)
-				{
-					noiseBuffer[octave,i] = noise(i, octave);
-				}
-			}
-			noiseBufferInitialized = true;
-		}
-
-		public static warp_Texture CHECKERBOARD(int w, int h, int cellbits, int oddColor, int evenColor)
-		{
-			warp_Texture t = new warp_Texture(w, h);
-
-			int pos = 0;
-			for (int y = 0; y < h; y++)
-			{
-				for (int x = 0; x < w; x++)
-				{
-					int c = ( ( (x >> cellbits) + (y >> cellbits)) & 1) == 0 ? evenColor : oddColor;
-					t.pixel[pos++] =  c;
-				}
-			}
-
-			return t;
-		}
-	}
+    /// <summary>
+    /// Summary description for warp_TextureFactory.
+    /// </summary>
+    public class warp_TextureFactory
+    {
+        public static float pi = 3.1415926535f;
+        public static float deg2rad = pi / 180;
+        private static float[,] noiseBuffer;
+        private static bool noiseBufferInitialized = false;
+        public static int ALPHA = unchecked((int)0xFF000000); // alpha mask
+
+        private warp_TextureFactory()
+        {
+        }
+
+        public static warp_Texture SKY(int w, int h, float density)
+        {
+            int[] colors = new int[2];
+            colors[0] = 0x003399;
+            colors[1] = 0xFFFFFF;
+            return PERLIN(w, h, 0.5f, 2.8f * density, 8, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+        }
+
+        public static warp_Texture MARBLE(int w, int h, float density)
+        {
+            int[] colors = new int[3];
+            colors[0] = 0x111111;
+            colors[1] = 0x696070;
+            colors[2] = 0xFFFFFF;
+            return WAVE(w, h, 0.5f, 0.64f * density, 6, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+        }
+
+        public static warp_Texture WOOD(int w, int h, float density)
+        {
+            int[] colors = new int[3];
+            colors[0] = 0x332211;
+            colors[1] = 0x523121;
+            colors[2] = 0x996633;
+
+            return GRAIN(w, h, 0.5f, 3f * density, 3, 8, 1024).colorize(warp_Color.makeGradient(colors, 1024));
+        }
+
+        public static warp_Texture PERLIN(int w, int h, float persistency,
+            float density, int samples, int scale)
+        {
+            initNoiseBuffer();
+            warp_Texture t = new(w, h);
+            int pos = 0;
+            float wavelength = (float)((w > h) ? w : h) / density;
+
+            for (int y = 0; y < h; y++)
+            {
+                for (int x = 0; x < w; x++)
+                {
+                    t.pixel[pos++] = (int)((float)scale *
+                        perlin2d(x, y, wavelength, persistency,
+                        samples));
+                }
+            }
+            return t;
+        }
+
+        public static warp_Texture WAVE(int w, int h, float persistency,
+            float density, int samples, int scale)
+        {
+            initNoiseBuffer();
+            warp_Texture t = new(w, h);
+            int pos = 0;
+            float wavelength = (float)((w > h) ? w : h) / density;
+
+            for (int y = 0; y < h; y++)
+            {
+                for (int x = 0; x < w; x++)
+                {
+                    t.pixel[pos++] = (int)(scale *
+                        (MathF.Sin(32f *
+                        perlin2d(x, y, wavelength,
+                        persistency, samples)) * 0.5f + 0.5f));
+                }
+            }
+            return t;
+        }
+
+        public static warp_Texture GRAIN(int w, int h, float persistency,
+            float density, int samples, int levels,
+            int scale)
+        // TIP: For wooden textures
+        {
+            initNoiseBuffer();
+            warp_Texture t = new(w, h);
+            int pos = 0;
+            float wavelength = (float)((w > h) ? w : h) / density;
+            float perlin;
+
+            for (int y = 0; y < h; y++)
+            {
+                for (int x = 0; x < w; x++)
+                {
+                    perlin = (float)levels *
+                        perlin2d(x, y, wavelength, persistency, samples);
+                    t.pixel[pos++] = (int)((float)scale *
+                        (perlin - (float)(int)perlin));
+                }
+            }
+            return t;
+        }
+
+        // Perlin noise functions
+
+        private static float perlin2d(float x, float y, float wavelength,
+            float persistence, int samples)
+        {
+            float sum = 0;
+            float freq = 1f / wavelength;
+            float amp = persistence;
+            float range = 0;
+
+            for (int i = 0; i < samples; i++)
+            {
+                sum += amp * interpolatedNoise(x * freq, y * freq, i);
+                range += amp;
+                amp *= persistence;
+                freq *= 2;
+            }
+            return warp_Math.crop(sum / persistence * 0.5f + 0.5f, 0, 1);
+        }
+
+        // Helper methods
+
+        private static float interpolatedNoise(float x, float y, int octave)
+        {
+            int intx = (int)x;
+            int inty = (int)y;
+            float fracx = x - (float)intx;
+            float fracy = y - (float)inty;
+
+            float i1 = warp_Math.interpolate(noise(intx, inty, octave),
+                noise(intx + 1, inty, octave), fracx);
+            float i2 = warp_Math.interpolate(noise(intx, inty + 1, octave),
+                noise(intx + 1, inty + 1, octave),
+                fracx);
+
+            return warp_Math.interpolate(i1, i2, fracy);
+        }
+
+        private static float smoothNoise(int x, int y, int o)
+        {
+            return (noise(x - 1, y - 1, o) + noise(x + 1, y - 1, o) +
+                noise(x - 1, y + 1, o) + noise(x + 1, y + 1, o)) / 16
+                +
+                (noise(x - 1, y, o) + noise(x + 1, y, o) + noise(x, y - 1, o) +
+                noise(x, y + 1, o)) / 8
+                + noise(x, y, o) / 4;
+        }
+
+        private static float noise(int x, int y, int octave)
+        {
+            return noiseBuffer[octave & 3, (x + y * 57) & 8191];
+        }
+
+        private static float noise(int seed, int octave)
+        {
+            int id = octave & 3;
+            int n = (seed << 13) ^ seed;
+
+            if (id == 0)
+            {
+                return (float)(1f -
+                    ((n * (n * n * 15731 + 789221) + 1376312589) &
+                    0x7FFFFFFF) *
+                    0.000000000931322574615478515625f);
+            }
+            if (id == 1)
+            {
+                return (float)(1f -
+                    ((n * (n * n * 12497 + 604727) + 1345679039) &
+                    0x7FFFFFFF) *
+                    0.000000000931322574615478515625f);
+            }
+            if (id == 2)
+            {
+                return (float)(1f -
+                    ((n * (n * n * 19087 + 659047) + 1345679627) &
+                    0x7FFFFFFF) *
+                    0.000000000931322574615478515625f);
+            }
+            return (float)(1f -
+                ((n * (n * n * 16267 + 694541) + 1345679501) &
+                0x7FFFFFFF) *
+                0.000000000931322574615478515625f);
+        }
+
+        private static void initNoiseBuffer()
+        {
+            if (noiseBufferInitialized)
+            {
+                return;
+            }
+
+            noiseBuffer = new float[4, 8192];
+            for (int octave = 0; octave < 4; octave++)
+            {
+                for (int i = 0; i < 8192; i++)
+                {
+                    noiseBuffer[octave, i] = noise(i, octave);
+                }
+            }
+            noiseBufferInitialized = true;
+        }
+
+        public static warp_Texture CHECKERBOARD(int w, int h, int cellbits, int oddColor, int evenColor)
+        {
+            warp_Texture t = new(w, h);
+
+            int pos = 0;
+            for (int y = 0; y < h; y++)
+            {
+                for (int x = 0; x < w; x++)
+                {
+                    int c = (((x >> cellbits) + (y >> cellbits)) & 1) == 0 ? evenColor : oddColor;
+                    t.pixel[pos++] = c;
+                }
+            }
+
+            return t;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_TextureProjector.cs b/trunk/managed/Warp3Dmod/warp_TextureProjector.cs
index 7deb390..a13a03e 100644
--- a/trunk/managed/Warp3Dmod/warp_TextureProjector.cs
+++ b/trunk/managed/Warp3Dmod/warp_TextureProjector.cs
@@ -2,40 +2,40 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_TextureProjector.
-	/// </summary>
-	public class warp_TextureProjector
-	{
-		public static void projectFrontal(warp_Object obj)
-		{
-			obj.rebuild();
-			warp_Vector min = obj.minimum();
-			warp_Vector max = obj.maximum();
-			float du = 1 / (max.x - min.x);
-			float dv = 1 / (max.y - min.y);
-
-			for (int i = 0; i < obj.vertices; i++)
-			{
-				obj.fastvertex[i].u = (obj.fastvertex[i].pos.x - min.x) * du;
-				obj.fastvertex[i].v = 1 - (obj.fastvertex[i].pos.y - min.y) * dv;
-			}
-		}
+    /// <summary>
+    /// Summary description for warp_TextureProjector.
+    /// </summary>
+    public class warp_TextureProjector
+    {
+        public static void projectFrontal(warp_Object obj)
+        {
+            obj.rebuild();
+            warp_Vector min = obj.fastMin;
+            warp_Vector max = obj.fastMax;
+            float du = 1 / (max.x - min.x);
+            float dv = 1 / (max.y - min.y);

-		public static void projectTop(warp_Object obj)
-		{
-			obj.rebuild();
-			warp_Vector min = obj.minimum();
-			warp_Vector max = obj.maximum();
-			float du = 1 / (max.x - min.x);
-			float dv = 1 / (max.z - min.z);
-			for (int i = 0; i < obj.vertices; i++)
-			{
-				obj.fastvertex[i].u = (obj.fastvertex[i].pos.x - min.x) * du;
-				obj.fastvertex[i].v = (obj.fastvertex[i].pos.z - min.z) * dv;
-			}
-		}
+            for (int i = 0; i < obj.vertexData.Count; i++)
+            {
+                obj.vertexData[i].u = (obj.vertexData[i].pos.x - min.x) * du;
+                obj.vertexData[i].v = 1 - (obj.vertexData[i].pos.y - min.y) * dv;
+            }
+        }

+        public static void projectTop(warp_Object obj)
+        {
+            obj.rebuild();
+            warp_Vector min = obj.fastMin;
+            warp_Vector max = obj.fastMax;
+            float du = 1 / (max.x - min.x);
+            float dv = 1 / (max.z - min.z);
+            for (int i = 0; i < obj.vertexData.Count; i++)
+            {
+                obj.vertexData[i].u = (obj.vertexData[i].pos.x - min.x) * du;
+                obj.vertexData[i].v = (obj.vertexData[i].pos.z - min.z) * dv;
+            }
+        }
+        /*
 		public static void projectCylindric(warp_Object obj)
 		{
 			obj.rebuild();
@@ -48,6 +48,22 @@ namespace Warp3D
 				obj.fastvertex[i].u = obj.fastvertex[i].pos.theta / (2 * 3.14159265f);
 				obj.fastvertex[i].v = (obj.fastvertex[i].pos.z - min.z) * dz;
 			}
-		}
-	}
+		}
+		*/
+
+        public static void projectCylindric(warp_Object obj)
+        {
+            obj.rebuild();
+            const float inv2p = 0.5f / MathF.PI;
+            warp_Vector min = obj.fastMin;
+            warp_Vector max = obj.fastMax;
+            float dz = 1 / (max.z - min.z);
+            for (int i = 0; i < obj.vertexData.Count; i++)
+            {
+                float theta = MathF.Atan2(obj.vertexData[i].pos.x, obj.vertexData[i].pos.y);
+                obj.vertexData[i].u = theta * inv2p;
+                obj.vertexData[i].v = (obj.vertexData[i].pos.z - min.z) * dz;
+            }
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_TextureSettings.cs b/trunk/managed/Warp3Dmod/warp_TextureSettings.cs
index 5df54c3..e95a688 100644
--- a/trunk/managed/Warp3Dmod/warp_TextureSettings.cs
+++ b/trunk/managed/Warp3Dmod/warp_TextureSettings.cs
@@ -2,32 +2,32 @@ using System;

 namespace Warp3D
 {
-	/// <summary>
-	/// Summary description for warp_TextureSettings.
-	/// </summary>
-	///
-	public class warp_TextureSettings
-	{
-		public warp_Texture texture;
-		public int width;
-		public int height;
-		public int type;
-		public float persistency;
-		public float density;
-		public int samples;
-		public int numColors;
-		public int[] colors;
+    /// <summary>
+    /// Summary description for warp_TextureSettings.
+    /// </summary>
+    ///
+    public class warp_TextureSettings
+    {
+        public warp_Texture texture;
+        public int width;
+        public int height;
+        public int type;
+        public float persistency;
+        public float density;
+        public int samples;
+        public int numColors;
+        public int[] colors;

-		public warp_TextureSettings(warp_Texture tex, int w, int h, int t, float p, float d, int s, int[] c)
-		{
-			texture=tex;
-			width=w;
-			height=h;
-			type=t;
-			persistency=p;
-			density=d;
-			samples=s;
-			colors=c;
-		}
-	}
+        public warp_TextureSettings(warp_Texture tex, int w, int h, int t, float p, float d, int s, int[] c)
+        {
+            texture = tex;
+            width = w;
+            height = h;
+            type = t;
+            persistency = p;
+            density = d;
+            samples = s;
+            colors = c;
+        }
+    }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Triangle.cs b/trunk/managed/Warp3Dmod/warp_Triangle.cs
index e628661..b252c47 100644
--- a/trunk/managed/Warp3Dmod/warp_Triangle.cs
+++ b/trunk/managed/Warp3Dmod/warp_Triangle.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
@@ -7,17 +8,16 @@ namespace Warp3D
     /// </summary>
     public class warp_Triangle
     {
+        public const float oneThird = 1.0f / 3f;
         public warp_Object parent;  // the object which obtains this triangle
         public warp_Vertex p1;  // first  vertex
         public warp_Vertex p2;  // second vertex
         public warp_Vertex p3;  // third  vertex

         public warp_Vector n;  // Normal vector of flat triangle
-        public warp_Vector rawNorm;  // Normal h vector of flat triangle
         public warp_Vector n2; // Projected Normal vector

-        private warp_Vector triangleCenter = new warp_Vector();
-        public float distZ = 0;
+        public int minDistZ = 0;

         public int id = 0;

@@ -39,36 +39,41 @@ namespace Warp3D
         public void project(warp_Matrix normalProjection)
         {
             n2 = n.transform(normalProjection);
-            distZ = getDistZ();
+            minDistZ = getMinDistZ();
         }

         public void regenerateNormal()
         {
-            rawNorm = warp_Vector.vectorProduct(p1.pos, p2.pos, p3.pos);
-            n = rawNorm.normalize();
+            warp_Vector tmpa = warp_Vector.sub(ref p2.pos, ref p1.pos);
+            warp_Vector tmpb = warp_Vector.sub(ref p3.pos, ref p1.pos);
+            n = warp_Vector.vectorProduct(ref tmpa, ref tmpb);
+            n.normalize();
         }

         public warp_Vertex getMedium()
         {
-            float cx = (p1.pos.x + p2.pos.x + p3.pos.x) / 3;
-            float cy = (p1.pos.y + p2.pos.y + p3.pos.y) / 3;
-            float cz = (p1.pos.z + p2.pos.z + p3.pos.z) / 3;
-            float cu = (p1.u + p2.u + p3.u) / 3;
-            float cv = (p1.v + p2.v + p3.v) / 3;
+            float cx = (p1.pos.x + p2.pos.x + p3.pos.x) * oneThird;
+            float cy = (p1.pos.y + p2.pos.y + p3.pos.y) * oneThird;
+            float cz = (p1.pos.z + p2.pos.z + p3.pos.z) * oneThird;
+            float cu = (p1.u + p2.u + p3.u) * oneThird;
+            float cv = (p1.v + p2.v + p3.v) * oneThird;
             return new warp_Vertex(cx, cy, cz, cu, cv);
         }

         public warp_Vector getCenter()
         {
-            float cx = (p1.pos.x + p2.pos.x + p3.pos.x) / 3;
-            float cy = (p1.pos.y + p2.pos.y + p3.pos.y) / 3;
-            float cz = (p1.pos.z + p2.pos.z + p3.pos.z) / 3;
+            float cx = (p1.pos.x + p2.pos.x + p3.pos.x) * oneThird;
+            float cy = (p1.pos.y + p2.pos.y + p3.pos.y) * oneThird;
+            float cz = (p1.pos.z + p2.pos.z + p3.pos.z) * oneThird;
             return new warp_Vector(cx, cy, cz);
         }

-        public float getDistZ()
+        public int getMinDistZ()
         {
-            return p1.z + p2.z + p3.z;
+            int m = p1.z;
+            if (m > p2.z)
+                m = p2.z;
+            return m > p3.z ? p3.z : m;
         }

         public bool degenerated()
diff --git a/trunk/managed/Warp3Dmod/warp_Vector.cs b/trunk/managed/Warp3Dmod/warp_Vector.cs
index 7898b3c..d73155e 100644
--- a/trunk/managed/Warp3Dmod/warp_Vector.cs
+++ b/trunk/managed/Warp3Dmod/warp_Vector.cs
@@ -1,14 +1,13 @@
 using System;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
-    public class warp_Vector
+    public struct warp_Vector
     {
-        public float x = 0;      //Cartesian (default)
-        public float y = 0;      //Cartesian (default)
-        public float z = 0;      //Cartesian (default),Cylindric
-        public float r = 0;      //Cylindric
-        public float theta = 0;  //Cylindric
+        public float x = 0;
+        public float y = 0;
+        public float z = 0;

         public warp_Vector()
         {
@@ -20,20 +19,31 @@ namespace Warp3D
             y = ypos;
             z = zpos;
         }
-        public warp_Vector normalize()
+
+        public static warp_Vector FromXYZ(float xpos, float zpos, float ypos)
+        {
+            return new warp_Vector
+            {
+                x = xpos,
+                y = ypos,
+                z = zpos
+            };
+        }
+        public void normalize()
         // Normalizes the vector
         {
-            float dist = length();
-            if(dist == 0)
-                return this;
-            float invdist = 1 / dist;
-            x *= invdist;
-            y *= invdist;
-            z *= invdist;
-            return this;
+            float dist = lengthSquare();
+            if (dist > 1e-6f)
+            {
+
+                float invdist = 1f / MathF.Sqrt(dist);
+                x *= invdist;
+                y *= invdist;
+                z *= invdist;
+            }
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vector reverse()
         // Reverses the vector
         {
@@ -43,21 +53,33 @@ namespace Warp3D
             return this;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public float length()
-        // Lenght of this vector
         {
-            return (float)Math.Sqrt(x * x + y * y + z * z);
+            return MathF.Sqrt(x * x + y * y + z * z);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public float lengthSquare()
+        {
+            return (x * x + y * y + z * z);
         }

         public warp_Vector transform(warp_Matrix m)
         // Modifies the vector by matrix m
         {
-            float newx = x * m.m00 + y * m.m01 + z * m.m02 + m.m03;
-            float newy = x * m.m10 + y * m.m11 + z * m.m12 + m.m13;
-            float newz = x * m.m20 + y * m.m21 + z * m.m22 + m.m23;
+            return new warp_Vector(
+                x * m.m00 + y * m.m01 + z * m.m02 + m.m03,
+                x * m.m10 + y * m.m11 + z * m.m12 + m.m13,
+                x * m.m20 + y * m.m21 + z * m.m22 + m.m23
+                );
+        }

-            return new warp_Vector(newx, newy, newz);
+        public void transformToXY(warp_Matrix m, out float nx, out float ny)
+        // Modifies the vector by matrix m
+        {
+                nx = x * m.m00 + y * m.m01 + z * m.m02 + m.m03;
+                ny = x * m.m10 + y * m.m11 + z * m.m12 + m.m13;
         }

         public warp_Vector pointtransform(warp_Matrix m)
@@ -66,8 +88,8 @@ namespace Warp3D
             float newx = x * m.m00 + y * m.m01 + z * m.m02 + m.m03;
             float newy = x * m.m10 + y * m.m11 + z * m.m12 + m.m13;
             float newz = x * m.m20 + y * m.m21 + z * m.m22 + m.m23;
-            float w =    x * m.m30 + y * m.m31 + z * m.m32 + m.m33;
-            if(w != 1.0f && w != 0f)
+            float w = x * m.m30 + y * m.m31 + z * m.m32 + m.m33;
+            if (w != 1.0f && w != 0f)
             {
                 w = 1.0f / w;
                 newx *= w;
@@ -78,109 +100,58 @@ namespace Warp3D
             return new warp_Vector(newx, newy, newz);
         }

-        public void buildCylindric()
-        // Builds the cylindric coordinates out of the given cartesian coordinates
-        {
-            r = (float)Math.Sqrt(x * x + y * y);
-            theta = (float)Math.Atan2(x, y);
-        }
-
-        public void buildCartesian()
-        // Builds the cartesian coordinates out of the given cylindric coordinates
-        {
-            x = r * warp_Math.cos(theta);
-            y = r * warp_Math.sin(theta);
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector getNormal(warp_Vector a, warp_Vector b)
-        // returns the normal vector of the plane defined by the two vectors
-        {
-            return vectorProduct(a, b).normalize();
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector getNormal(warp_Vector a, warp_Vector b, warp_Vector c)
-        // returns the normal vector of the plane defined by the two vectors
-        {
-            return vectorProduct(a, b, c).normalize();
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector vectorProduct(warp_Vector a, warp_Vector b)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static warp_Vector vectorProduct(ref warp_Vector a, ref warp_Vector b)
         // returns a x b
         {
             return new warp_Vector(a.y * b.z - b.y * a.z, a.z * b.x - b.z * a.x, a.x * b.y - b.x * a.y);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector vectorProduct(warp_Vector a, warp_Vector b, warp_Vector c)
-        // returns (b-a) x (c-a)
-        {
-            return vectorProduct(sub(b, a), sub(c, a));
-        }
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static float vectorsCos(warp_Vector a, warp_Vector b)
-        // returns the angle between 2 vectors
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float vectorsCos(ref warp_Vector a, ref warp_Vector b)
         {
             a.normalize();
             b.normalize();
             return (a.x * b.x + a.y * b.y + a.z * b.z);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static float Dot(warp_Vector a, warp_Vector b)
-        // returns the angle between 2 vectors
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static float Dot(ref warp_Vector a, ref warp_Vector b)
         {
             return (a.x * b.x + a.y * b.y + a.z * b.z);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector add(warp_Vector a, warp_Vector b)
-        // adds 2 vectors
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static warp_Vector add(ref warp_Vector a, ref warp_Vector b)
         {
             return new warp_Vector(a.x + b.x, a.y + b.y, a.z + b.z);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector sub(warp_Vector a, warp_Vector b)
-        // substracts 2 vectors
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static warp_Vector sub(ref warp_Vector a, ref warp_Vector b)
         {
             return new warp_Vector(a.x - b.x, a.y - b.y, a.z - b.z);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
-        public static warp_Vector scale(float f, warp_Vector a)
-        // substracts 2 vectors
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static warp_Vector scale(float f, ref warp_Vector a)
         {
             return new warp_Vector(f * a.x, f * a.y, f * a.z);
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static float len(warp_Vector a)
         // length of vector
         {
-            return (float)Math.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
+            return MathF.Sqrt(a.x * a.x + a.y * a.y + a.z * a.z);
         }

-        /*
-		public static warp_Vector random(float fact)
-			// returns a random vector
-		{
-			return new warp_Vector(fact*warp_Math.random(),fact*warp_Math.random(),fact*warp_Math.random());
-		}
-
-		public String toString()
-		{
-			return new String ("<vector x="+x+" y="+y+" z="+z+">\r\n");
-		}
-*/
-
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vector getClone()
         {
             return new warp_Vector(x, y, z);
         }
+
+        public static warp_Vector Zero = new();
     }
 }
diff --git a/trunk/managed/Warp3Dmod/warp_Vertex.cs b/trunk/managed/Warp3Dmod/warp_Vertex.cs
index 91c55d8..193ef01 100644
--- a/trunk/managed/Warp3Dmod/warp_Vertex.cs
+++ b/trunk/managed/Warp3Dmod/warp_Vertex.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Runtime.CompilerServices;

 namespace Warp3D
 {
@@ -9,70 +10,64 @@ namespace Warp3D
     /// </summary>
     public class warp_Vertex
     {
-        public warp_Object parent;
+        public warp_Object parent = null;

-        public warp_Vector pos = new warp_Vector();   //(x,y,z) Coordinate of vertex
-        public warp_Vector n = new warp_Vector();   //Normal Vector at vertex
-        public float u = 0; // Texture x-coordinate (relative)
-        public float v = 0; // Texture y-coordinate (relative)
-
-
-        public warp_Vector pos2;  //Transformed vertex coordinate
-        public warp_Vector n2;  //Transformed normal vector (camera space)
-        public int x;  //Projected x coordinate
-        public int y;  //Projected y coordinate
-        public int z;  //Projected z coordinate for z-Buffer
+        public warp_Vector pos;   //(x,y,z) Coordinate of vertex
+        public warp_Vector n;   //Normal at vertex
+        public float u; // Texture x-coordinate (relative)
+        public float v; // Texture y-coordinate (relative)
+        public int id; // Vertex index

-        public float tx = 0; // Texture x-coordinate (relative)
-        public float ty = 0; // Texture y-coordinate (relative)
+        // projected data cache
+        public int x;  //x coordinate
+        public int y;  //y coordinate
+        public int z;  //z coordinate for z-Buffer

-        public int nx = 0; // Normal x-coordinate for envmapping
-        public int ny = 0; // Normal y-coordinate for envmapping
+        public int nx; // Normal x-coordinate for envmapping
+        public int ny; // Normal y-coordinate for envmapping

-        public float invZ = 1.0f;
+        public float invZ;

-        public bool visible = true;  //visibility tag for clipping
-        public int clipcode = 0;
-        public int id; // Vertex index
+        public int clipcode;

-        //private Vector neighbor=new Vector(); //Neighbor triangles of vertex
-        private List<warp_Triangle> neighbor = new List<warp_Triangle>();
+        private readonly List<warp_Triangle> neighbor = new();

         public warp_Vertex()
         {
-            pos = new warp_Vector(0f, 0f, 0f);
+            pos = new(0f, 0f, 0f);
         }

         public warp_Vertex(float xpos, float ypos, float zpos)
         {
-            pos = new warp_Vector(xpos, ypos, zpos);
+            pos = new(xpos, ypos, zpos);
         }

         public warp_Vertex(float xpos, float ypos, float zpos, float u, float v)
         {
-            pos = new warp_Vector(xpos, ypos, zpos);
+            pos = new(xpos, ypos, zpos);
             this.u = u;
             this.v = v;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vertex(warp_Vector ppos)
         {
-            pos = ppos.getClone();
+            pos = ppos;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vertex(warp_Vector ppos, float u, float v)
         {
-            pos = ppos.getClone();
+            pos = ppos;
             this.u = u;
             this.v = v;
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vertex(warp_Vector ppos, warp_Vector norm, float u, float v)
         {
-            pos = ppos.getClone();
-            n = norm.getClone();
+            pos = ppos;
+            n = norm;
             this.u = u;
             this.v = v;
         }
@@ -80,66 +75,62 @@ namespace Warp3D
         public void project(warp_Matrix vertexProjection, warp_Matrix normalProjection, warp_Camera camera)
         // Projects this vertex into camera space
         {
-            pos2 = pos.transform(vertexProjection);
-            n2 = n.transform(normalProjection);
-
-            if(pos2.z < 0.001f && pos2.z > -0.0001f)
+            warp_Vector pos2 = pos.transform(vertexProjection);
+            if (pos2.z < 0.001f && pos2.z > -0.0001f)
                 pos2.z = 0.001f;

-            if(camera.isOrthographic)
+            if (camera.isOrthographic)
             {
                 x = (int)pos2.x;
                 y = (int)pos2.y;
                 invZ = -1.0f;
-                tx = -u;
-                ty = -v;
             }
             else
             {
                 invZ = 1.0f / pos2.z;
                 x = (int)(pos2.x * invZ + camera.halfscreenwidth);
                 y = (int)(pos2.y * invZ + camera.halfscreenheight);
-                invZ = - invZ;
-                tx = u * invZ;
-                ty = v * invZ;
+                invZ = -invZ;
             }
-
             z = (int)(65536f * pos2.z);
-            nx = ((int)(n2.x * 127 + 127)) << 16;
-            ny = ((int)(n2.y * 127 + 127)) << 16;
+
+            n.transformToXY(normalProjection, out float nxf, out float nyf);
+            nx = ((int)(nxf * 127 + 127)) << 16;
+            ny = ((int)(nyf * 127 + 127)) << 16;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void setUV(float u, float v)
         {
             this.u = u;
             this.v = v;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void clipFrustrum(int w, int h)
         {
             // View plane clipping
             clipcode = 0;
-            if(x < 0)
+            if (x < 0)
                 clipcode |= 1;
-            else if(x >= w)
+            else if (x >= w)
                 clipcode |= 2;
-            if(y < 0)
+            if (y < 0)
                 clipcode |= 4;
-            else if(y >= h)
+            else if (y >= h)
                 clipcode |= 8;
-            if(pos2.z < 0)
+            if (z < 0)
                 clipcode |= 16;
-            visible = (clipcode == 0);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void registerNeighbor(warp_Triangle triangle)
         {
-            if(!neighbor.Contains(triangle))
+            if (!neighbor.Contains(triangle))
                 neighbor.Add(triangle);
         }

+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void resetNeighbors()
         {
             neighbor.Clear();
@@ -150,16 +141,15 @@ namespace Warp3D
             float nx = 0;
             float ny = 0;
             float nz = 0;
-            for(int i = 0; i < neighbor.Count; ++i)
+            for (int i = 0; i < neighbor.Count; ++i)
             {
-                warp_Triangle tri = neighbor[i];
-                warp_Vector wn = tri.rawNorm;
-                nx += wn.x;
-                ny += wn.y;
-                nz += wn.z;
+                nx += neighbor[i].n.x;
+                ny += neighbor[i].n.y;
+                nz += neighbor[i].n.z;
             }

-            n = new warp_Vector(nx, ny, nz).normalize();
+            n = new warp_Vector(nx, ny, nz);
+            n.normalize();
         }

         /*
@@ -183,42 +173,44 @@ namespace Warp3D
                     n=new warp_Vector(nx,ny,nz).normalize();
                 }
         */
-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void scaleTextureCoordinates(float fx, float fy)
         {
             u *= fx;
             v *= fy;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void moveTextureCoordinates(float fx, float fy)
         {
             u += fx;
             v += fy;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public warp_Vertex getClone()
         {
-            warp_Vertex newVertex = new warp_Vertex();
-            newVertex.pos = pos.getClone();
-            newVertex.n = n.getClone();
-            newVertex.u = u;
-            newVertex.v = v;
+            warp_Vertex newVertex = new()
+            {
+                pos = pos,
+                n = n,
+                u = u,
+                v = v
+            };

             return newVertex;
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool equals(warp_Vertex v)
         {
             return ((pos.x == v.pos.x) && (pos.y == v.pos.y) && (pos.z == v.pos.z));
         }

-        [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public bool equals(warp_Vertex v, float tolerance)
         {
-            return Math.Abs(warp_Vector.sub(pos, v.pos).length()) < tolerance;
+            return warp_Vector.sub(ref pos, ref v.pos).lengthSquare() < tolerance * tolerance;
         }
     }
 }
diff --git a/trunk/managed/XmlRpc/AssemblyInfo.cs b/trunk/managed/XmlRpc/AssemblyInfo.cs
index 6cd8b21..f05c9ab 100644
--- a/trunk/managed/XmlRpc/AssemblyInfo.cs
+++ b/trunk/managed/XmlRpc/AssemblyInfo.cs
@@ -1,7 +1,7 @@
 using System.Runtime.InteropServices;
 using System.Reflection;

-[assembly: AssemblyVersion("1.10.0.2")]
+[assembly: AssemblyVersion("1.10.0.4")]
 [assembly: AssemblyTitle("XmlRpc Opensim")]
 [assembly: AssemblyCompany("Ronin Consulting Inc, OpenSimulator")]
 [assembly: AssemblyDescription("XML RPC client and server")]
diff --git a/trunk/managed/XmlRpc/Logger.cs b/trunk/managed/XmlRpc/Logger.cs
index beacd6b..bdd2834 100644
--- a/trunk/managed/XmlRpc/Logger.cs
+++ b/trunk/managed/XmlRpc/Logger.cs
@@ -40,8 +40,7 @@ namespace Nwc.XmlRpc
         ///<param name="level">The <c>LogLevel</c> of your message.</param>
         static public void WriteEntry(String message,LogLevel level)
         {
-            if(Delegate != null)
-                Delegate(message,level);
+            Delegate?.Invoke(message, level);
         }
     }
 }
diff --git a/trunk/managed/XmlRpc/SimpleHttpRequest.cs b/trunk/managed/XmlRpc/SimpleHttpRequest.cs
index b4d39da..e40d7ef 100644
--- a/trunk/managed/XmlRpc/SimpleHttpRequest.cs
+++ b/trunk/managed/XmlRpc/SimpleHttpRequest.cs
@@ -16,9 +16,9 @@ namespace Nwc.XmlRpc
         private String _filePathFile = null;
         private String _filePathDir = null;
         private String __filePath;
-        private TcpClient _client;
-        private StreamReader _input;
-        private StreamWriter _output;
+        private readonly TcpClient _client;
+        private readonly StreamReader _input;
+        private readonly StreamWriter _output;
         private Hashtable _headers;

         /// <summary>A constructor which accepts the TcpClient.</summary>
@@ -107,16 +107,16 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_filePathFile != null)
+                if(_filePathFile is not null)
                     return _filePathFile;

-                int i = FilePath.LastIndexOf("/");
+                int i = FilePath.LastIndexOf('/');

                 if(i == -1)
                     return "";

                 i++;
-                _filePathFile = FilePath.Substring(i,FilePath.Length - i);
+                _filePathFile = FilePath[i..];
                 return _filePathFile;
             }
         }
@@ -126,16 +126,15 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_filePathDir != null)
+                if(_filePathDir is not null)
                     return _filePathDir;

-                int i = FilePath.LastIndexOf("/");
-
+                int i = FilePath.LastIndexOf('/');
                 if(i == -1)
                     return "";

                 i++;
-                _filePathDir = FilePath.Substring(0,i);
+                _filePathDir = FilePath[..i];
                 return _filePathDir;
             }
         }
@@ -143,28 +142,38 @@ namespace Nwc.XmlRpc
         private void GetRequestMethod()
         {
             string req = _input.ReadLine();
-            if(req == null)
+            if(req is null)
                 throw new ApplicationException("Void request.");
+            var sreq = req.AsSpan();

-            if(0 == String.Compare("GET ",req.Substring(0,4),true))
+            if(sreq.StartsWith("GET "))
+            {
                 _httpMethod = "GET";
-            else if(0 == String.Compare("POST ",req.Substring(0,5),true))
+                sreq = sreq[5..];
+            }
+            else if(sreq.StartsWith("POST "))
+            {
                 _httpMethod = "POST";
+                sreq = sreq[6..];
+            }
             else
                 throw new InvalidOperationException("Unrecognized method in query: " + req);

-            req = req.TrimEnd();
-            int idx = req.IndexOf(' ') + 1;
-            if(idx >= req.Length)
+            sreq = sreq.TrimEnd();
+            if(sreq.Length == 0)
                 throw new ApplicationException("What do you want?");

-            string page_protocol = req.Substring(idx);
-            int idx2 = page_protocol.IndexOf(' ');
+            int idx2 = sreq.IndexOf(' ');
             if(idx2 == -1)
-                idx2 = page_protocol.Length;
-
-            _filePath = page_protocol.Substring(0,idx2).Trim();
-            _protocol = page_protocol.Substring(idx2).Trim();
+            {
+                _filePath = sreq.ToString();
+                _protocol = string.Empty;
+            }
+            else
+            {
+                _filePath = sreq[..idx2].Trim().ToString();
+                _protocol = sreq[idx2..].Trim().ToString();
+            }
         }

         private void GetRequestHeaders()
@@ -188,8 +197,8 @@ namespace Nwc.XmlRpc
                     continue;
                 }

-                String key = line.Substring(0,idx);
-                String value = line.Substring(idx + 1);
+                String key = line[..idx];
+                String value = line[(idx + 1)..];

                 try
                 {
diff --git a/trunk/managed/XmlRpc/XmlRpcBoxcarRequest.cs b/trunk/managed/XmlRpc/XmlRpcBoxcarRequest.cs
index 5083359..0d3b930 100644
--- a/trunk/managed/XmlRpc/XmlRpcBoxcarRequest.cs
+++ b/trunk/managed/XmlRpc/XmlRpcBoxcarRequest.cs
@@ -43,9 +43,11 @@ namespace Nwc.XmlRpc
                 ArrayList reqArray = new ArrayList();
                 foreach(XmlRpcRequest request in Requests)
                 {
-                    Hashtable requestEntry = new Hashtable();
-                    requestEntry.Add(XmlRpcXmlTokens.METHOD_NAME,request.MethodName);
-                    requestEntry.Add(XmlRpcXmlTokens.PARAMS,request.Params);
+                    Hashtable requestEntry = new Hashtable
+                    {
+                        { XmlRpcXmlTokens.METHOD_NAME, request.MethodName },
+                        { XmlRpcXmlTokens.PARAMS, request.Params }
+                    };
                     reqArray.Add(requestEntry);
                 }
                 _params.Add(reqArray);
diff --git a/trunk/managed/XmlRpc/XmlRpcDeserializer.cs b/trunk/managed/XmlRpc/XmlRpcDeserializer.cs
index 44d571e..414dcc7 100644
--- a/trunk/managed/XmlRpc/XmlRpcDeserializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcDeserializer.cs
@@ -21,7 +21,7 @@ namespace Nwc.XmlRpc
     /// but is designed to be subclassed.</remarks>
     public class XmlRpcDeserializer:XmlRpcXmlTokens
     {
-        private static DateTimeFormatInfo _dateFormat = new DateTimeFormatInfo();
+        private readonly static DateTimeFormatInfo _dateFormat = new();

         private object _container;
         private Stack _containerStack;
@@ -58,7 +58,7 @@ namespace Nwc.XmlRpc
             switch(reader.NodeType)
             {
                 case XmlNodeType.Element:
-                    if(Logger.Delegate != null)
+                    if(Logger.Delegate is not null)
                         Logger.WriteEntry("START " + reader.Name,LogLevel.Information);
                     switch(reader.Name)
                     {
@@ -77,13 +77,13 @@ namespace Nwc.XmlRpc
                     }
                     break;
                 case XmlNodeType.EndElement:
-                    if(Logger.Delegate != null)
+                    if(Logger.Delegate is not null)
                         Logger.WriteEntry("END " + reader.Name,LogLevel.Information);
                     switch(reader.Name)
                     {
                         case BASE64:
                             if(string.IsNullOrEmpty(_text))
-                                _value = new byte[0];
+                                _value = Array.Empty<byte>();
                             else
                                 _value = Convert.FromBase64String(_text);
                             break;
@@ -105,25 +105,19 @@ namespace Nwc.XmlRpc
                             _value = Int32.Parse(_text);
                             break;
                         case DATETIME:
-#if __MONO__
-		                    _value = DateParse(_text);
-#else
                             _value = DateTime.ParseExact(_text,"F",_dateFormat);
-#endif
                             break;
                         case NAME:
                             _name = _text;
                             break;
                         case VALUE:
-                            if(_value == null)
-                                _value = _text; // some kits don't use <string> tag, they just do <value>
-
-                            if((_container != null) && (_container is IList)) // in an array?  If so add value to it.
-                                ((IList)_container).Add(_value);
+                            _value ??= _text; // some kits don't use <string> tag, they just do <value>
+                            if(_container is IList cnt) // in an array?  If so add value to it.
+                                cnt.Add(_value);
                             break;
                         case MEMBER:
-                            if((_container != null) && (_container is IDictionary)) // in an struct?  If so add value to it.
-                                ((IDictionary)_container).Add(_name,_value);
+                            if(_container is IDictionary icnt) // in an struct?  If so add value to it.
+                                icnt.Add(_name,_value);
                             break;
                         case ARRAY:
                         case STRUCT:
@@ -133,7 +127,7 @@ namespace Nwc.XmlRpc
                     }
                     break;
                 case XmlNodeType.Text:
-                    if(Logger.Delegate != null)
+                    if(Logger.Delegate is not null)
                         Logger.WriteEntry("Text " + reader.Value,LogLevel.Information);
                     _text = reader.Value;
                     break;
@@ -179,20 +173,6 @@ namespace Nwc.XmlRpc
             _container = null;
             _containerStack = new Stack();
         }
-
-#if __MONO__
-    private DateTime DateParse(String str)
-      {
-	int year = Int32.Parse(str.Substring(0,4));
-	int month = Int32.Parse(str.Substring(4,2));
-	int day = Int32.Parse(str.Substring(6,2));
-	int hour = Int32.Parse(str.Substring(9,2));
-	int min = Int32.Parse(str.Substring(12,2));
-	int sec = Int32.Parse(str.Substring(15,2));
-	return new DateTime(year,month,day,hour,min,sec);
-      }
-#endif
-
     }
 }

diff --git a/trunk/managed/XmlRpc/XmlRpcException.cs b/trunk/managed/XmlRpc/XmlRpcException.cs
index 4185f11..38e1163 100644
--- a/trunk/managed/XmlRpc/XmlRpcException.cs
+++ b/trunk/managed/XmlRpc/XmlRpcException.cs
@@ -7,7 +7,7 @@ namespace Nwc.XmlRpc
     /// include a message so this adds the code needed by XML-RPC.</remarks>
     public class XmlRpcException:Exception
     {
-        private int _code;
+        private readonly int _code;

         /// <summary>Instantiate an <c>XmlRpcException</c> with a code and message.</summary>
         /// <param name="code"><c>Int</c> faultCode associated with this exception.</param>
@@ -38,7 +38,7 @@ namespace Nwc.XmlRpc
         /// <summary>Format the message to include the code.</summary>
         override public String ToString()
         {
-            return "Code: " + FaultCode + " Message: " + base.ToString();
+            return $"Code: {FaultCode} Message: {base.ToString()}";
         }
     }
 }
diff --git a/trunk/managed/XmlRpc/XmlRpcExposedAttribute.cs b/trunk/managed/XmlRpc/XmlRpcExposedAttribute.cs
index 2a33092..6238a05 100644
--- a/trunk/managed/XmlRpc/XmlRpcExposedAttribute.cs
+++ b/trunk/managed/XmlRpc/XmlRpcExposedAttribute.cs
@@ -35,7 +35,7 @@ namespace Nwc.XmlRpc
             Type type = obj.GetType();
             MethodInfo method = type.GetMethod(methodName);

-            if(method == null)
+            if(method is null)
                 throw new MissingMethodException("Method " + methodName + " not found.");

             if(!IsExposed(type))
diff --git a/trunk/managed/XmlRpc/XmlRpcRequest.cs b/trunk/managed/XmlRpc/XmlRpcRequest.cs
index 40ce8b4..1b877f4 100644
--- a/trunk/managed/XmlRpc/XmlRpcRequest.cs
+++ b/trunk/managed/XmlRpc/XmlRpcRequest.cs
@@ -5,6 +5,10 @@ using System.Xml;
 using System.Net;
 using System.Net.Security;
 using System.Text;
+using System.Net.Http;
+using System.Threading;
+using System.Linq;
+using System.Threading.Tasks;

 namespace Nwc.XmlRpc
 {
@@ -12,9 +16,9 @@ namespace Nwc.XmlRpc
     public class XmlRpcRequest
     {
         private string m_methodName = null;
-        private Encoding m_encoding = new UTF8Encoding();
-        private XmlRpcRequestSerializer _serializer = new XmlRpcRequestSerializer();
-        private XmlRpcResponseDeserializer _deserializer = new XmlRpcResponseDeserializer();
+        private readonly Encoding m_encoding = new UTF8Encoding();
+        private readonly XmlRpcRequestSerializer _serializer = new();
+        private readonly XmlRpcResponseDeserializer _deserializer = new();

         /// <summary><c>ArrayList</c> containing the parameters.</summary>
         protected IList _params = null;
@@ -67,12 +71,12 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                int index = MethodName.IndexOf(".");
+                int index = MethodName.IndexOf('.');

                 if (index == -1)
                     return MethodName;

-                return MethodName.Substring(0, index);
+                return MethodName[..index];
             }
         }

@@ -81,12 +85,12 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                int index = MethodName.IndexOf(".");
+                int index = MethodName.IndexOf('.');

                 if (index == -1)
                     return MethodName;

-                return MethodName.Substring(index + 1, MethodName.Length - index - 1);
+                return MethodName.Substring(index + 1);
             }
         }

@@ -94,6 +98,16 @@ namespace Nwc.XmlRpc
         /// <param name="url"><c>String</c> The url of the XML-RPC server.</param>
         /// <returns><c>Object</c> The value returned from the method invocation on the server.</returns>
         /// <exception cref="XmlRpcException">If an exception generated on the server side.</exception>
+        public object Invoke(string url, HttpClient client)
+        {
+            XmlRpcResponse res = Send(url, client);
+
+            if (res.IsFault)
+                throw new XmlRpcException(res.FaultCode, res.FaultString);
+
+            return res.Value;
+        }
+
         public object Invoke(string url, RemoteCertificateValidationCallback certCallBack = null)
         {
             XmlRpcResponse res = Send(url, 100000, certCallBack);
@@ -121,7 +135,7 @@ namespace Nwc.XmlRpc
                 request.ServerCertificateValidationCallback = certCallBack;

             using (Stream stream = request.GetRequestStream())
-            using (XmlTextWriter xml = new XmlTextWriter(stream, m_encoding))
+            using (XmlTextWriter xml = new(stream, m_encoding))
             {
                 _serializer.Serialize(xml, this);
                 xml.Flush();
@@ -129,11 +143,67 @@ namespace Nwc.XmlRpc

             XmlRpcResponse resp;
             using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
-            using (StreamReader input = new StreamReader(response.GetResponseStream()))
+            using (StreamReader input = new(response.GetResponseStream()))
                 resp = (XmlRpcResponse)_deserializer.Deserialize(input);
             return resp;
         }

+        public XmlRpcResponse Send(string url, HttpClient client)
+        {
+            HttpResponseMessage responseMessage = null;
+            HttpRequestMessage request = null;
+            try
+            {
+                request = new(HttpMethod.Post, url);
+                request.Headers.ExpectContinue = false;
+                request.Headers.TransferEncodingChunked = false;
+
+                //if (keepalive)
+                {
+                    request.Headers.TryAddWithoutValidation("Keep-Alive", "timeout=30, max=10");
+                    request.Headers.TryAddWithoutValidation("Connection", "Keep-Alive");
+                }
+                //else
+                //    request.Headers.TryAddWithoutValidation("Connection", "close");
+
+                byte[] outbuf;
+                using (MemoryStream outbufms = new())
+                using (XmlTextWriter xml = new(outbufms, m_encoding))
+                {
+                    _serializer.Serialize(xml, this);
+                    xml.Flush();
+                    outbuf = outbufms.ToArray();
+                }
+
+                request.Content = new ByteArrayContent(outbuf);
+                request.Content.Headers.TryAddWithoutValidation("Content-Type", "text/xml");
+                request.Content.Headers.TryAddWithoutValidation("Content-Length", outbuf.Length.ToString());
+
+                responseMessage = client.Send(request, HttpCompletionOption.ResponseHeadersRead);
+                responseMessage.EnsureSuccessStatusCode();
+
+                XmlRpcResponse resp;
+
+                using (StreamReader input = new(responseMessage.Content.ReadAsStream()))
+                    resp = (XmlRpcResponse)_deserializer.Deserialize(input);
+                return resp;
+            }
+            catch (WebException ex) when (ex.Status is WebExceptionStatus.Timeout)
+            {
+                throw new HttpRequestException("request timeout");
+            }
+            //catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
+            catch (TaskCanceledException)
+            {
+                throw new HttpRequestException("request timeout");
+            }
+            finally
+            {
+                request?.Dispose();
+                responseMessage?.Dispose();
+            }
+        }
+
         /// <summary>Produce <c>String</c> representation of the object.</summary>
         /// <returns><c>String</c> representation of the object.</returns>
         override public string ToString()
diff --git a/trunk/managed/XmlRpc/XmlRpcRequestDeserializer.cs b/trunk/managed/XmlRpc/XmlRpcRequestDeserializer.cs
index 5e96cc4..81ce496 100644
--- a/trunk/managed/XmlRpc/XmlRpcRequestDeserializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcRequestDeserializer.cs
@@ -14,9 +14,7 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_singleton == null)
-                    _singleton = new XmlRpcRequestDeserializer();
-
+                _singleton ??= new XmlRpcRequestDeserializer();
                 return _singleton;
             }
         }
@@ -26,10 +24,10 @@ namespace Nwc.XmlRpc
         /// <returns><c>XmlRpcRequest</c> object resulting from the parse.</returns>
         override public Object Deserialize(TextReader xmlData)
         {
-            using(XmlTextReader reader = new XmlTextReader(xmlData))
+            using(XmlTextReader reader = new(xmlData))
             {
                 reader.DtdProcessing = DtdProcessing.Ignore;
-                XmlRpcRequest request = new XmlRpcRequest(reader.Encoding);
+                XmlRpcRequest request = new(reader.Encoding);
                 bool done = false;

                 lock(this)
diff --git a/trunk/managed/XmlRpc/XmlRpcRequestSerializer.cs b/trunk/managed/XmlRpc/XmlRpcRequestSerializer.cs
index b83a14c..e86b1d5 100644
--- a/trunk/managed/XmlRpc/XmlRpcRequestSerializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcRequestSerializer.cs
@@ -16,9 +16,7 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_singleton == null)
-                    _singleton = new XmlRpcRequestSerializer();
-
+                _singleton ??= new XmlRpcRequestSerializer();
                 return _singleton;
             }
         }
diff --git a/trunk/managed/XmlRpc/XmlRpcResponder.cs b/trunk/managed/XmlRpc/XmlRpcResponder.cs
index 9f0e0ea..942175c 100644
--- a/trunk/managed/XmlRpc/XmlRpcResponder.cs
+++ b/trunk/managed/XmlRpc/XmlRpcResponder.cs
@@ -12,9 +12,9 @@ namespace Nwc.XmlRpc
     /// side dialog. Namely they manage an inbound deserializer and an outbound serializer. </remarks>
     public class XmlRpcResponder
     {
-        private XmlRpcRequestDeserializer _deserializer = new XmlRpcRequestDeserializer();
-        private XmlRpcResponseSerializer _serializer = new XmlRpcResponseSerializer();
-        private XmlRpcServer _server;
+        private readonly XmlRpcRequestDeserializer _deserializer = new();
+        private readonly XmlRpcResponseSerializer _serializer = new();
+        private readonly XmlRpcServer _server;
         private TcpClient _client;
         private SimpleHttpRequest _httpReq;

@@ -58,7 +58,7 @@ namespace Nwc.XmlRpc
         public void Respond(SimpleHttpRequest httpReq)
         {
             XmlRpcRequest xmlRpcReq = (XmlRpcRequest)_deserializer.Deserialize(httpReq.Input);
-            XmlRpcResponse xmlRpcResp = new XmlRpcResponse();
+            XmlRpcResponse xmlRpcResp = new();

             try
             {
@@ -74,12 +74,12 @@ namespace Nwc.XmlRpc
                       XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
             }

-            if(Logger.Delegate != null)
+            if(Logger.Delegate is not null)
                 Logger.WriteEntry(xmlRpcResp.ToString(),LogLevel.Information);

             XmlRpcServer.HttpHeader(httpReq.Protocol,"text/xml",0," 200 OK",httpReq.Output);
             httpReq.Output.Flush();
-            using(XmlTextWriter xml = new XmlTextWriter(httpReq.Output))
+            using(XmlTextWriter xml = new(httpReq.Output))
             {
                 _serializer.Serialize(xml, xmlRpcResp);
                 xml.Flush();
@@ -90,13 +90,13 @@ namespace Nwc.XmlRpc
         ///<summary>Close all contained resources, both the HttpReq and client.</summary>
         public void Close()
         {
-            if(_httpReq != null)
+            if(_httpReq is not null)
             {
                 _httpReq.Close();
                 _httpReq = null;
             }

-            if(_client != null)
+            if(_client is not null)
             {
                 _client.Close();
                 _client = null;
diff --git a/trunk/managed/XmlRpc/XmlRpcResponse.cs b/trunk/managed/XmlRpc/XmlRpcResponse.cs
index 838e8e0..539b391 100644
--- a/trunk/managed/XmlRpc/XmlRpcResponse.cs
+++ b/trunk/managed/XmlRpc/XmlRpcResponse.cs
@@ -69,9 +69,11 @@ namespace Nwc.XmlRpc
         /// <param name="message"><c>String</c> the faultString value.</param>
         public void SetFault(int code,String message)
         {
-            Hashtable fault = new Hashtable();
-            fault.Add("faultCode",code);
-            fault.Add("faultString",message);
+            Hashtable fault = new()
+            {
+                { "faultCode", code },
+                { "faultString", message }
+            };
             Value = fault;
             IsFault = true;
         }
diff --git a/trunk/managed/XmlRpc/XmlRpcResponseDeserializer.cs b/trunk/managed/XmlRpc/XmlRpcResponseDeserializer.cs
index 853d4bf..38a70ee 100644
--- a/trunk/managed/XmlRpc/XmlRpcResponseDeserializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcResponseDeserializer.cs
@@ -18,9 +18,7 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_singleton == null)
-                    _singleton = new XmlRpcResponseDeserializer();
-
+                _singleton ??= new XmlRpcResponseDeserializer();
                 return _singleton;
             }
         }
@@ -30,10 +28,10 @@ namespace Nwc.XmlRpc
         /// <returns><c>XmlRpcResponse</c> object resulting from the parse.</returns>
         override public Object Deserialize(TextReader xmlData)
         {
-            using(XmlTextReader reader = new XmlTextReader(xmlData))
+            using(XmlTextReader reader = new(xmlData))
             {
                 reader.DtdProcessing = DtdProcessing.Ignore;
-                XmlRpcResponse response = new XmlRpcResponse();
+                XmlRpcResponse response = new();
                 bool done = false;

                 lock(this)
diff --git a/trunk/managed/XmlRpc/XmlRpcResponseSerializer.cs b/trunk/managed/XmlRpc/XmlRpcResponseSerializer.cs
index 2bc7891..f4a3c20 100644
--- a/trunk/managed/XmlRpc/XmlRpcResponseSerializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcResponseSerializer.cs
@@ -16,9 +16,7 @@ namespace Nwc.XmlRpc
         {
             get
             {
-                if(_singleton == null)
-                    _singleton = new XmlRpcResponseSerializer();
-
+                _singleton ??= new XmlRpcResponseSerializer();
                 return _singleton;
             }
         }
diff --git a/trunk/managed/XmlRpc/XmlRpcSerializer.cs b/trunk/managed/XmlRpc/XmlRpcSerializer.cs
index 8ce3110..b2850c7 100644
--- a/trunk/managed/XmlRpc/XmlRpcSerializer.cs
+++ b/trunk/managed/XmlRpc/XmlRpcSerializer.cs
@@ -13,7 +13,7 @@ namespace Nwc.XmlRpc
     /// <seealso cref="XmlRpcXmlTokens"/>
     public class XmlRpcSerializer : XmlRpcXmlTokens
     {
-        private Encoding m_encoding = new UTF8Encoding();
+        private readonly Encoding m_encoding = new UTF8Encoding();
         /// <summary>Serialize the <c>XmlRpcRequest</c> to the output stream.</summary>
         /// <param name="output">An <c>XmlTextWriter</c> stream to write data to.</param>
         /// <param name="obj">An <c>Object</c> to serialize.</param>
@@ -30,17 +30,13 @@ namespace Nwc.XmlRpc
         /// <seealso cref="XmlRpcRequest"/>
         public String Serialize(Object obj)
         {
-            using (MemoryStream ms = new MemoryStream(1024))
-            {
-                using (XmlTextWriter xml = new XmlTextWriter(ms, m_encoding))
-                {
-                    xml.Formatting = Formatting.Indented;
-                    xml.Indentation = 4;
-                    Serialize(xml, obj);
-                    xml.Flush();
-                    return m_encoding.GetString(ms.ToArray());
-                }
-            }
+            using MemoryStream ms = new(1024);
+            using XmlTextWriter xml = new(ms, m_encoding);
+            xml.Formatting = Formatting.Indented;
+            xml.Indentation = 4;
+            Serialize(xml, obj);
+            xml.Flush();
+            return m_encoding.GetString(ms.ToArray());
         }

         /// <remarks>Serialize the object to the output stream.</remarks>
@@ -48,12 +44,11 @@ namespace Nwc.XmlRpc
         /// <param name="obj">An <c>Object</c> to serialize.</param>
         public void SerializeObject(XmlTextWriter output, Object obj)
         {
-            if (obj == null)
+            if (obj is null)
                 return;

-            if (obj is byte[])
+            if (obj is byte[] ba)
             {
-                byte[] ba = (byte[])obj;
                 output.WriteStartElement(BASE64);
                 output.WriteBase64(ba, 0, ba.Length);
                 output.WriteEndElement();
@@ -66,25 +61,25 @@ namespace Nwc.XmlRpc
             {
                 output.WriteElementString(INT, obj.ToString());
             }
-            else if (obj is DateTime)
+            else if (obj is DateTime dt)
             {
-                output.WriteElementString(DATETIME, ((DateTime)obj).ToString(ISO_DATETIME));
+                output.WriteElementString(DATETIME, dt.ToString(ISO_DATETIME));
             }
-            else if (obj is Double)
+            else if (obj is Double dbl)
             {
-                output.WriteElementString(DOUBLE, ((Double)obj).ToString(CultureInfo.InvariantCulture));
+                output.WriteElementString(DOUBLE, dbl.ToString(CultureInfo.InvariantCulture));
             }
-            else if (obj is Boolean)
+            else if (obj is Boolean bl)
             {
-                output.WriteElementString(BOOLEAN, ((((Boolean)obj) == true) ? "1" : "0"));
+                output.WriteElementString(BOOLEAN, bl == true ? "1" : "0");
             }
-            else if (obj is IList)
+            else if (obj is IList lst)
             {
                 output.WriteStartElement(ARRAY);
                 output.WriteStartElement(DATA);
                 if (((ArrayList)obj).Count > 0)
                 {
-                    foreach (Object member in ((IList)obj))
+                    foreach (Object member in lst)
                     {
                         output.WriteStartElement(VALUE);
                         SerializeObject(output, member);
@@ -94,9 +89,8 @@ namespace Nwc.XmlRpc
                 output.WriteEndElement();
                 output.WriteEndElement();
             }
-            else if (obj is IDictionary)
+            else if (obj is IDictionary h)
             {
-                IDictionary h = (IDictionary)obj;
                 output.WriteStartElement(STRUCT);
                 foreach (String key in h.Keys)
                 {
diff --git a/trunk/managed/XmlRpc/XmlRpcSystemObject.cs b/trunk/managed/XmlRpc/XmlRpcSystemObject.cs
index 47725d6..fc61044 100644
--- a/trunk/managed/XmlRpc/XmlRpcSystemObject.cs
+++ b/trunk/managed/XmlRpc/XmlRpcSystemObject.cs
@@ -1,251 +1,254 @@
 namespace Nwc.XmlRpc
 {
-  using System;
-  using System.Collections;
-  using System.Reflection;
-
-  /// <summary> XML-RPC System object implementation of extended specifications.</summary>
-  [XmlRpcExposed]
-  public class XmlRpcSystemObject
-  {
-    private XmlRpcServer _server;
-    static private IDictionary _methodHelp = new Hashtable();
-
-    /// <summary>Static <c>IDictionary</c> to hold mappings of method name to associated documentation String</summary>
-    static public IDictionary MethodHelp {
-      get { return _methodHelp; }
-    }
-
-    /// <summary>Constructor.</summary>
-    /// <param name="server"><c>XmlRpcServer</c> server to be the system object for.</param>
-    public XmlRpcSystemObject(XmlRpcServer server)
-      {
-	_server = server;
-	server.Add("system",this);
-	_methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description.");
-      }
-
-    /// <summary>Invoke a method on a given object.</summary>
-    /// <remarks>Using reflection, and respecting the <c>XmlRpcExposed</c> attribute,
-    /// invoke the <paramref>methodName</paramref> method on the <paramref>target</paramref>
-    /// instance with the <paramref>parameters</paramref> provided. All this packages other <c>Invoke</c> methods
-    /// end up calling this.</remarks>
-    /// <returns><c>Object</c> the value the invoked method returns.</returns>
-    /// <exception cref="XmlRpcException">If method does not exist, is not exposed, parameters invalid, or invocation
-    /// results in an exception. Note, the <c>XmlRpcException.Code</c> will indicate cause.</exception>
-    static public Object Invoke(Object target, String methodName, IList parameters)
-      {
-	if (target == null)
-	  throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
-				    XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object.");
-
-	Type type = target.GetType();
-	MethodInfo method = type.GetMethod(methodName);
-
-	try
-	  {
-	    if (!XmlRpcExposedAttribute.ExposedMethod(target,methodName))
-	      throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
-					XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed.");
-	  }
-	catch (MissingMethodException me)
-	  {
-	    throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
-				      XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message);
-	  }
-
-	Object[] args = new Object[parameters.Count];
-
-	int index = 0;
-	foreach (Object arg in parameters)
-	  {
-	    args[index] = arg;
-	    index++;
-	  }
-
-	try
-	  {
-	    Object retValue = method.Invoke(target, args);
-	    if (retValue == null)
-	      throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
-					XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL.");
-	    return retValue;
-	  }
-	catch (XmlRpcException e)
-	  {
-	    throw e;
-	  }
-	catch (ArgumentException ae)
-	  {
-	    Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message,
-			      LogLevel.Information);
-	    String call = methodName + "( ";
-	    foreach (Object o in args)
-	      {
-		call += o.GetType().Name;
-		call += " ";
-	      }
-	    call += ")";
-	    throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
-				      XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call);
-	  }
-	catch (TargetParameterCountException tpce)
-	  {
-	    Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message,
-			      LogLevel.Information);
-	    throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
-				      XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName);
-	  }
-	catch (TargetInvocationException tie)
-	  {
-	    throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
-				      XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message);
-	  }
-      }
-
-    /// <summary>List methods available on all handlers of this server.</summary>
-    /// <returns><c>IList</c> An array of <c>Strings</c>, each <c>String</c> will have form "object.method".</returns>
-    [XmlRpcExposed]
-      public IList listMethods()
-      {
-	IList methods = new ArrayList();
-	Boolean considerExposure;
-
-	foreach (DictionaryEntry handlerEntry in _server)
-	  {
-	    considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType());
-
-	    foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers())
-	      {
- 		if (mi.MemberType != MemberTypes.Method)
- 		  continue;
-
-		if(!((MethodInfo)mi).IsPublic)
-		  continue;
+    using System;
+    using System.Collections;
+    using System.Reflection;

-		if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi))
-		  continue;
-
-		methods.Add(handlerEntry.Key + "." + mi.Name);
-	      }
-	  }
-
-	return methods;
-      }
-
-    /// <summary>Given a method name return the possible signatures for it.</summary>
-    /// <param name="name"><c>String</c> The object.method name to look up.</param>
-    /// <returns><c>IList</c> Of arrays of signatures.</returns>
+    /// <summary> XML-RPC System object implementation of extended specifications.</summary>
     [XmlRpcExposed]
-      public IList methodSignature(String name)
-      {
-	IList signatures = new ArrayList();
-	int index = name.IndexOf('.');
-
-	if (index < 0)
-	  return signatures;
-
-	String oName = name.Substring(0,index);
-	Object obj = _server[oName];
-
-	if (obj == null)
-	  return signatures;
+    public class XmlRpcSystemObject
+    {
+        private readonly XmlRpcServer _server;
+        static private readonly IDictionary _methodHelp = new Hashtable();
+
+        /// <summary>Static <c>IDictionary</c> to hold mappings of method name to associated documentation String</summary>
+        static public IDictionary MethodHelp
+        {
+            get { return _methodHelp; }
+        }
+
+        /// <summary>Constructor.</summary>
+        /// <param name="server"><c>XmlRpcServer</c> server to be the system object for.</param>
+        public XmlRpcSystemObject(XmlRpcServer server)
+        {
+            _server = server;
+            server.Add("system", this);
+            _methodHelp.Add(this.GetType().FullName + ".methodHelp", "Return a string description.");
+        }
+
+        /// <summary>Invoke a method on a given object.</summary>
+        /// <remarks>Using reflection, and respecting the <c>XmlRpcExposed</c> attribute,
+        /// invoke the <paramref>methodName</paramref> method on the <paramref>target</paramref>
+        /// instance with the <paramref>parameters</paramref> provided. All this packages other <c>Invoke</c> methods
+        /// end up calling this.</remarks>
+        /// <returns><c>Object</c> the value the invoked method returns.</returns>
+        /// <exception cref="XmlRpcException">If method does not exist, is not exposed, parameters invalid, or invocation
+        /// results in an exception. Note, the <c>XmlRpcException.Code</c> will indicate cause.</exception>
+        static public Object Invoke(Object target, String methodName, IList parameters)
+        {
+            if (target is null)
+                throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
+                              XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Invalid target object.");
+
+            Type type = target.GetType();
+            MethodInfo method = type.GetMethod(methodName);
+
+            try
+            {
+                if (!XmlRpcExposedAttribute.ExposedMethod(target, methodName))
+                    throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
+                              XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": Method " + methodName + " is not exposed.");
+            }
+            catch (MissingMethodException me)
+            {
+                throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_METHOD,
+                              XmlRpcErrorCodes.SERVER_ERROR_METHOD_MSG + ": " + me.Message);
+            }
+
+            Object[] args = new Object[parameters.Count];
+
+            int index = 0;
+            foreach (Object arg in parameters)
+            {
+                args[index] = arg;
+                index++;
+            }
+
+            try
+            {
+                Object retValue = method.Invoke(target, args);
+                if (retValue is null)
+                    throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
+                              XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": Method returned NULL.");
+                return retValue;
+            }
+            catch (XmlRpcException e)
+            {
+                throw e;
+            }
+            catch (ArgumentException ae)
+            {
+                Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + ae.Message,
+                          LogLevel.Information);
+                String call = methodName + "( ";
+                foreach (Object o in args)
+                {
+                    call += o.GetType().Name;
+                    call += " ";
+                }
+                call += ")";
+                throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
+                              XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement type mismatch invoking " + call);
+            }
+            catch (TargetParameterCountException tpce)
+            {
+                Logger.WriteEntry(XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": " + tpce.Message,
+                          LogLevel.Information);
+                throw new XmlRpcException(XmlRpcErrorCodes.SERVER_ERROR_PARAMS,
+                              XmlRpcErrorCodes.SERVER_ERROR_PARAMS_MSG + ": Arguement count mismatch invoking " + methodName);
+            }
+            catch (TargetInvocationException tie)
+            {
+                throw new XmlRpcException(XmlRpcErrorCodes.APPLICATION_ERROR,
+                              XmlRpcErrorCodes.APPLICATION_ERROR_MSG + " Invoked method " + methodName + ": " + tie.Message);
+            }
+        }
+
+        /// <summary>List methods available on all handlers of this server.</summary>
+        /// <returns><c>IList</c> An array of <c>Strings</c>, each <c>String</c> will have form "object.method".</returns>
+        [XmlRpcExposed]
+        public IList listMethods()
+        {
+            IList methods = new ArrayList();
+            Boolean considerExposure;
+
+            foreach (DictionaryEntry handlerEntry in _server)
+            {
+                considerExposure = XmlRpcExposedAttribute.IsExposed(handlerEntry.Value.GetType());
+
+                foreach (MemberInfo mi in handlerEntry.Value.GetType().GetMembers())
+                {
+                    if (mi.MemberType != MemberTypes.Method)
+                        continue;
+
+                    if (!((MethodInfo)mi).IsPublic)
+                        continue;
+
+                    if (considerExposure && !XmlRpcExposedAttribute.IsExposed(mi))
+                        continue;
+
+                    methods.Add(handlerEntry.Key + "." + mi.Name);
+                }
+            }
+
+            return methods;
+        }
+
+        /// <summary>Given a method name return the possible signatures for it.</summary>
+        /// <param name="name"><c>String</c> The object.method name to look up.</param>
+        /// <returns><c>IList</c> Of arrays of signatures.</returns>
+        [XmlRpcExposed]
+        public IList methodSignature(String name)
+        {
+            IList signatures = new ArrayList();
+            int index = name.IndexOf('.');
+
+            if (index < 0)
+                return signatures;
+
+            String oName = name[..index];
+            Object obj = _server[oName];
+
+            if (obj is null)
+                return signatures;
+
+            MemberInfo[] mi = obj.GetType().GetMember(name[(index + 1)..]);
+
+            if (mi is null || mi.Length != 1) // for now we want a single signature
+                return signatures;
+
+            MethodInfo method;
+
+            try
+            {
+                method = (MethodInfo)mi[0];
+            }
+            catch (Exception e)
+            {
+                Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e,
+                          LogLevel.Information);
+                return signatures;
+            }
+
+            if (!method.IsPublic)
+                return signatures;
+
+            IList signature = new ArrayList
+            {
+                method.ReturnType.Name
+            };
+
+            foreach (ParameterInfo param in method.GetParameters())
+            {
+                signature.Add(param.ParameterType.Name);
+            }
+
+
+            signatures.Add(signature);
+
+            return signatures;
+        }
+
+        /// <summary>Help for given method signature. Not implemented yet.</summary>
+        /// <param name="name"><c>String</c> The object.method name to look up.</param>
+        /// <returns><c>String</c> help text. Rich HTML text.</returns>
+        [XmlRpcExposed]
+        public String methodHelp(String name)
+        {
+            String help = null;
+
+            try
+            {
+                help = (String)_methodHelp[_server.MethodName(name)];
+            }
+            catch (XmlRpcException e)
+            {
+                throw e;
+            }
+            catch (Exception) { /* ignored */ };
+
+            help ??= "No help available for: " + name;
+
+            return help;
+        }
+
+        /// <summary>Boxcarring support method.</summary>
+        /// <param name="calls"><c>IList</c> of calls</param>
+        /// <returns><c>ArrayList</c> of results/faults.</returns>
+        [XmlRpcExposed]
+        public IList multiCall(IList calls)
+        {
+            IList responses = new ArrayList();
+            XmlRpcResponse fault = new();
+
+            foreach (IDictionary call in calls)
+            {
+                try
+                {
+                    XmlRpcRequest req = new((String)call[XmlRpcXmlTokens.METHOD_NAME], (ArrayList)call[XmlRpcXmlTokens.PARAMS]);
+                    Object results = _server.Invoke(req);
+                    IList response = new ArrayList
+                    {
+                        results
+                    };
+                    responses.Add(response);
+                }
+                catch (XmlRpcException e)
+                {
+                    fault.SetFault(e.FaultCode, e.FaultString);
+                    responses.Add(fault.Value);
+                }
+                catch (Exception e2)
+                {
+                    fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
+                               XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
+                    responses.Add(fault.Value);
+                }
+            }
+
+            return responses;
+        }

-	MemberInfo[] mi = obj.GetType().GetMember(name.Substring(index + 1));
-
-	if (mi == null || mi.Length != 1) // for now we want a single signature
-	  return signatures;
-
-	MethodInfo method;
-
-	try
-	  {
-	    method = (MethodInfo)mi[0];
-	  }
-	catch (Exception e)
-	  {
-	    Logger.WriteEntry("Attempted methodSignature call on " + mi[0] + " caused: " + e,
-			      LogLevel.Information);
-	    return signatures;
-	  }
-
-	if (!method.IsPublic)
-	  return signatures;
-
-	IList signature = new ArrayList();
-	signature.Add(method.ReturnType.Name);
-
-	foreach (ParameterInfo param in method.GetParameters())
-	  {
-	    signature.Add(param.ParameterType.Name);
-	  }
-
-
-	signatures.Add(signature);
-
-	return signatures;
-      }
-
-    /// <summary>Help for given method signature. Not implemented yet.</summary>
-    /// <param name="name"><c>String</c> The object.method name to look up.</param>
-    /// <returns><c>String</c> help text. Rich HTML text.</returns>
-    [XmlRpcExposed]
-      public String methodHelp(String name)
-      {
-	String help = null;
-
-	try
-	  {
-	    help = (String)_methodHelp[_server.MethodName(name)];
-	  }
-	catch (XmlRpcException e)
-	  {
-	    throw e;
-	  }
-	catch (Exception) { /* ignored */ };
-
-	if (help == null)
-	  help = "No help available for: " + name;
-
-	return help;
-      }
-
-    /// <summary>Boxcarring support method.</summary>
-    /// <param name="calls"><c>IList</c> of calls</param>
-    /// <returns><c>ArrayList</c> of results/faults.</returns>
-    [XmlRpcExposed]
-      public IList multiCall(IList calls)
-      {
-	IList responses = new ArrayList();
-	XmlRpcResponse fault = new XmlRpcResponse();
-
-	foreach (IDictionary call in calls)
-	  {
-	    try
-	      {
-		XmlRpcRequest req = new XmlRpcRequest((String)call[XmlRpcXmlTokens.METHOD_NAME],
-						      (ArrayList)call[XmlRpcXmlTokens.PARAMS]);
-		Object results = _server.Invoke(req);
-		IList response = new ArrayList();
-		response.Add(results);
-		responses.Add(response);
-	      }
-	    catch (XmlRpcException e)
-	      {
-		fault.SetFault(e.FaultCode, e.FaultString);
-		responses.Add(fault.Value);
-	      }
-	    catch (Exception e2)
-	      {
-		fault.SetFault(XmlRpcErrorCodes.APPLICATION_ERROR,
-			       XmlRpcErrorCodes.APPLICATION_ERROR_MSG + ": " + e2.Message);
-		responses.Add(fault.Value);
-	      }
-	  }
-
-	return responses;
-      }
-
-  }
+    }
 }

diff --git a/trunk/managed/XmlRpc/xmlrpc.csproj b/trunk/managed/XmlRpc/xmlrpc.csproj
index b644207..4933760 100644
--- a/trunk/managed/XmlRpc/xmlrpc.csproj
+++ b/trunk/managed/XmlRpc/xmlrpc.csproj
@@ -1,71 +1,17 @@
-<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
-    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{678DEE13-A366-4130-9BCA-46F695640AD5}</ProjectGuid>
+    <TargetFramework>net8.0</TargetFramework>
     <OutputType>Library</OutputType>
     <NoStandardLibraries>false</NoStandardLibraries>
-    <AssemblyName>XMLRPC</AssemblyName>
-    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
-    <FileAlignment>512</FileAlignment>
-    <TargetFrameworkProfile />
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
-    <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
-    <OutputPath>bin\Debug\</OutputPath>
-    <DefineConstants>DEBUG;TRACE</DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
+    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
+    <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+    <Deterministic>true</Deterministic>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
-    <DebugType>pdbonly</DebugType>
-    <Optimize>true</Optimize>
-    <OutputPath>bin\Release\</OutputPath>
     <DefineConstants>
     </DefineConstants>
-    <ErrorReport>prompt</ErrorReport>
-    <WarningLevel>4</WarningLevel>
-    <Prefer32Bit>false</Prefer32Bit>
-  </PropertyGroup>
-  <PropertyGroup>
-    <RootNamespace>xmlrpc</RootNamespace>
+    <TieredCompilationQuickJit>false</TieredCompilationQuickJit>
+    <Optimize>True</Optimize>
   </PropertyGroup>
-  <ItemGroup>
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="System.Xml" />
-    <Reference Include="System.Xml.Linq" />
-  </ItemGroup>
-  <ItemGroup>
-    <Compile Include="AssemblyInfo.cs" />
-    <Compile Include="Logger.cs" />
-    <Compile Include="SimpleHttpRequest.cs" />
-    <Compile Include="XmlRpcBoxcarRequest.cs" />
-    <Compile Include="XmlRpcClientProxy.cs" />
-    <Compile Include="XmlRpcDeserializer.cs" />
-    <Compile Include="XmlRpcErrorCodes.cs" />
-    <Compile Include="XmlRpcException.cs" />
-    <Compile Include="XmlRpcExposedAttribute.cs" />
-    <Compile Include="XmlRpcRequest.cs" />
-    <Compile Include="XmlRpcRequestDeserializer.cs" />
-    <Compile Include="XmlRpcRequestSerializer.cs" />
-    <Compile Include="XmlRpcResponder.cs" />
-    <Compile Include="XmlRpcResponse.cs" />
-    <Compile Include="XmlRpcResponseDeserializer.cs" />
-    <Compile Include="XmlRpcResponseSerializer.cs" />
-    <Compile Include="XmlRpcSerializer.cs" />
-    <Compile Include="XmlRpcServer.cs" />
-    <Compile Include="XmlRpcSystemObject.cs" />
-    <Compile Include="XmlRpcXmlTokens.cs" />
-  </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.CSHARP.Targets" />
-  <ProjectExtensions>
-    <VisualStudio AllowExistingFolder="true" />
-  </ProjectExtensions>
+
 </Project>
\ No newline at end of file
ViewGit