2016-12-03 3 views
0

Ich versuche, einen Spline mit mehreren Dauern zu machen. Grundsätzlich möchte ich einen Spline erstellen, der durch benutzerdefinierte Keyframes generiert wird. Es kann mehrere Schlüsselbilder mit unterschiedlicher Dauer geben. Also frage ich, wie würde ich eine solche mit unterschiedlichen Geschwindigkeiten durch verschiedene Schlüsselrahmen reisen. Nehmen wir an, ich möchte, dass zwischen Keyframe A und B 1 Sekunde liegt, aber zwischen B und C 5 Sekunden. Ähnlich wie Animations-Editoren wie Source Filmmaker oder Autodesk Maya. Jedes Mal wenn ich gesehen habe, dass jemand einen Spline macht, hat er immer eine konstante Geschwindigkeit. Immer X Sekunden zwischen Schlüsselbildern, aber das ist nicht, wie Animationseditoren arbeiten, da sie unterschiedliche Geschwindigkeiten haben, das ist was ich will.Spline mit mehreren Dauern

Nur um zu bemerken, ich habe es versucht. Ich habe die Dauer geändert, sobald es zu einem anderen Keyframe kommt, aber das verlangsamt es sofort, wie bei einem Slow Motion Movie-Effekt, was ich nicht suche. Übertrage ich die Geschwindigkeit graduell auf die des nächsten Keyframes? Gibt es nur eine Gleichung?

function smooth(points, steps) --points is an array, steps is how many frames inbetween spline points 

if #points < 3 then 
    return points 
end 

local steps = steps or 5 

local spline = {} 
local count = #points - 1 
local p0, p1, p2, p3, x, y, z 

for i = 1, count do 

    if i == 1 then 
     p0, p1, p2, p3 = points[i], points[i], points[i + 1], points[i + 2] 
    elseif i == count then 
     p0, p1, p2, p3 = points[#points - 2], points[#points - 1], points[#points], points[#points] 
    else 
     p0, p1, p2, p3 = points[i - 1], points[i], points[i + 1], points[i + 2] 
    end 

    for t = 0, 1, 1/steps do 

     -- Main spline equation 
     x = 1 * ((2 * p1.x) + (p2.x - p0.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t * t + (3 * p1.x - p0.x - 3 * p2.x + p3.x) * t * t * t) 
     y = 1 * ((2 * p1.y) + (p2.y - p0.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t * t + (3 * p1.y - p0.y - 3 * p2.y + p3.y) * t * t * t) 
     z = 1 * ((2 * p1.z) + (p2.z - p0.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * t * t + (3 * p1.z - p0.z - 3 * p2.z + p3.z) * t * t * t) 
     if not(#spline > 0 and spline[#spline].x == x and spline[#spline].y == y and spline[#spline].z == z) then 
      table.insert(spline , { x = x , y = y, z = z })    
     end 

    end 

end 

return spline 

end 
+0

Können Sie das näher erläutern? – TheRoomDiedWithIt

+0

(Sorry für die Verzögerungen, keine wirklich günstige Zeit) Ich benutze Lua, aber diese Frage ist nicht so sprachspezifisch. Ich möchte nur wissen, wie es geht. Wie übertrage ich die Geschwindigkeit? Gibt es eine Gleichung, die die Geschwindigkeit löst? – TheRoomDiedWithIt

+0

(Späte Antwort, Bewegung ist beunruhigend) Nun, ich habe Probleme zu verstehen, was du meinst, kannst du vielleicht deine Antwort als Antwort anstatt als Kommentar posten und ausführlicher machen? – TheRoomDiedWithIt

Antwort

0

geradliniger Ansatz verwendet:

local zero_vector = {0, 0, 0} 

local function get_slope(is_edge, left, right) 
    if is_edge then 
     return zero_vector 
    else 
     local t = right.time - left.time 
     assert(t > 0, "Non-increasing time sequence") 
     return {(right[1] - left[1])/t, 
       (right[2] - left[2])/t, 
       (right[3] - left[3])/t} 
    end 
end 

function smooth(checkpoints, frames_per_second) 
    frames_per_second = frames_per_second or 5 
    if #checkpoints < 2 then 
     return checkpoints 
    end 
    -- Prepare formulas for each segment of spline 
    local formulas = {} 
    for segment = 1, #checkpoints - 1 do 
     local left = checkpoints[segment] 
     local right = checkpoints[segment + 1] 
     local t = right.time - left.time 
     assert(t > 0, "Non-increasing time sequence") 
     local left_deriv = get_slope(segment == 1, 
     checkpoints[segment - 1], right) 
     local right_deriv = get_slope(segment == #checkpoints - 1, 
     left, checkpoints[segment + 2]) 
     formulas[segment] = {} 
     for j = 1, 3 do 
     local d = left[j] 
     local c = left_deriv[j] 
     local a = (right[j] - d - c*t)/(t*t) 
     local b = 3*a + (c - right_deriv[j])/t 
     formulas[segment][j] = {(a - b)/t, b, c, d} 
     end 
    end 
    -- Calculate spline points 
    local total_seconds = checkpoints[#checkpoints].time - checkpoints[1].time 
    local segment = 1 
    local spline = {} 
    for frame_no = 0, total_seconds * frames_per_second do 
     local t = checkpoints[1].time + frame_no/frames_per_second 
     local point = {time = t} 
     while segment < #formulas and t > checkpoints[segment + 1].time do 
     segment = segment + 1 
     end 
     t = t - checkpoints[segment].time 
     for j = 1, 3 do 
     local c = formulas[segment][j] 
     point[j] = ((c[1]*t + c[2])*t + c[3])*t + c[4] 
     end 
     table.insert(spline, point) 
    end 
    return spline 
end 

Anwendungsbeispiel:

--      x y z "timestamp in seconds" 
local checkpoint_A = {11, 12, 13, time = 0} 
local checkpoint_B = {21, 15, 18, time = 1} -- 1 second between A and B 
local checkpoint_C = {13, 24, 20, time = 6} -- 5 seconds between B and C 

local checkpoints = {checkpoint_A, checkpoint_B, checkpoint_C} 

-- total duration is 6 seconds, 10 frames per second, 61 points returned 
local array_of_61_points = smooth(checkpoints, 10) 

for _, point in ipairs(array_of_61_points) do 
    print(string.format("time = %.1f, x = %.3f, y = %.3f, z = %.3f", 
     point.time, point[1], point[2], point[3])) 
end