private void Recalculate() { long now = this.CameraMain.Plugin.Time; { long remove = now - this.MaxHistoryDuration; while (this.History.Count != 0) { var n = this.History.First; if (n.Value.Time <= remove) { this.History.RemoveFirst(); } else { break; } } } if (this.History.Count == 0) { return; } // Calculate weighted average. double totalWeight = 0.0; double[] totalPosition = new double[3]; double totalOffsetX = 0.0; double totalOffsetY = 0.0; { var n = this.History.Last; while (n != null) { var cur = n.Value; n = n.Previous; long diff = this.MaxHistoryDuration - (now - cur.Time); double ratio = (double)diff / (double)this.MaxHistoryDuration; double weight = ratio * ratio; totalWeight += weight; totalPosition[0] += cur.Position[0] * weight; totalPosition[1] += cur.Position[1] * weight; totalPosition[2] += cur.Position[2] * weight; double ofx = cur.OffsetX; double ofy = cur.OffsetY; //this.ApplyIgnoreOffset(ref ofx, ref ofy); totalOffsetX += ofx * weight; totalOffsetY += ofy * weight; } } if (totalWeight <= 0.0) { return; } totalPosition[0] /= totalWeight; totalPosition[1] /= totalWeight; totalPosition[2] /= totalWeight; totalOffsetX /= totalWeight; totalOffsetY /= totalWeight; if (this.LastCalculated == null) { this.LastCalculated = new CameraStabilizeHistoryEntry(); this.LastCalculated.Time = now; this.LastCalculated.Position = new float[3]; this.LastCalculated.Position[0] = (float)totalPosition[0]; this.LastCalculated.Position[1] = (float)totalPosition[1]; this.LastCalculated.Position[2] = (float)totalPosition[2]; this.LastCalculated.OffsetX = (float)totalOffsetX; this.LastCalculated.OffsetY = (float)totalOffsetY; return; } bool changed = false; { double value = totalPosition[0]; double old = this.LastCalculated.Position[0]; double ignore = this.IgnorePositionX; double diff = value - old; if (Math.Abs(diff) > ignore) { if (diff >= 0.0) { diff -= ignore; } else { diff += ignore; } this.LastCalculated.Position[0] += (float)diff; changed = true; } } { double value = totalPosition[1]; double old = this.LastCalculated.Position[1]; double ignore = this.IgnorePositionY; double diff = value - old; if (Math.Abs(diff) > ignore) { if (diff >= 0.0) { diff -= ignore; } else { diff += ignore; } this.LastCalculated.Position[1] += (float)diff; changed = true; } } { double value = totalPosition[2]; double old = this.LastCalculated.Position[2]; double ignore = this.IgnorePositionZ; double diff = value - old; if (Math.Abs(diff) > ignore) { if (diff >= 0.0) { diff -= ignore; } else { diff += ignore; } this.LastCalculated.Position[2] += (float)diff; changed = true; } } { double value = totalOffsetX; double old = this.LastCalculated.OffsetX; double ignore = this.IgnoreRotationX; double diff = value - old; if (Math.Abs(diff) > ignore) { if (diff >= 0.0) { diff -= ignore; } else { diff += ignore; } this.LastCalculated.OffsetX += (float)diff; changed = true; } } { double value = totalOffsetY; double old = this.LastCalculated.OffsetY; double ignore = this.IgnoreRotationY; double diff = value - old; if (Math.Abs(diff) > ignore) { if (diff >= 0.0) { diff -= ignore; } else { diff += ignore; } this.LastCalculated.OffsetY += (float)diff; changed = true; } } if (changed) { this.LastCalculated.Time = now; } }
internal void Update(NiAVObject root, NiAVObject head, CameraUpdate update) { this.UpdateValues(update); var tpos = head.WorldTransform.Position; var spos = root.WorldTransform.Position; float x = tpos.X - spos.X; float y = tpos.Y - spos.Y; float z = tpos.Z - spos.Z; root.WorldTransform.Rotation.GetEulerAngles(this.TempPoint); float angle = this.TempPoint.Z; this.TempPoint.X = x; this.TempPoint.Y = y; this.TempPoint.Z = z; float len = this.TempPoint.Length; if (len > 0.0f) { this.TempPoint.Normalize(this.TempPoint); } tpos = this.TempTransform.Position; tpos.X = 0.0f; tpos.Y = 0.0f; tpos.Z = 0.0f; this.TempTransform.LookAt(this.TempPoint); this.TempTransform.Rotation.RotateZ(angle, this.TempTransform.Rotation); this.TempPoint.X = 0.0f; this.TempPoint.Y = len; this.TempPoint.Z = 0.0f; this.TempTransform.Translate(this.TempPoint, this.TempPoint); x = this.TempPoint.X; y = this.TempPoint.Y; z = this.TempPoint.Z; root.WorldTransform.Rotation.GetEulerAngles(this.TempPoint); head.WorldTransform.Rotation.GetEulerAngles(this.TempTransform.Position); double ofx = Utility.ClampToPi(this.TempTransform.Position.Z - this.TempPoint.Z); double ofy = Utility.ClampToPi(this.TempTransform.Position.X - this.TempPoint.X); this.ApplyIgnoreOffset(ref ofx, ref ofy); long now = this.CameraMain.Plugin.Time; var e = new CameraStabilizeHistoryEntry(); e.Time = now; e.OffsetX = (float)ofx; e.OffsetY = (float)ofy; e.Position = new float[] { x, y, z }; this.History.AddLast(e); this.NeedRecalculate = true; }
internal void Update(NiAVObject root, NiAVObject head, CameraUpdate update) { UpdateValues(update); var tpos = head.WorldTransform.Position; var spos = root.WorldTransform.Position; var x = tpos.X - spos.X; var y = tpos.Y - spos.Y; var z = tpos.Z - spos.Z; root.WorldTransform.Rotation.GetEulerAngles(TempPoint); var angle = TempPoint.Z; TempPoint.X = x; TempPoint.Y = y; TempPoint.Z = z; var len = TempPoint.Length; if (len > 0.0f) { TempPoint.Normalize(TempPoint); } tpos = TempTransform.Position; tpos.X = 0.0f; tpos.Y = 0.0f; tpos.Z = 0.0f; TempTransform.LookAt(TempPoint); TempTransform.Rotation.RotateZ(angle, TempTransform.Rotation); TempPoint.X = 0.0f; TempPoint.Y = len; TempPoint.Z = 0.0f; TempTransform.Translate(TempPoint, TempPoint); x = TempPoint.X; y = TempPoint.Y; z = TempPoint.Z; root.WorldTransform.Rotation.GetEulerAngles(TempPoint); head.WorldTransform.Rotation.GetEulerAngles(TempTransform.Position); var ofx = Utility.ClampToPi(TempTransform.Position.Z - TempPoint.Z); var ofy = Utility.ClampToPi(TempTransform.Position.X - TempPoint.X); ApplyIgnoreOffset(ref ofx, ref ofy); var now = CameraMain.Plugin.Time; var e = new CameraStabilizeHistoryEntry(); e.Time = now; e.OffsetX = (float)ofx; e.OffsetY = (float)ofy; e.Position = new[] { x, y, z }; History.AddLast(e); NeedRecalculate = true; }