diff --git a/Source/Core/GZBuilder/Data/ModelData.cs b/Source/Core/GZBuilder/Data/ModelData.cs
index 5fcfcd6e2a23056c372c227a3700482d2e37f3fd..5e26d11b98383a97f9ebf8792561116540d728f4 100644
--- a/Source/Core/GZBuilder/Data/ModelData.cs
+++ b/Source/Core/GZBuilder/Data/ModelData.cs
@@ -1,36 +1,55 @@
-using System.Collections.Generic;
+#region ================== Namespaces
+
+using System.Collections.Generic;
+using CodeImp.DoomBuilder.Geometry;
+using CodeImp.DoomBuilder.GZBuilder.MD3;
 using SlimDX;
 using SlimDX.Direct3D9;
-using CodeImp.DoomBuilder.GZBuilder.MD3;
+
+#endregion
 
 namespace CodeImp.DoomBuilder.GZBuilder.Data
 {
 	internal sealed class ModelData
 	{
+		#region ================== Variables
+
+		private ModelLoadState loadstate;
+
+		#endregion
+
+		#region ================== Properties
+
 		internal List<string> ModelNames;
 		internal List<string> TextureNames;
 
 		internal GZModel Model;
 
-		private ModelLoadState loadstate;
-		public ModelLoadState LoadState { get { return loadstate; } internal set { loadstate = value; } }
-
 		internal Matrix Scale;
-		internal float zOffset;
+		internal Vector2D OffsetXY;
+		internal float OffsetZ;
 
 		internal float AngleOffset; //in radians
 		internal float PitchOffset; //in radians
 		internal float RollOffset; //in radians
 		internal bool OverridePalette; //used for voxel models only
-		internal bool IsVoxel;
 		internal bool InheritActorPitch;
 		internal bool InheritActorRoll;
 
+		internal bool IsVoxel;
+
+		public ModelLoadState LoadState { get { return loadstate; } internal set { loadstate = value; } }
+
+		#endregion
+
+		#region ================== Constructor / Disposer
+
 		internal ModelData() 
 		{
 			ModelNames = new List<string>();
 			TextureNames = new List<string>();
 			Scale = Matrix.Identity;
+			OffsetXY = new Vector2D();
 		}
 
 		internal void Dispose() 
@@ -42,5 +61,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data
 				loadstate = ModelLoadState.None;
 			}
 		}
+
+		#endregion
 	}
 }
diff --git a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
index 0c49ffb24399c48bb16553f91c68bb78d715c636..53bfbf3ae0bbb3000daee2ddb49aab4e4c61a6bc 100644
--- a/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
+++ b/Source/Core/GZBuilder/GZDoom/ModeldefStructure.cs
@@ -21,7 +21,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
 			string[] modelNames = new string[4];
 			string path = "";
 			Vector3 scale = new Vector3(1, 1, 1);
-			float zOffset = 0;
+			Vector3 offset = new Vector3();
 			float angleOffset = 0;
 			float pitchOffset = 0;
 			float rollOffset = 0;
@@ -155,34 +155,62 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
 
 						case "scale":
 							parser.SkipWhitespace(true);
-
 							token = parser.StripTokenQuotes(parser.ReadToken());
 							if(!parser.ReadSignedFloat(token, ref scale.X)) 
 							{
 								// Not numeric!
-								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale X value, but got '" + token + "'");
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale X value, but got '" + token + "'");
 								gotErrors = true;
 								break;
 							}
 
 							parser.SkipWhitespace(true);
-
 							token = parser.StripTokenQuotes(parser.ReadToken());
 							if(!parser.ReadSignedFloat(token, ref scale.Y)) 
 							{
 								// Not numeric!
-								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Y value, but got '" + token + "'");
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale Y value, but got '" + token + "'");
 								gotErrors = true;
 								break;
 							}
 
 							parser.SkipWhitespace(true);
