[OpenGL] Animacja ruchu belki lokomotywy

[OpenGL] Animacja ruchu belki lokomotywy
SA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 7 lat
  • Postów:25
0

Witam !
Na wszelki wypadek, chciałbym przeprosić, jeśli temat umieściłem w nie tym dziale co trzeba, ale nie znalazłem kategorii odnośnie grafiki komputerowej.
Przedstawiając mój problem, to mam zrobić animację w OpenGl przedstawiającą podwozie lokomotywy, które z geometrycznej perspektywy, składa się 1 głównego prostopadłościanu, 4 walców reprezentujących koła oraz 2 poruszających się belek w postaci prostopadłościanów. Generalnie największy problem mam właśnie z ruchem belki, która ma wykonywać charakterystyczną "ósemkę" (proszę nie patrzeć na sens fizyczny tego ruchu ;) ) - tzn. że gdy belka na jednym kole jest "na dole", to na drugim jest "na górze" i dwa końce belki zataczają kółka w dwie różne strony. Do rozwiązania swojego problemu postanowiłem po prostu zrobić przede wszystkim na belce transformacje przesunięcia, aby belka przesuwała się, robiąc końcami kółka, a za odpowiednie pochylenie belki miała posłużyć rotacja wokół osi naszej belki. I tutaj mam problem, że środek ciężkości mojej belki też się przesuwa i wektor określający oś wokół, której kręci się belka także się zmienia.

Jeszcze co do szczegółów - środek ciężkości znajduje się w punkcie (1.0f, 0.2f, 0.0f) po przesunięciu belki w odpowiednie miejsce. W ogóle to mam powoli dylemat, czy na początku powinienem dokonać translacji, czy rotacji (jakby co wiem, że to co wstawie w kodzie później, zrobi się szybciej, bo...macierze :) ).

Więc podsumowując uważam, że ruch "ósemkowy" powinien zostać osiągnięty poprzez prawidłowe złożenie dwóch ruchów:

  1. Ruch postępujący belki
Kopiuj
 // Belka porusza się w płaszczyźnie określonej przez współrzędne y i z.
 GLfloat y = -0.2f + 0.15f * glm::cos((GLfloat)glfwGetTime() * glm::radians(-60.0f)); // -0.2f żeby krążyło wokół środka koła, 0.15f - promień
 GLfloat z = 0.15f * glm::sin((GLfloat)glfwGetTime() * glm::radians(-60.0f));
 model = glm::translate(model, glm::vec3(0.0f, y, z));
  1. Ruch powodujący odpowiednie nachylenie belki (rotacja):
Kopiuj
 angle = 0.1f * glm::asin(sin((GLfloat)glfwGetTime() * glm::radians(-60.0f))); // ograniczony kąt obrotu
 model = glm::rotate(model, angle, glm::vec3(1.0f, 0.2f, 0.0f)); // bez ruchu postępującego to powoduje takie "wahanie" belki

Próbowałem już wiele kombinacji złożenia tego ruchu, ale nadal mam problem jak uwzględnić, że współrzędne y i z naszego środka ciężkości belki się zmieniają. Z góry dziękuje za wszelkie podpowiedzi.

edytowany 3x, ostatnio: Sarnapa
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 22 godziny
1

Animacja ruchu belki lokomotywy

Ta „belka” nazywa się wiązar (łącząca koła ze sobą) i korbowód (łącząca tłok z wiązarem).

gdy belka na jednym kole jest "na dole", to na drugim jest "na górze"

Nie ma czegoś takiego. Jak by to miało jeździć? ;-)

edytowany 1x, ostatnio: Azarien
SA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 7 lat
  • Postów:25
0

Znaczy... Takie samo pytanie zadałem prowadzącemu projekt... A on odparł, że tu nie liczy się fizyka, tylko sobie taki ruch wymyślił, żeby utrudnić zadanie :)

xxx_xx_x
  • Rejestracja:prawie 13 lat
  • Ostatnio:13 dni
  • Postów:365
1

Najprościej to

  1. Wyznaczyć punkt A i B, gdzie A to początek belki B jej koniec. Czyli dwa niezależne ruchy po okręgu.
  2. Wyznaczyć belkę na wektorze A i B, potrzebny do tego będzie wektor prostopadły do wektora AB.
    Jeżeli dobrze rozumiem założenia to belka powinna zmieniać swoją długość?
SA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 7 lat
  • Postów:25
0

Znaczy nie zakładałem wstępnie, aby zmieniać długość belki, nawet o tym nie pomyślałem, ale po licznych próbach wydaje mi się że chyba to nieuniknione. A mógłbyś bardziej wyjaśnić swój pomysł ?

edytowany 2x, ostatnio: Sarnapa
SC
  • Rejestracja:prawie 10 lat
  • Ostatnio:prawie 8 lat
  • Postów:18
1

