Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming

Simuleer Tearable Cloth en Ragdolls met Simple Verlet-integratie

by
Difficulty:IntermediateLength:LongLanguages:

Dutch (Nederlands) translation by Adjatay Bashroh Aldad (you can also view the original English article)

Soft body dynamics gaat over het simuleren van realistische vervormbare objecten. We zullen het hier gebruiken om een ​​uitneembare stoffen gordijn en een set ragdolls te simuleren waarmee je kunt communiceren en over het scherm kunt glijden. Het zal snel, stabiel en eenvoudig genoeg zijn om te doen met wiskunde op het middelbare schoolniveau.

Opmerking: hoewel deze tutorial is geschreven in Processing en gecompileerd met Java, zou u in bijna elke game-ontwikkelomgeving dezelfde technieken en concepten moeten kunnen gebruiken.


Eindresultaat Voorbeeld

In deze demo kun je een groot gordijn zien (waarop de stoffen simulatie te zien is) en een aantal kleine stickmen (die de ragdoll-simulatie laten zien):

Je kunt de demo ook zelf proberen. Klik en sleep om te communiceren, druk op "R" om te resetten en druk op "G" om de zwaartekracht in te stellen.


Stap 1: Een Punt en Zijn Beweging

De bouwstenen van ons spel met de Point. Om dubbelzinnigheid te voorkomen, noemen we het de PointMass. De details staan ​​in de naam: het is een punt in de ruimte en het vertegenwoordigt een hoeveelheid massa.

De meest eenvoudige manier om fysica voor dit punt te implementeren, is om zijn snelheid op de een of andere manier "vooruit te sturen".


Stap 2: Timesteps

We kunnen niet aannemen dat onze game de hele tijd op dezelfde snelheid draait. Het kan voor sommige gebruikers 15 frames per seconde zijn, bij 60 voor anderen. Het is het beste om rekening te houden met framesnelheden van alle bereiken, wat kan worden gedaan met behulp van een tijdspanne.

Op deze manier zou het spel nog steeds op dezelfde snelheid draaien als een frame langer zou duren voordat het voor één persoon dan voor een ander zou zijn. Voor een physics-engine is dit echter ongelooflijk onstabiel.

Stel je voor dat je spel een seconde of twee vastloopt. De motor zou daarover compenseren en de PointMass langs meerdere wanden en objecten bewegen waar anders een botsing mee zou zijn gedetecteerd. Dus, niet alleen zou botsing detectie worden beïnvloed, maar ook de methode van constraint oplossen die we zullen gebruiken.

Hoe kunnen we de stabiliteit van de eerste vergelijking, x = x + velx, met de consistentie van de tweede vergelijking, x = x + velX * tijd opgevouwen? Wat als we de twee misschien zouden kunnen combineren?

Dat is precies wat we zullen doen. Stel je voor dat onze tijdElapsed 30 was. We zouden precies hetzelfde kunnen doen als de laatste vergelijking, maar met een hogere nauwkeurigheid en resolutie, door x = x + (velx * 5) zes keer te noemen.

Het algoritme gebruikt hier een vaste tijdzone die groter is dan één. Het vindt de verstreken tijd, verdeelt het in "brokken" van vaste grootte en duwt de resterende hoeveelheid tijd over naar het volgende frame. We voeren de simulatie beetje bij beetje uit voor elk deel waarin onze verstreken tijd wordt opgesplitst.

Ik koos 16 voor de tijdspanne, om de natuurkunde te simuleren alsof het ongeveer 60 frames per seconde was. Conversie van verstreken tijd naar frames per seconde kan met een beetje wiskunde worden gedaan: 1 seconde/verstreken tijd-seconden.

1s/(16ms / 1000s) = 62.5fps, dus een timestap van 16ms is gelijk aan 62,5 frames per seconde.


Stap 3: Beperkingen

Beperkingen zijn beperkingen en regels die aan de simulatie zijn toegevoegd, zodat ze kunnen leiden waar PointMasses wel en niet naartoe kan gaan.

Ze kunnen eenvoudig zijn als beperkende beperking, om te voorkomen dat PointMasses van de linkerrand van het scherm verdwijnen:

Het toevoegen van de beperking aan de rechterkant van het scherm gebeurt op dezelfde manier:

Dit doen voor de y-as is een kwestie van elke x in een y veranderen.