-
 							token = parser.StripTokenQuotes(parser.ReadToken());
 							if(!parser.ReadSignedFloat(token, ref scale.Z)) 
 							{
 								// Not numeric!
-								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected scale Z value, but got '" + token + "'");
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Scale Z value, but got '" + token + "'");
+								gotErrors = true;
+							}
+							break;
+
+						case "offset":
+							parser.SkipWhitespace(true);
+							token = parser.StripTokenQuotes(parser.ReadToken());
+							if(!parser.ReadSignedFloat(token, ref offset.X)) 
+							{
+								// Not numeric!
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset X value, but got '" + token + "'");
+								gotErrors = true;
+								break;
+							}
+
+							parser.SkipWhitespace(true);
+							token = parser.StripTokenQuotes(parser.ReadToken());
+							if(!parser.ReadSignedFloat(token, ref offset.Y)) 
+							{
+								// Not numeric!
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset Y value, but got '" + token + "'");
+								gotErrors = true;
+								break;
+							}
+
+							parser.SkipWhitespace(true);
+							token = parser.StripTokenQuotes(parser.ReadToken());
+							if(!parser.ReadSignedFloat(token, ref offset.Z)) 
+							{
+								// Not numeric!
+								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected Offset Z value, but got '" + token + "'");
 								gotErrors = true;
 							}
 							break;
@@ -191,7 +219,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
 							parser.SkipWhitespace(true);
 
 							token = parser.StripTokenQuotes(parser.ReadToken());