Ja bym zrobił tak:

  1. 2 belki A i B,
  2. Ustawiam punkt ciężkości(pivot) belek na jeden z końców,
  3. Rotuje każdą z belek tak by była pochylona o kąt między nią a punktem na drugim kole
  4. Przesuwam każdą z belek na odpowiednie koło,

po takim czymś belki powinny nachodzić na siebie równolegle i wyglądać to powinno jak tłok.

xxx_xx_x
  • Rejestracja:prawie 13 lat
  • Ostatnio:13 dni
  • Postów:365
1

Problem sprowadza się do 2D więc, powiedzmy że masz koło o środku S(y, z) i promieniu R, oraz kąt obrotu T(w radianach). Wartość T posłuży do wyznaczenia punktu zaczepienia belki.
A.y = S.y + R * sin(T);
A.z = S.z + R * cos(T);
Zwiększanie T spowoduje przemieszczanie się punktu A po okręgu.
Analogicznie postępujemy z punktem B, różnica jest taka że T będziesz zmniejszać zamiast zwiększać (zmieni się kierunek obrotu).

Mamy już początek i koniec belki, potrzebujemy teraz nadać "grubość" belce czyli rozciągnąć ją w dwóch kierunkach prostopadłych do wektora AB. Wektor AB nazwijmy V, wektor prostopadły VP.
V normalizujemy (obliczamy jego długość i dzielimy każdą współrzędną przez tę wartość).
VP można wyznaczyć za pomocą iloczynu wektorowego. Ponieważ interesuje nas płaszczyzna YZ, użyjemy do tego wektora X(1,0,0)

Po przekształceniu VP:
VP.x = 0;
VP.y = V.z;
VP.z = -V.y;

Teraz chcemy żeby belka miała grubość L. Wyznaczamy 4 punkty (narożniki belki)

P0 = A + 0.5 * VP * L;
P1 = B + 0.5 * VP * L;
P2 = B - 0.5 * VP * L;
P3 = A - 0.5 * VP * L;

Teraz rysujesz prostokąt (P0, P1, P2, P3), lub dwa trójkąty : (P0, P1, P2), (P0, P2, P3)

SA
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 7 lat
  • Postów:25
0

Właśnie robiłem z dwoma belkami, ale mam nałożoną teksturę na belkę i słabo to wygląda...Wykombinowałem jednak coś innego, ale idealnie nie jest. Generalnie wykombinowałem sobie po prostu, że nachylenie belki będę osiągać poprzez obrót wokół jednego końca belki w płaszczyźnie określonej przez współrzędne x i y. Ruch "postępujący: dający nam okrążanie środka kół zachowany. Asin do ograniczenia kąta nachylenia. I było w miarę git, ale niestety po stronie drugiego końca belki, jej ruch jest za bardzo "skokowy", nie tak płynny jak przy końcu belki, wokół którego następował obrót. Czym to może być spowodowane ?
Kod:

Kopiuj
glm::mat4 model4;
GLfloat angle = (GLfloat)glfwGetTime() * glm::radians(-45.0f); // kat do obrysowania kola
GLfloat deltaY = 0.15f * glm::cos(angle); // przemieszczenie
GLfloat y = -0.2f + deltaY;
GLfloat z = 0.15f * glm::sin(angle);
GLfloat angle2 = 0.05f * glm::asin(sin(angle)); // kat nachylenia
model4 = glm::translate(model4, glm::vec3(i * (-2.0f), 0.2f, 0.0f));
model4 = glm::translate(model4, glm::vec3(0.0f, y, z));
model4 = glm::translate(model4, glm::vec3(0.0f, 1.5f, 0.0f));
model4 = glm::rotate(model4, angle2, glm::vec3(1.0f, 0.0f, 0.0f));
model4 = glm::translate(model4, glm::vec3(0.0f, -1.5f, 0.0f)); 

EDIT:

Nie zauwazyłem rozwiązania @xxx_xx_x, którym postaram się zainspirować (i oczywiście bardzo za nie dziękuje), ale jakby ktoś wiedział co jest nie tak z kodem powyżej, to bym prosił o uwagi.

edytowany 4x, ostatnio: Sarnapa
xxx_xx_x
glm::asin(sin(angle)) - czy to przypadkiem nie jest po prostu angle?
xxx_xx_x
Zrobiłem aplikację w 2d testującą moje rozwiązanie i na pewno działa :)
SA
oj... poprawilem z rozpędu, a było dobrze... Nie do końca bo asin zwraca od -pi/2 do pi/2 a angle moze byc wiekszy... w ten sposob uzyskalem ograniczenie kąta nachylenia belki
xxx_xx_x
asin jest dość kosztowną metodą jak każda metoda trygonometryczna, można skorzystać z cykliczności sin i łatwo przyciąć wartości do przedziału -pi/2 ; pi/2
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)