2011-09-09 6 views
12

मैं कोड में एनीमेशन प्रभाव का अनुकरण करने की कोशिश कर रहा हूं (लगभग कोई भी भाषा भाषा के बजाए गणित के रूप में दिखाई देगी)। अनिवार्य रूप से, यह एक द्रव्यमान वसंत प्रणाली का अनुकरण है। मैं डब्ल्यूपीएफ/सिल्वरलाइट की ElasticEase देख रहा हूं और यह जो कुछ मैं ढूंढ रहा हूं उसके करीब यह प्रतीत होता है, लेकिन काफी नहीं।स्प्रिंग-मास सिस्टम का डंपिंग प्रभाव (या यह लोचदार है?)

सबसे पहले, यहां मैं जो खोज रहा हूं - एक वस्तु, सेकंड की एक निश्चित संख्या यात्रा करना, एक स्थान मारना और तुरंत उसी समय आराम करने के लिए सेकंड की एक निश्चित संख्या के लिए ओसीसीलेट को धीमा करना जहां डंपिंग थी आवेदन किया है। तो इसे देखने के लिए, मान लें कि मेरे पास 600w/900h कैनवास है और मेरे पास एक वर्ग है जो TranslateTransform.Y में 900px से 150px तक एनिमेट करना शुरू कर देता है। 150 पीएक्स ऊंचाई (187.5 पीएक्स प्रति सेकेंड) तक पहुंचने में 4 सेकंड लगते हैं, जिस चरण में इसे तुरंत हटा दिया जाता है और केवल 0.4 सेकंड (87.5 पीएक्स प्रति सेकेंड) से 115 पीएक्स ऊंचाई तक 35px अधिक यात्रा करता है, फिर 1 सेकंड से 163 पीएक्स ऊंचाई तक (48 पीएक्स और 48 पीएक्स प्रति सेकेंड) और उसके बाद 146 पीएक्स (17 पीएक्स और 17 पीएक्स प्रति सेकेंड) तक वापस लौटता है और तब तक जब तक ऑसीलेशन इसे 150px की अंतिम विश्राम स्थान तक धीमा नहीं करता है। ऑसीलेशन अवधि 16 सेकंड है। , पिक्सेल दूरी और सेकंड की संख्या बिंदु A से बिंदु बी को पाने के लिए लेता है - enter image description here

यहाँ है कि मैं क्या पहले से पता होगा:

उदाहरण मैं ऊपर वर्णित शीर्ष छोड़ दिया यहाँ नीले आयत है ऑसीलेशन के लिए सेकंड की संख्या। द्रव्यमान जैसी चीजें कोई फर्क नहीं पड़ती हैं।

मैंने ElasticEase की कोशिश की है और यह मुद्दा यह प्रतीत होता है कि मैं 4 सेकंड के लिए कोई आसानता के साथ यात्रा करने के लिए ऑब्जेक्ट नहीं प्राप्त कर सकता और फिर अगले 16 सेकंड के लिए "बाउंस" नहीं कर सकता। .Springiness हमेशा बहुत ज़्यादा भी है, भले ही मैं के रूप में यह 20.

ILSpy शो के अपने कार्य की तरह एक बहुत उच्च संख्या के लिए सेट:

protected override double EaseInCore(double normalizedTime) 
     { 
      double num = Math.Max(0.0, (double)this.Oscillations); 
      double num2 = Math.Max(0.0, this.Springiness); 
      double num3; 
      if (DoubleUtil.IsZero(num2)) 
      { 
       num3 = normalizedTime; 
      } 
      else 
      { 
       num3 = (Math.Exp(num2 * normalizedTime) - 1.0)/(Math.Exp(num2) - 1.0); 
      } 
      return num3 * Math.Sin((6.2831853071795862 * num + 1.5707963267948966) * normalizedTime); 
     } 

मैं 2 वीडियो शामिल की है और और एक एक्सेल DropBox पर एक ज़िप फ़ोल्डर में फ़ाइल करें। मुझे लगता है कि यह प्रश्न काम में प्रगति का अधिक होगा क्योंकि लोग अधिक स्पष्ट प्रश्न पूछते हैं।