-							if(!parser.ReadSignedFloat(token, ref zOffset)) 
+							if(!parser.ReadSignedFloat(token, ref offset.Z)) 
 							{
 								// Not numeric!
 								General.ErrorLogger.Add(ErrorType.Error, "Error in " + parser.Source + " at line " + parser.GetCurrentLineNumber() + ": expected ZOffset value, but got '" + token + "'");
@@ -382,7 +410,8 @@ namespace CodeImp.DoomBuilder.GZBuilder.GZDoom
 			//classname is set in ModeldefParser
 			ModelData mde = new ModelData();
 			mde.Scale = Matrix.Scaling(scale);
-			mde.zOffset = zOffset;
+			mde.OffsetXY = new Vector2D(offset.Y, -offset.X); // Things are complicated in GZDoom...
+			mde.OffsetZ = offset.Z;
 			mde.AngleOffset = Angle2D.DegToRad(angleOffset);
 			mde.RollOffset = Angle2D.DegToRad(rollOffset);
 			mde.PitchOffset = Angle2D.DegToRad(pitchOffset);
diff --git a/Source/Core/General/MapManager.cs b/Source/Core/General/MapManager.cs
index 9ddac7580fff9c3af36e3572f529d661f30b6ab0..ac01fd3fed645fac2fcc2b07db991a332cec868b 100644
--- a/Source/Core/General/MapManager.cs
+++ b/Source/Core/General/MapManager.cs
@@ -1784,6 +1784,10 @@ namespace CodeImp.DoomBuilder {
 			// Set this to false so we can see if errors are added
 			General.ErrorLogger.IsErrorAdded = false;
 
+#if DEBUG 
+			DebugConsole.Clear();
+#endif
+
 			ReloadResources();
 
 			if (General.ErrorLogger.IsErrorAdded)
diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs
index f73d9344ba789385bbc60661c2d0763a23b9d5e4..7c7dc3a9c8111f46eceab58e32cd3208d2f0a521 100644
--- a/Source/Core/Rendering/Renderer2D.cs
+++ b/Source/Core/Rendering/Renderer2D.cs
@@ -1339,7 +1339,7 @@ namespace CodeImp.DoomBuilder.Rendering
 						foreach(Thing t in group.Value) 
 						{
 							if(General.Settings.GZDrawModelsMode == ModelRenderMode.SELECTION && !t.Selected) continue;
-							Vector2D screenpos = ((Vector2D)t.Position).GetTransformed(translatex, translatey, scale, -scale);
+							Vector2D screenpos = ((Vector2D)t.Position + General.Map.Data.ModeldefEntries[t.Type].OffsetXY.GetScaled(t.ScaleX).GetRotated(t.Angle)).GetTransformed(translatex, translatey, scale, -scale);
 							float modelScale = scale * t.ActorScale.Width * t.ScaleX;
 
 							//should we render this model?
@@ -1353,12 +1353,14 @@ namespace CodeImp.DoomBuilder.Rendering
 							{
 								float sx = t.ScaleX * t.ActorScale.Width;
 								float sy = t.ScaleY * t.ActorScale.Height;
-								Matrix modelcale = Matrix.Scaling(sx, sx, sy) * General.Map.Data.ModeldefEntries[t.Type].Scale;
+								
+								Matrix modelscale = Matrix.Scaling(sx, sx, sy);
+								Matrix mdescale = General.Map.Data.ModeldefEntries[t.Type].Scale;
 								Matrix rotation = Matrix.RotationY(-(t.RollRad + General.Map.Data.ModeldefEntries[t.Type].RollOffset))
 										* Matrix.RotationX(-(t.PitchRad + General.Map.Data.ModeldefEntries[t.Type].PitchOffset))
 										* Matrix.RotationZ(t.Angle + General.Map.Data.ModeldefEntries[t.Type].AngleOffset);
 								Matrix position = Matrix.Translation(screenpos.x, screenpos.y, 0.0f);
-								Matrix world = rotation * modelcale * viewscale * position;
+								Matrix world = mdescale * rotation * modelscale * viewscale * position;
 
 								graphics.Shaders.Things2D.SetTransformSettings(world);
 								graphics.Shaders.Things2D.ApplySettings();
diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs
index 5fb5cce515c6b7fa03a8a64210bbd6c4619954b8..d02ce23c647e4efe59e1bbba026140dda267559e 100644
--- a/Source/Core/Rendering/Renderer3D.cs
+++ b/Source/Core/Rendering/Renderer3D.cs
@@ -1122,13 +1122,18 @@ namespace CodeImp.DoomBuilder.Rendering
 					// Create the matrix for positioning / rotation
 					float sx = t.Thing.ScaleX * t.Thing.ActorScale.Width;
 					float sy = t.Thing.ScaleY * t.Thing.ActorScale.Height * viewstretch;
-					Matrix modelcale = Matrix.Scaling(sx, sx, sy) * General.Map.Data.ModeldefEntries[t.Thing.Type].Scale;
+
+					Matrix modelscale = Matrix.Scaling(sx, sx, sy);
+					Matrix mdescale = General.Map.Data.ModeldefEntries[t.Thing.Type].Scale;
+
 					Matrix rotation = Matrix.RotationY(-(t.Thing.RollRad + General.Map.Data.ModeldefEntries[t.Thing.Type].RollOffset))
 						* Matrix.RotationX(-(t.Thing.PitchRad + General.Map.Data.ModeldefEntries[t.Thing.Type].PitchOffset))
 						* Matrix.RotationZ(t.Thing.Angle + General.Map.Data.ModeldefEntries[t.Thing.Type].AngleOffset);
-					Matrix position = t.Position * Matrix.Translation(new Vector3(0, 0, General.Map.Data.ModeldefEntries[t.Thing.Type].zOffset * t.Thing.ScaleY));
+					
+					Vector2D offset2d = General.Map.Data.ModeldefEntries[t.Thing.Type].OffsetXY.GetScaled(t.Thing.ScaleX).GetRotated(t.Thing.Angle);
+					Matrix position = Matrix.Translation(offset2d.x, offset2d.y, General.Map.Data.ModeldefEntries[t.Thing.Type].OffsetZ * t.Thing.ScaleY) * t.Position;
 
-					world = rotation * modelcale * position;
+					world = mdescale * rotation * modelscale * position;
 					ApplyMatrices3D();
 
 					//mxd. set variables for fog rendering