最終更新 1765432298

修正履歴 7c14fd64e20ae8676959e4befe0ff14fc6dfa385

framegen.cs Raw
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using Vintagestory.API.MathTools;
5using VSClientOptimizer.Config;
6using VSClientOptimizer.Math;
7using VSClientOptimizer.Interpolation;
8
9namespace VSClientOptimizer.Performance
10{
11 /// <summary>
12 /// Frame Generation - Creates intermediate frames between real frames for smoother motion
13 /// Similar to AMD FSR Frame Generation or NVIDIA DLSS 3 Frame Generation
14 /// </summary>
15 public class FrameGenerator
16 {
17 private Queue<FrameSnapshot> frameHistory = new Queue<FrameSnapshot>();
18 private const int MaxFrameHistory = 3;
19 private float generationMultiplier = 2.0f;
20 private bool useMotionVectors = true;
21
22 public class FrameSnapshot
23 {
24 public long TimestampMs;
25 public Dictionary<long, EntityPositionSnapshot> EntityStates;
26
27 public FrameSnapshot(long timestamp)
28 {
29 TimestampMs = timestamp;
30 EntityStates = new Dictionary<long, EntityPositionSnapshot>();
31 }
32}
33
34 public FrameGenerator(float multiplier, bool useMotion)
35 {
36 generationMultiplier = System.Math.Max(1.0f, System.Math.Min(4.0f, multiplier)); // Clamp 1-4x
37 useMotionVectors = useMotion;
38 }
39
40 public void AddFrame(long timestamp, Dictionary<long, EntityPositionSnapshot> states)
41 {
42 var snapshot = new FrameSnapshot(timestamp);
43 foreach (var kvp in states)
44 {
45 snapshot.EntityStates[kvp.Key] = kvp.Value;
46 }
47
48 frameHistory.Enqueue(snapshot);
49 if (frameHistory.Count > MaxFrameHistory)
50 frameHistory.Dequeue();
51 }
52
53 public List<FrameSnapshot> GenerateIntermediateFrames()
54 {
55 var generatedFrames = new List<FrameSnapshot>();
56
57if (frameHistory.Count < 2 || generationMultiplier <= 1.0f)
58 return generatedFrames;
59
60 var frames = frameHistory.ToArray();
61 var lastFrame = frames[frames.Length - 2];
62 var currentFrame = frames[frames.Length - 1];
63
64 long timeDiff = currentFrame.TimestampMs - lastFrame.TimestampMs;
65 if (timeDiff <= 0) return generatedFrames;
66
67 // Generate intermediate frames
68 int intermediateCount = (int)(generationMultiplier - 1);
69 for (int i = 1; i <= intermediateCount; i++)
70 {
71 float t = i / generationMultiplier;
72 long interpTime = lastFrame.TimestampMs + (long)(timeDiff * t);
73
74 var interpFrame = new FrameSnapshot(interpTime);
75
76 // Interpolate each entity's state
77 foreach (var entityId in lastFrame.EntityStates.Keys)
78 {
79 if (currentFrame.EntityStates.TryGetValue(entityId, out var currentState) &&
80 lastFrame.EntityStates.TryGetValue(entityId, out var lastState))
81 {
82 var interpState = InterpolateEntityState(lastState, currentState, t);
83 interpFrame.EntityStates[entityId] = interpState;
84 }
85 }
86
87 generatedFrames.Add(interpFrame);
88 }
89
90 return generatedFrames;
91 }
92
93 private EntityPositionSnapshot InterpolateEntityState(
94 EntityPositionSnapshot from,
95 EntityPositionSnapshot to,
96 float t)
97 {
98 // Position interpolation
99 Vector3 fromPos = new Vector3(from.Position.X, from.Position.Y, from.Position.Z);
100 Vector3 toPos = new Vector3(to.Position.X, to.Position.Y, to.Position.Z);
101
102 Vector3 interpPos;
103 if (useMotionVectors && (from.Velocity.X != 0 || from.Velocity.Y != 0 || from.Velocity.Z != 0))
104 {
105 // Use motion vectors for smoother interpolation
106 double deltaTime = (to.TimestampMs - from.TimestampMs) / 1000.0;
107 Vector3 motionPredicted = fromPos + (from.Velocity * (deltaTime * t));
108 interpPos = Vector3.Lerp(Vector3.Lerp(fromPos, toPos, t), motionPredicted, 0.3f);
109 }
110 else
111 {
112 interpPos = Vector3.Lerp(fromPos, toPos, t);
113 }
114
115 // Rotation interpolation
116 Rotation3 fromRot = new Rotation3(from.Rotation.X, from.Rotation.Y, from.Rotation.Z);
117 Rotation3 toRot = new Rotation3(to.Rotation.X, to.Rotation.Y, to.Rotation.Z);
118 Rotation3 interpRot = Rotation3.Lerp(fromRot, toRot, t);
119
120 // Velocity interpolation
121 Vector3 interpVel = Vector3.Lerp(from.Velocity, to.Velocity, t);
122
123 long interpTime = from.TimestampMs + (long)((to.TimestampMs - from.TimestampMs) * t);
124
125return new EntityPositionSnapshot(
126 new Vec3d(interpPos.X, interpPos.Y, interpPos.Z),
127 new Vec3f(interpRot.Pitch, interpRot.Yaw, interpRot.Roll),
128 interpTime,
129 interpVel
130 );
131 }
132 }
133}
134