(अस्वीकरण: मैं नहीं पता है कि मैं क्या बारे में बात कर रहा हूँ जब यह इस चीज के बारे में ज्यादा बात आती है)

+0

आपकी समस्या एक गणित/भौतिकी है (जैसा कि आपको संदेह है)। यह मानक मानक भौतिकी पाठ्यक्रम है जो ऑसीलेशन समस्या को दबाता है, लेकिन इसमें पूरी तरह से व्याख्या करने के लिए कुछ सौ शब्द (और कुछ गणित सूत्र, जो SO में बहुत खराब प्रस्तुत करते हैं) लेते हैं। मूल समस्या यह है कि डंपिंग घातीय है, इसलिए जब आप इसे विघटित करते हैं, पूंछ के उत्सर्जन खो जाते हैं। क्या आप वाकई http://en.wikipedia.org/wiki/Damping के बजाय पूर्ण स्पष्टीकरण चाहते हैं? :) –

+0

धन्यवाद @belisarius। गणित/भौतिकी वास्तव में मेरे साथ परे है, विशेष रूप से ऊपर दिए गए नमूने पर विचार करने से द्रव्यमान को ध्यान में रखना प्रतीत नहीं होता है। कोई भी व्याख्या और/या कोड नमूने जो आप प्रदान कर सकते हैं जो मुझे इससे पहले कि मेरे पास ज्ञात चर के साथ शुरू करने में मदद कर सकता है, मेरे सामने सबसे उपयोगी होगा। –

+0

मैं कोशिश करूंगा, लेकिन जैसा कि मैंने पहले देखा है कि यह मुझे अच्छा करने में काफी समय लगेगा, शायद कुछ भौतिक विज्ञानी/छात्र एक बक्षीस का पीछा करते हुए मुझे उम्मीद कर सकते हैं :)। बीटीडब्लू, द्रव्यमान वहां है, लेकिन समस्या के सभी अन्य स्थिरांक (लोचदार निरंतर और नमी कोफ) द्रव्यमान द्वारा एक जन स्वतंत्र समस्या प्राप्त करने के लिए विभाजित होते हैं (क्योंकि एफएम * ए == 0 शून्य के बराबर है, आप विभाजित कर सकते हैं जो भी स्थिर आप चाहते हैं सभी शर्तें)। एफ दो ताकतों, लोचदार, लोचदार स्थिर के और आनुपातिक, और धुंधला बल, वेग के अनुपात के समान आनुपातिक और एक धुंधला स्थिरता की संरचना है। –

उत्तर

8

भौतिकी छोड़ दें और बस समीकरण सीधे जाकर।

मापदंडों: "यहाँ मैं क्या पहले से पता होगा - पिक्सेल दूरी [D] और सेकंड की संख्या [T0] यह बिंदु A से बिंदु बी को पाने के लिए ले जाता है, दोलन के लिए सेकंड की संख्या [टी 1 ]। "इसके अलावा, मैं मुक्त पैरामीटर के रूप में जोड़ दूंगा: अधिकतम आकार, अमेक्स, डंपिंग टाइम निरंतर, टीसी, और एक फ्रेम दर, आरएफ, जो कि किसी भी समय एक नया स्थिति मान चाहता है। मुझे लगता है कि आप इस हमेशा के लिए गणना करने के लिए नहीं करना चाहते, तो मैं बस 10 सेकंड, Ttotal प्रयास करेंगे, लेकिन वहाँ उचित रोक स्थिति की एक किस्म ...

कोड हैं: अजगर में कोड यह ()।

from numpy import pi, arange, sin, exp 

Ystart, D = 900., 900.-150. # all time units in seconds, distance in pixels, Rf in frames/second 
T0, T1, Tc, Amax, Rf, Ttotal = 5., 2., 2., 90., 30., 10. 

A0 = Amax*(D/T0)*(4./(900-150)) # basically a momentum... scales the size of the oscillation with the speed 

