Interpolation "zu schnell"

  • C++

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Interpolation "zu schnell"

    Hi,
    Ich implementier grad für ein Spiel eine MD2-Loader-Klasse und dafür eine Funktion die aus einer Zeitangabe eine Frame einer Animation interpoliert.
    Bis jetzt läuft das so ab dass der Funktion die Zeit seit Animationsbeginn in Sekunden als float übergeben und diese daraus die vorherige, in Vertices vorhandene und die darauf folgende Frame errechnet und dann die neue Frame interpoliert.
    Eigentlich funktioniert auch fast alles, aber irgendwie läuft das ganze "zu schnell".
    d.H. wenn ich als Parameter 1.3f übergebe ist die Animation bei ca. 2.9f Sekunden.
    Kann leider keinen fehler entdecken,
    also hier mal der Code:

    PHP-Quellcode

    1. bool CMD2Loader::SetTime(float fTime){
    2. float fIntp;
    3. int nPrevFrame, nNextFrame;
    4. char cBuffer[1024];
    5. sprintf(cBuffer, "%f", fTime);
    6. if(fTime <= 0.0f){
    7. for(int i = 0; i < m_pHeader->m_iNumVertices; i++){
    8. m_pVertices[i].m_fVertex[0] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameFirst].m_pVertices[i].m_fVertex[0];
    9. m_pVertices[i].m_fVertex[1] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameFirst].m_pVertices[i].m_fVertex[1];
    10. m_pVertices[i].m_fVertex[2] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameFirst].m_pVertices[i].m_fVertex[2];
    11. }
    12. }
    13. else if(fTime >= (md2AnimList->m_nFrameLast - md2AnimList->m_nFrameFirst) / md2AnimList->m_nFPS){
    14. for(int i = 0; i < m_pHeader->m_iNumVertices; i++){
    15. m_pVertices[i].m_fVertex[0] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameLast].m_pVertices[i].m_fVertex[0];
    16. m_pVertices[i].m_fVertex[1] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameLast].m_pVertices[i].m_fVertex[1];
    17. m_pVertices[i].m_fVertex[2] = m_pFrames[md2AnimList[m_nCurrAnim].m_nFrameLast].m_pVertices[i].m_fVertex[2];
    18. }
    19. }
    20. else{
    21. _control87(_RC_DOWN, _MCW_RC);
    22. fIntp = md2AnimList[m_nCurrAnim].m_nFrameFirst + (fTime * md2AnimList[m_nCurrAnim].m_nFPS);
    23. _asm{
    24. fld fIntp;
    25. fistp nPrevFrame;
    26. }
    27. fIntp = ((fTime * md2AnimList[m_nCurrAnim].m_nFPS) + md2AnimList[m_nCurrAnim].m_nFrameFirst) - nPrevFrame; //fmod(fTime * md2AnimList[m_nCurrAnim].m_nFPS, 1.0f);
    28. nNextFrame = nPrevFrame + 1;
    29. //sprintf(cBuffer, "%i %i %f %f %f %f", nPrevFrame, nNextFrame, fIntp, fTime, fTime * md2AnimList[m_nCurrAnim].m_nFPS, fTime * md2AnimList[m_nCurrAnim].m_nFPS - fIntp);
    30. for(int i = 0; i < m_pHeader->m_iNumVertices; i++){
    31. m_pVertices[i].m_fVertex[0] = m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[0] + ((m_pFrames[nNextFrame].m_pVertices[i].m_fVertex[0] - m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[0]) * fIntp);
    32. m_pVertices[i].m_fVertex[1] = m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[1] + ((m_pFrames[nNextFrame].m_pVertices[i].m_fVertex[1] - m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[1]) * fIntp);
    33. m_pVertices[i].m_fVertex[2] = m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[2] + ((m_pFrames[nNextFrame].m_pVertices[i].m_fVertex[2] - m_pFrames[nPrevFrame].m_pVertices[i].m_fVertex[2]) * fIntp);
    34. }
    35. }
    36. SetWindowText(hWnd, cBuffer);
    37. return 0;
    38. }
    Alles anzeigen

    md2AnimList ist ein statisches Array in dem die standard MD2 Animationen mit Anfangs-Frame, End-Frame und FPS gespeichert sind.
    m_pFrames ist ein Array sämtlicher im Model gespeicherten Frames.
    m_pVertices (wenn nicht member von m_pFrames) ist ein als public deklariertes Array der Vertices in dem die Interpolierten Frames gespeichert und nach außen erfügbar gemacht werden.
    fIntp "grad der Interpolation", also ein Wert von 0 wäre die Ausgangs-Frame und ein Wert von 1 wäre gleich der nächsten Frame.
    Ansonsten sollte der Code glaube ich selbsterklärend sein, falls etwas unklar ist bitte fragen.
    Schonmal danke im vorraus,
    mfg. Cobi
    (Dass das ganze noch arg optimierungs bedürftig ist ist mir klar)

    Ps. irgendwie behält der Code-Tag die formatierung nicht richtig bei :|
  • öh, ich bin zwar etwas verwirrt, wo nun genau das Problem liegt, aber ich versuch's mal.

    Du rufst also dieses Unterprogramm der Klasse CMD2Loader auf, übergibst als Parameter 1,3 Sekunden und bist aber eigentlich schon bei 2,9 Sekunden?

    Ich würde mal mit einem Profiler prüfen, wo dein Programm Zeit verbrät. Praktisch alle Compiler bringen solche Analysewerkzeuge mit. Eventuell machst du gar nichts falsch, sondern musst lediglich bestimmte Laufzeiten mit einkalkulieren. Da du mit mehrdimensinalen Arrays arbeitest, kann bei ungeschickten Operationen schon mal die ein oder andere Millisekunde verloren gehen.

    Der Code sieht jedenfalls OK aus.

    Grüße
    Michael
  • Das Problem ist dass die Animation zu weit interpoliert wird.
    d.H. wenn ich z.B. 1.3f übergeben wird die Frame an der Stelle 2.6f Sekunden Interpoliert.
    Also meine Berechnungen sind aus irgendeinem Grund falsch.

    [edit]
    OMG :boing:
    Sorry, problem hat sich erledigt.
    (Manchmal sieht man auch echt den Wald vor lauter Bäumen nicht)
    Ich hatte in der berechnung der Animations-Länge den Array-Index vergessen, somit wurden immer die Daten der ersten Animation verwendet. :depp:
    So funktionierts:
    (md2AnimList[m_nCurrAnim].m_nFrameLast - md2AnimList[m_nCurrAnim].m_nFrameFirst) / (float)md2AnimList[m_nCurrAnim].m_nFPS

    [edit2]
    Ähm, eine Frage hätte ich doch noch:
    Warum ist diese Struktur bitteschön 20 Bytes groß?

    Quellcode

    1. typedef struct STGAHeader{
    2. BYTE m_uIDSize;
    3. BYTE m_uColorMapType; // 0 = none, 1 = has palette
    4. BYTE m_uImageType; // 0 = none, 1 = indexed, 2 = rgb, 3 = grey, +8 = rle packed
    5. short m_sColorMapStart;
    6. short m_sColorMapLength;
    7. BYTE m_uColorMapBits;
    8. short m_sXStart;
    9. short m_sYStart;
    10. short m_sWidth;
    11. short m_sHeight;
    12. BYTE m_uBits;
    13. BYTE m_uDescriptor;
    14. } STGAHeader;
    Alles anzeigen


    Ich habe das x mal durchgerechnet und das ist einfach bullshit!
    Das müssen 18 Bytes sein, aber sizeof meint 20 :confused: