diff --git a/Source/Core/GZBuilder/Data/ModelData.cs b/Source/Core/GZBuilder/Data/ModelData.cs index c3299873..5424ba5e 100755 --- a/Source/Core/GZBuilder/Data/ModelData.cs +++ b/Source/Core/GZBuilder/Data/ModelData.cs @@ -22,6 +22,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data private ModelLoadState loadstate; private Vector3f scale; + private Vector3f rotationcenter; private Matrix transform; private Matrix transformrotation; private Matrix transformstretched; @@ -40,6 +41,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data internal GZModel Model; internal Vector3f Scale { get { return scale; } } + internal Vector3f RotationCenter { get { return rotationcenter; } set { rotationcenter = value; } } internal Matrix Transform { get { /* return (General.Settings.GZStretchView ? transformstretched : transform); */ return transformstretched; } } internal Matrix TransformRotation { get { return transformrotation; } } internal bool OverridePalette; // Used for voxel models only @@ -47,6 +49,7 @@ namespace CodeImp.DoomBuilder.GZBuilder.Data internal bool InheritActorPitch; internal bool UseActorPitch; internal bool UseActorRoll; + internal bool UseRotationCenter; internal bool IsVoxel; diff --git a/Source/Core/Rendering/Renderer2D.cs b/Source/Core/Rendering/Renderer2D.cs index cb934bf4..a836a5f7 100755 --- a/Source/Core/Rendering/Renderer2D.cs +++ b/Source/Core/Rendering/Renderer2D.cs @@ -1544,7 +1544,12 @@ namespace CodeImp.DoomBuilder.Rendering Matrix modelscale = Matrix.Scaling((float)sx, (float)sx, (float)sy); Matrix rotation = Matrix.RotationY((float)-t.RollRad) * Matrix.RotationX((float)-t.PitchRad) * Matrix.RotationZ((float)t.Angle); Matrix position = Matrix.Translation((float)screenpos.x, (float)screenpos.y, 0.0f); - Matrix world = General.Map.Data.ModeldefEntries[t.Type].Transform * modelscale * rotation * viewscale * position; + Matrix world; + + if (General.Map.Data.ModeldefEntries[t.Type].UseRotationCenter) + world = General.Map.Data.ModeldefEntries[t.Type].Transform * modelscale * Matrix.Translation(-General.Map.Data.ModeldefEntries[t.Type].RotationCenter) * rotation * Matrix.Translation(General.Map.Data.ModeldefEntries[t.Type].RotationCenter) * viewscale * position; + else + world = General.Map.Data.ModeldefEntries[t.Type].Transform * modelscale * rotation * viewscale * position; SetThings2DTransformSettings(world); diff --git a/Source/Core/Rendering/Renderer3D.cs b/Source/Core/Rendering/Renderer3D.cs index 9b15aad8..f1c72145 100755 --- a/Source/Core/Rendering/Renderer3D.cs +++ b/Source/Core/Rendering/Renderer3D.cs @@ -1603,7 +1603,10 @@ namespace CodeImp.DoomBuilder.Rendering Matrix modelscale = Matrix.Scaling((float)sx, (float)sx, (float)sy); Matrix modelrotation = Matrix.RotationY((float)-t.Thing.RollRad) * Matrix.RotationX((float)-t.Thing.PitchRad) * Matrix.RotationZ((float)t.Thing.Angle); - world = General.Map.Data.ModeldefEntries[t.Thing.Type].Transform * modelscale * modelrotation * t.Position; + if(General.Map.Data.ModeldefEntries[t.Thing.Type].UseRotationCenter) + world = General.Map.Data.ModeldefEntries[t.Thing.Type].Transform * modelscale * Matrix.Translation(-General.Map.Data.ModeldefEntries[t.Thing.Type].RotationCenter) * modelrotation * Matrix.Translation(General.Map.Data.ModeldefEntries[t.Thing.Type].RotationCenter) * t.Position; + else + world = General.Map.Data.ModeldefEntries[t.Thing.Type].Transform * modelscale * modelrotation * t.Position; graphics.SetUniform(UniformName.world, world); // Set variables for fog rendering diff --git a/Source/Core/ZDoom/ModeldefParser.cs b/Source/Core/ZDoom/ModeldefParser.cs index 8e69d0a2..a06420d3 100755 --- a/Source/Core/ZDoom/ModeldefParser.cs +++ b/Source/Core/ZDoom/ModeldefParser.cs @@ -45,6 +45,9 @@ namespace CodeImp.DoomBuilder.ZDoom this.actorsbyclass = actorsbyclass; this.entries = new Dictionary<string, ModelData>(StringComparer.OrdinalIgnoreCase); this.parsedlumps = new HashSet<string>(); + + // We don't want the '-' as a special token because commands can contain them (like "rotation-center") + specialtokens = ":{}+\n;"; } #endregion @@ -187,7 +190,7 @@ namespace CodeImp.DoomBuilder.ZDoom if(mds.Frames.ContainsKey(targetsprite)) { // Create model data - ModelData md = new ModelData { InheritActorPitch = mds.InheritActorPitch, UseActorPitch = mds.UseActorPitch, UseActorRoll = mds.UseActorRoll, Path = mds.DataPath }; + ModelData md = new ModelData { InheritActorPitch = mds.InheritActorPitch, UseActorPitch = mds.UseActorPitch, UseActorRoll = mds.UseActorRoll, UseRotationCenter = mds.UseRotationCenter, RotationCenter = mds.RotationCenter, Path = mds.DataPath }; // Things are complicated in GZDoom... Matrix moffset = Matrix.Translation(mds.Offset.Y, -mds.Offset.X, mds.Offset.Z); diff --git a/Source/Core/ZDoom/ModeldefStructure.cs b/Source/Core/ZDoom/ModeldefStructure.cs index ef52cf95..dee2d052 100755 --- a/Source/Core/ZDoom/ModeldefStructure.cs +++ b/Source/Core/ZDoom/ModeldefStructure.cs @@ -34,12 +34,14 @@ namespace CodeImp.DoomBuilder.ZDoom private string path; private Vector3f scale; private Vector3f offset; + private Vector3f rotationcenter; private float angleoffset; private float pitchoffset; private float rolloffset; private bool inheritactorpitch; private bool useactorpitch; private bool useactorroll; + private bool userotationcenter; private Dictionary<string, HashSet<FrameStructure>> frames; @@ -52,12 +54,14 @@ namespace CodeImp.DoomBuilder.ZDoom public Dictionary<int, string> ModelNames { get { return modelnames; } } public Vector3f Scale { get { return scale; } } public Vector3f Offset { get { return offset; } } + public Vector3f RotationCenter { get { return rotationcenter; } } public float AngleOffset { get { return angleoffset; } } public float PitchOffset { get { return pitchoffset; } } public float RollOffset { get { return rolloffset; } } public bool InheritActorPitch { get { return inheritactorpitch; } } public bool UseActorPitch { get { return useactorpitch; } } public bool UseActorRoll { get { return useactorroll; } } + public bool UseRotationCenter { get { return userotationcenter; } } public string DataPath { get { return path; } } // biwa public Dictionary<string, HashSet<FrameStructure>> Frames { get { return frames; } } @@ -351,6 +355,35 @@ namespace CodeImp.DoomBuilder.ZDoom } break; + case "rotation-center": + parser.SkipWhitespace(true); + token = parser.ReadToken(); + if (!parser.ReadSignedFloat(token, ref rotationcenter.X)) + { + // Not numeric! + parser.ReportError("Expected rotation center X value, but got \"" + token + "\""); + return false; + } + + parser.SkipWhitespace(true); + token = parser.ReadToken(); + if (!parser.ReadSignedFloat(token, ref rotationcenter.Y)) + { + // Not numeric! + parser.ReportError("Expected rotation center Y value, but got \"" + token + "\""); + return false; + } + + parser.SkipWhitespace(true); + token = parser.ReadToken(); + if (!parser.ReadSignedFloat(token, ref rotationcenter.Z)) + { + // Not numeric! + parser.ReportError("Expected rotation center Z value, but got \"" + token + "\""); + return false; + } + break; + case "useactorpitch": inheritactorpitch = false; useactorpitch = true; @@ -360,6 +393,11 @@ namespace CodeImp.DoomBuilder.ZDoom useactorroll = true; break; + case "rotating": + case "userotationcenter": + userotationcenter = true; + break; + case "inheritactorpitch": inheritactorpitch = true; useactorpitch = false;