def Y(t): 
    if t<T0: # linear part 
     y = Ystart-(D/T0)*t 
    else: # decaying oscillations 
     y = Ystart-D-A0*sin((2*pi/T1)*(t-T0))*exp(-abs(T0-t)/Tc) 
    return y 

y_result = [] 
for t in arange(0, Ttotal, 1./Rf): # or one could do "for i in range(int(Ttotal*Rf))" to stick with ints  
    y = Y(t) 
    y_result.append(y) 

विचार बिंदु तक रेखीय गति, एक खस्ताहाल दोलन द्वारा पीछा किया है: मुख्य बात समीकरण, def Y(t) में पाया। sin और exp द्वारा इसे गुणा करके क्षय प्रदान किया जाता है। बेशक, किसी भी दूरी, आवेश आकार, आदि प्राप्त करने के लिए पैरामीटर बदलें, जो आप चाहते हैं।

enter image description here

नोटों:

टिप्पणी में
  1. अधिकांश लोगों को भौतिकी दृष्टिकोण सुझाव दे रहे हैं। मैंने इनका उपयोग नहीं किया क्योंकि अगर कोई एक निश्चित गति निर्दिष्ट करता है, तो यह भौतिक विज्ञान से शुरू करने के लिए थोड़ा अधिक कर रहा है, अंतर समीकरणों पर जाएं, और फिर गति की गणना करें, और अंतिम चीज़ प्राप्त करने के लिए पैरामीटर को ट्विक करें । साथ ही साथ अंतिम चीज़ पर भी जा सकते हैं। जब तक कि, किसी के पास भौतिकी के लिए अंतर्ज्ञान नहीं है कि वे काम करना चाहते हैं।
  2. अक्सर इस तरह की समस्याओं में निरंतर गति (पहला व्युत्पन्न) रखना चाहता है, लेकिन आप कहते हैं "तुरंत धीमा हो जाता है", इसलिए मैंने इसे यहां नहीं किया।
  3. ध्यान दें कि धुंधलापन की अवधि और आयाम सटीक रूप से निर्दिष्ट नहीं किया जाएगा जब नमी लागू होती है, लेकिन यह शायद आपकी देखभाल करने से अधिक विस्तृत है।
  4. यदि आपको इसे एक समीकरण के रूप में व्यक्त करने की आवश्यकता है, तो आप योगदान को चालू और बंद करने के लिए "हेवीसाइड फ़ंक्शन" का उपयोग करके ऐसा कर सकते हैं।

इस बहुत लंबा बनाने के जोखिम पर, मुझे एहसास हुआ कि मैं GIMP में एक gif कर सकता है, तो यह हैं कि यह दिखता है:

enter image description here

मैं बनाने के लिए पूर्ण कोड पोस्ट कर सकते हैं यदि रुचि है तो प्लॉट्स, लेकिन मूल रूप से मैं प्रत्येक टाइमस्टेप के लिए वाई को अलग-अलग डी और टी 0 मानों के साथ बुला रहा हूं। अगर मैं इसे फिर से करना चाहता था, तो मैं डंपिंग बढ़ा सकता था (यानी, टीसी घटाना), लेकिन यह थोड़ा परेशानी है इसलिए मैं इसे छोड़ रहा हूं।

+0

सहमत हैं, आपको वास्तव में द्रव्यमान की आवश्यकता नहीं है। गति और त्वरण होने के पर्याप्त है। एक वसंत ग्राफ लेआउट करते समय पता चला। बेवकूफ तरीका गति, द्रव्यमान, बल इत्यादि के साथ पूर्ण भौतिक सिमुलेशन करना होगा। फिर पता चला है कि आप कष्टप्रद दुष्प्रभावों के साथ केवल दोहरे काम कर रहे हैं। – gjvdkamp

+0

क्या एक शानदार स्पष्टीकरण !! धन्यवाद! मैं अगले दिन या दो में यह देखने के लिए काम कर रहा हूं कि मैं इसे काम पर ला सकता हूं या नहीं। –

+0

@ ओटाकू लगता है कि डी पर व्युत्पन्न निरंतर नहीं है। जब आप शरीर को पहली बार आराम की स्थिति तक पहुंचते हैं तो आप अचानक वेग बदल सकते हैं –