Het hebben van de juiste soort beperkingen kan resulteren in zeer mooie en boeiende interacties. Beperkingen kunnen ook extreem complex worden. Probeer je voor te stellen dat je een trillende mand met korrels simuleert waarbij geen van de korrels elkaar kruisen, of een robotarm met 100 verbindingen, of zelfs iets simpels als een stapel dozen. Het typische proces omvat het vinden van botsingspunten, het vinden van het exacte tijdstip van de botsing en vervolgens het vinden van de juiste kracht of impuls om op elk lichaam toe te passen om die botsing te voorkomen.

Het begrijpen van de hoeveelheid complexiteit die een set beperkingen kan hebben, kan moeilijk zijn en dan het oplossen van die beperkingen in realtime zelfs nog moeilijker. Wat we zullen doen is het vereenvoudigen van constraint-oplossingen aanzienlijk vereenvoudigen.


Stap 4: Verlet Integratie

Een wiskundige en programmeur genaamd Thomas Jakobsen onderzocht enkele manieren om de fysica van personages voor games te simuleren. Hij stelde dat nauwkeurigheid niet zo belangrijk is als geloofwaardigheid en prestaties. Het hart van zijn hele algoritme was een methode die sinds de jaren 60 werd gebruikt om moleculaire dynamica te modelleren, Verlet-integratie genaamd. Misschien kent u het spel Hitman: Codename 47. Het was een van de eerste games die ragdoll-fysica gebruikte en maakt gebruik van de door Jakobsen ontwikkelde algoritmen.

Verlet-integratie is de methode die we gebruiken om de positie van onze PointMass door te geven. Wat we eerder deden, x = x + velX, is een methode die Euler-integratie wordt genoemd (die ik ook gebruikte bij coderen van Destructible Pixel Terrain).

Het belangrijkste verschil tussen Euler en Verlet integratie is hoe snelheid wordt uitgevoerd. Met behulp van Euler, een snelheid met het object is opgeslagen en is toegevoegd aan de positie van het object van elk frame. Het gebruik van Verlet past echter inertie toe door de vorige en huidige positie te gebruiken. Neem het verschil in de twee posities en voeg het toe aan de laatste positie om traagheid toe te passen.

We hebben daar de versnelling toegevoegd voor de zwaartekracht. Anders dan dat, zijn accX en accY niet nodig voor het oplossen van botsingen. Met behulp van Verlet-integratie hoeven we niet langer een soort van impuls of gedwongen oplossing voor botsingen uit te voeren. Alleen de positie wijzigen is voldoende om een ​​stabiele, realistische en snelle simulatie te hebben. Wat Jakobsen heeft ontwikkeld, is een lineaire vervanger voor iets dat anders niet-lineair is.


Stap 5: Link Beperkingen 

De voordelen van Verlet-integratie kunnen het beste worden weergegeven aan de hand van een voorbeeld. In een textielmotor hebben we niet alleen PointMasses, maar ook links ertussen. Onze "links" vormen een afstandsbeperking tussen twee PointMasses. Idealiter willen we dat twee PointMasses met deze beperking altijd op een bepaalde afstand van elkaar staan.

Wanneer we deze beperking oplossen, moet Verlet Integration deze punten in beweging houden. Als het ene uiteinde bijvoorbeeld snel naar beneden zou worden verplaatst, zou het andere uiteinde het als een zweep moeten volgen door traagheid.

We hebben slechts één link nodig voor elk paar PointMasses dat aan elkaar is gekoppeld. Alle gegevens die u nodig hebt in de koppeling zijn de PointMasses en de rustafstanden. Optioneel kun je stijfheid hebben, voor meer lente-beperkingen. In onze demo hebben we ook een "traangevoeligheid", de afstand waarmee de link wordt verwijderd.

Ik zal hier alleen restingDistance uitleggen, maar de scheurafstand en stijfheid zijn beide geïmplementeerd in de demo en de broncode.

U kunt lineaire algebra gebruiken om de beperking op te lossen. Zoek de afstanden tussen de twee, bepaal hoe ver ze in rust zijn en vertaal ze vervolgens op basis van dat en hun verschillen.

Dalam demo, kami memperhitungkan massa dan kekakuan juga. Ada beberapa masalah dalam menyelesaikan kendala ini. Wanneer er meer dan twee of drie PointMasses met elkaar zijn verbonden, kan het oplossen van enkele van deze beperkingen andere eerder opgeloste beperkingen schenden.

Thomas Jakobsen kwam ook dit probleem tegen. In eerste instantie zou men een systeem van vergelijkingen kunnen maken en alle beperkingen tegelijkertijd kunnen oplossen. Dit zou echter snel toenemen in complexiteit, en het zou moeilijk zijn om meer dan alleen maar enkele links naar het systeem toe te voegen.

Jakobsen ontwikkelde een methode die in eerste instantie dom en naïef lijkt. Hij creëerde een methode genaamd "ontspanning", waarbij we in plaats van een keer op te lossen voor de beperking, we er verschillende keren voor oplossen. Elke keer dat we de links herhalen en oplossen, wordt de reeks links steeds dichter bij het oplossen.

Stap 6: Breng het Samen

Om samen te vatten, hier is hoe onze motor werkt in pseudocode. Voor een meer specifiek voorbeeld, bekijk de broncode van de demo.


Stap 7: Voeg een Stof Toe

Nu kunnen we de stof zelf bouwen. Het maken van de koppelingen moet vrij eenvoudig zijn: link naar links wanneer PointMass niet de eerste is in de rij en koppelingen maken wanneer het niet de eerste in zijn kolom is. 

De demo gebruikt een eendimensionale lijst om PointMasses op te slaan en vindt punten om te linken naar x + y * width.

U zou in de code kunnen opmerken dat wij ook 'pin PM' hebben. Als we niet willen dat ons gordijn valt, kunnen we de bovenste rij PointMasses vergrendelen naar hun startpositie. Om een ​​pinconstraint te programmeren, voegt u enkele variabelen toe om de pinlocatie bij te houden en vervolgens de PointMass naar die positie te verplaatsen nadat elke constraint is opgelost.


Stap 8: Voeg een Aantal Ragdolls Toe

Ragdolls waren de oorspronkelijke bedoelingen van Jakobsen achter zijn gebruik van Verlet Integratie. Eerst beginnen we met de hoofden. We zullen een Cirkelbeperking creëren die alleen met de grens interageert.

Vervolgens kunnen we het lichaam creëren. Ik voegde elk lichaamsdeel toe om de massa en lengteverhoudingen van een gewoon menselijk lichaam enigszins te evenaren. Bekijk Body.pde in de bronbestanden voor volledige details. Dit doen zal ons naar een ander probleem leiden: het lichaam zal gemakkelijk in ongemakkelijke vormen draaien en ziet er erg onrealistisch uit.

Er zijn een aantal manieren om dit op te lossen. In de demo gebruiken we onzichtbare en zeer onstabiele schakels van de voeten naar de schouder en het bekken naar het hoofd om het lichaam op natuurlijke wijze in een minder onhandige rustpositie te duwen.

U kunt ook nep-hoekbeperkingen maken met behulp van koppelingen. Laten we zeggen dat we drie PointMasses hebben, waarvan er twee zijn gekoppeld aan een in het midden. U kunt een lengte tussen de uiteinden vinden om aan elke gekozen hoek te voldoen. Om die lengte te vinden, kun je de Wet van Cosinus gebruiken.

Pas de link aan zodat deze beperking alleen van toepassing is wanneer de afstand kleiner is dan de rustafstand of, als het meer is dan. Hierdoor blijft de hoek op het middelpunt altijd te dichtbij of te ver, afhankelijk van wat je nodig hebt.


Stap 9: Meer Afmetingen!

Een van de geweldige dingen met het hebben van een volledig lineaire fysica-engine is het feit dat het elke gewenste dimensie kan zijn. Alles dat aan x werd gedaan, werd ook gedaan met een y-waarde, en kan daarom worden overgebracht naar drie of zelfs vier dimensies (ik weet echter niet zeker hoe je dat rendert!)

Hier volgt een linkbeperking voor de simulatie in 3D:


Conclusie

Bedankt voor het lezen! Veel van de simulatie is sterk gebaseerd op Thomas Jakobsen's Advanced Character Physics-artikel uit GDC 2001. Ik heb mijn best gedaan om de meeste ingewikkelde dingen te strippen en te vereenvoudigen tot het punt dat de meeste programmeurs zullen begrijpen. Als je hulp nodig hebt of opmerkingen hebt, kun je hieronder berichten plaatsen.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.