5

मैं @ tom10 के समान ही सोच रहा था। (मैंने IEasingFunction भी माना जो IList<IEasingFunction> ले लिया, लेकिन मौजूदा लोगों में से वांछित व्यवहार को हैक करना मुश्किल होगा)।

// Based on the example at 
// http://msdn.microsoft.com/en-us/library/system.windows.media.animation.easingfunctionbase.aspx 
namespace Org.CheddarMonk 
{ 
    public class OtakuEasingFunction : EasingFunctionBase 
    { 
     // The time proportion at which the cutoff from linear movement to 
     // bounce occurs. E.g. for a 4 second movement followed by a 16 
     // second bounce this would be 4/(4 + 16) = 0.2. 
     private double _CutoffPoint; 
     public double CutoffPoint { 
      get { return _CutoffPoint; } 
      set { 
       if (value <= 0 || value => 1 || double.IsNaN(value)) { 
        throw new ArgumentException(); 
       } 
       _CutoffPoint = value; 
      } 
     } 

     // The size of the initial bounce envelope, as a proportion of the 
     // animation distance. E.g. if the animation moves from 900 to 150 
     // and you want the maximum bounce to be no more than 35 you would 
     // set this to 35/(900 - 150) ~= 0.0467. 
     private double _EnvelopeHeight; 
     public double EnvelopeHeight { 
      get { return _EnvelopeHeight; } 
      set { 
       if (value <= 0 || double.IsNaN(value)) { 
        throw new ArgumentException(); 
       } 
       _EnvelopeHeight = value; 
      } 
     } 

     // A parameter controlling how fast the bounce height should decay. 
     // The higher the decay, the sooner the bounce becomes negligible. 
     private double _EnvelopeDecay; 
     public double EnvelopeDecay { 
      get { return _EnvelopeDecay; } 
      set { 
       if (value <= 0 || double.IsNaN(value)) { 
        throw new ArgumentException(); 
       } 
       _EnvelopeDecay = value; 
      } 
     } 

     // The number of half-bounces. 
     private int _Oscillations; 
     public int Oscillations { 
      get { return _Oscillations; } 
      set { 
       if (value <= 0) { 
        throw new ArgumentException(); 
       } 
       _Oscillations = value; 
      } 
     } 

     public OtakuEasingFunction() { 
      // Sensible default values. 
      CutoffPoint = 0.7; 
      EnvelopeHeight = 0.3; 
      EnvelopeDecay = 1; 
      Oscillations = 3; 
     } 

     protected override double EaseInCore(double normalizedTime) { 
      // If we get an out-of-bounds value, be nice. 
      if (normalizedTime < 0) return 0; 
      if (normalizedTime > 1) return 1; 

      if (normalizedTime < _CutoffPoint) { 
       return normalizedTime/_CutoffPoint; 
      } 

      // Renormalise the time. 
      double t = (normalizedTime - _CutoffPoint)/(1 - _CutoffPoint); 
      double envelope = EnvelopeHeight * Math.Exp(-t * EnvelopeDecay); 
      double bounce = Math.Sin(t * Oscillations * Math.PI); 
      return envelope * bounce; 
     } 

     protected override Freezable CreateInstanceCore() { 
      return new OtakuEasingFunction(); 
     } 
    } 
} 

यह अनचाहे कोड है, लेकिन यदि समस्याएं हैं तो इसे डीबग करना बहुत बुरा नहीं होना चाहिए। मुझे यकीन नहीं है कि एक्सएएमएल संपादक के गुणों में उन्हें सही तरीके से संभालने के लिए क्या गुण (यदि कोई है) को जोड़ा जाना चाहिए।

+0

वाह पीटर! ये अद्भुत है! मैं इसे अगले दिन या दो में कोशिश कर रहा हूं और आपको बता दूंगा। –

+0

पीटर, जो आपने प्रदान किया है वह महान है, उतना ही टॉम के जितना अच्छा है। मैं इस पर एक और बक्षीस खोलूंगा और आपको 2 दिनों के समय में अंक भी दूंगा। –

संबंधित मुद्दे