Www.mg.edu.rs
Matematička gimnazija
Kraljice Natalije 37
Beograd
Maturski rad iz informatike
SIMULACIJA ELASTIČNIH TELA
Mentor: Učenik:
Profesor Milan Čabarkapa Jovan Rnjak, 4e
Beograd, 28/5/2012
Sadržaj
Strana
Uvod...............................................................................2
1. OpenGL/GLUT..........................................................4
2. Struktura podataka
2.1 Klasa Point.....................................................6
2.2 Klasa Constraint.............................................7
2.3 Klasa Body.....................................................8
3. Tok Programa
3.1 Računanja sila...............................................10
3.2 Integracija......................................................13
3.3 Detekcija kolizije i reakcija.......................... 16
3.4 Inicjalizacija...................................................23
3.5 Prikaz.............................................................27
3.6 Update ciklus.................................................29
Zaključak........................................................................31
Uvod
Ovaj rad predstavlja moj prvi korak u svet grafičke simulacije, kao i moj prvi “ozbiljni” program i namera mi je da se nadograđujem u tom smeru ubuduće. Sam rad kombinira elemente najinteresantnijih predmeta sa kojim sam se susreo tokom školovanja u Matematičkoj gimnaziji. To su informatika, fizika, numerika i linearna algebra.
Pri izboru programskog jezika dvoumio sam se između C++ i Python-a. Moji prvi pokusaji su bili u Python-u, privukla me je jednostavnija sintaksa, kao i intuitivnije metode za manipulaciju podataka. Ispostavilo se da ta jednostavnost ima visoku cenu, pored sporije brzine nedostajao mi je temeljiti debugger i Python-ov “weak typing” je uzrokovalo veliku neorganizaciju sa moje strane, pa je moj konačni izbor bio C++. Nažalost jake tačke C-a su istovremeno moje loše tačke; mnogo vremena sam proveo pokušavajući da razrešim greške izazvane “ilegalnim” pokazivačima, korupcije stek-a i drugih anomalija koje cenim da sam sam nekako izazvao, indirektno.
Izbor grafičkog API-a (Application Programming Interface) je bio lakši. Direct3D je zavisan od Windows-a i da bi ga koristio trebao bi se služiti sa WinAPI-om, a s tim bi i sam metod crtanja bio suviše kompleksan, tako da sam se odlučio za OpenGL sa dodatkom GLUT toolkit-a. ()
Simulacija se bazira na ideji da su sva tela izgrađena od tačaka koje su međusobno spojene oprugama. Ovakva vrsta simulacije nije fizički precizna, ali sa dobrim konfiguracijama koeficijenata opruga, trenja i gravitacije, moguće je dobiti veoma prihvatljive reakcije od simuliranih tela. Simulacija se odvija u dve prostorne dimenzije.
Izrada programske logike kao i source kod je uglavnom moj samostalni rad (sa izuzetkom GLUT templejta sa kojim sam počeo) i samim tim je implementacija prilično neoptimalna na nekim mestima. Ipak mislim da ta jednostavnost implementacije lakše otkriva suštinu ovakvih programa i shodno tome čitanje ovog rada bi poslužilo kao dobar uvod u principe grafičkih simulacija.
1. OpenGL/GLUT
void main(int argc, char** argv)
{
//--------------------------------------------------------------------------
// OpenGL / GLUT init / Window init
//--------------------------------------------------------------------------
glutInit( &argc, argv ); //Inicijalizacija OpenGL-a/GLUT-a
glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH); //Tip buffer-a
glutInitWindowSize (width, height); //Atributi prozora
glutInitWindowPosition (0, 0);
glutCreateWindow ("Soft Body Dynamics");
glShadeModel(GL_SMOOTH); //Opcije za anti-aliasing
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glEnable (GL_BLEND); //Opcije za blend
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable (GL_DEPTH_TEST);
glDisable (GL_LIGHTING);
glutDisplayFunc (Display); //Funkcija za crtanje
glutReshapeFunc (Reshape); //Event-Handler za promenu dimenzije prozora
glutTimerFunc (0, Timer, (float) 180.0f / 60.0f); //Glavni update loop
glutPassiveMotionFunc (PassiveMotion);
glutMouseFunc (Mouse); //Event-Handleri za Mis/tastaturu
glutKeyboardFunc (Keyboard);
Init ();
glutMainLoop ();
}
void Reshape(int w, int h)
{
width = w;
height = h;
glViewport( 0, 0, w, h);
}
void Timer(int t)
{
Update();
Display();
glutTimerFunc(t, Timer, t);
}
void Motion(int x, int y)
{
mouse_x = x;
mouse_y = y;
}
void Mouse(int buttons, int state, int x, int y)
{
mouse_x = x;
mouse_y = y;
if (buttons == GLUT_LEFT_BUTTON)
{
if (state == GLUT_DOWN)
mouse_b |= 1;
else
mouse_b &= ~1;
}
if (buttons == GLUT_RIGHT_BUTTON)
{
if (state == GLUT_DOWN)
mouse_b |= 2;
else
mouse_b &= ~2;
}
}
void Keyboard(unsigned char k, int x, int y)
{
char c=toupper(k);
switch(c)
{
case 'G':gravity=!gravity;break;
case '4':scenario=3;glutReshapeWindow(800,600);glutPostRedisplay();Init();break;
case '3':scenario=2;glutReshapeWindow(800,800);glutPostRedisplay();Init();break;
case '2':scenario=1;glutReshapeWindow(800,600);glutPostRedisplay();Init();break;
case '1':scenario=0;glutReshapeWindow(1200,800);glutPostRedisplay();Init();break;
case 'W':wireframe=!wireframe;break;
case 'F':coutvx=0;
this->dx=0;
this->vy=0;
this->dy=0;
}
Point::Point(int x,int y,float InvMass)
{
this->x=x;
this->y=y;
this->InvMass=InvMass;
this->vx=0;
this->dx=0;
this->vy=0;
this->dy=0;
}
Klasa Point predstavlja jedinični element svih tela. Sastoji se od položaja tačke u prostoru, kao i njene brzine i ubrzanja. Uzeo sam inverznu masu radi lakšeg definisanja statičnih tela (ona tela čija masa teži ka beskonačnosti, dakle inverzna masa je nula). Baferi za brzinu i položaj su neophodni da bi se sprečila zavisnost izračunatih sila od redosleda po kojim se računa.
3.2 Klasa Constraint
class Constraint
{
public:
int A; //Prva,
int B; //i Druga tačka.
float Coefficient; //Koeficijent elastičnosti
float RelaxDistance; //Ravnotežno rastojanje
Constraint(){this->A=0;this->B=0;}; //Konstruktor
Constraint(int, int, float, float); //Konstruktor A,B,Koeficijent,Ravnotežno rastojanje
Constraint(int,int,float); //Konstruktor A,B,Koeficijent
};
Constraint::Constraint(int A, int B, float Coefficient)
{
this->A=A;
this->B=B;
this->Coefficient=Coefficient;
}
Constraint::Constraint(int A, int B, float Coefficient, float RelaxDistance)
{
this->A=A;
this->B=B;
this->Coefficient=Coefficient;
this->RelaxDistance=RelaxDistance;
}
Klasa Constraint predstavlja oprugu unutar jednog tela. A i B predstavljaju položaj tačke u nizu tačaka jednog tela.
Konstante i globalne varijable
float mouse_x = 0.0f; //Položaj miša na x-osi
float mouse_y = 0.0f; //Polozaj miša na y-osi
int mouse_b = 0; //Superpozicija pritisnutih dugmi na mišu (bit flag/field)
float dtu= 1.0f /60.0f; //Step za integraciju
float dtu6 = dtu/6.0;
float width =800; //Dužina prozora
float height = 600; //Visina prozora
bool wireframe=0; //Wireframe on/off
const int MAX_BODIES =20; //Maksimalan broj tela u jednom sistemu
int scenario=0; //Trenutni scenario
bool gravity=1;
3.3 Klasa Body
class Body
{
public:
Point* PointCloud; //Niz tačaka
Constraint* Constraints; //Niz opruga
int CollGroup;
int* CollPoints;
int NumCollPoints; //Ukupan broj CollPoints
int NumPoints; //Ukupan broj tačaka tela
int NumConstraints; //Ukupan broj opruga
int ThisI; //Indeks tela
bool CheckCollision[MAX_BODIES]; //Označava da li će telo proveravati preklope sa i-tim telom
bool* Outside; //Oznaćava za i-tu tačku da li se nalazi na spoljašnost.
Body(); //Konstruktor
Body(int,int,int); //Konstruktor NumPoints, NumConstraints, NumCollPoints
void AssignCollPoints(int[],int); //Učitavanje niza CollPoints
void AddPoint(Point, int); //Dodaj tačku
void AddConstraint(Constraint,int); //Dodaj oprugu i automatski zadaj RelaxDistance u zavisnosti od unesenih tacaka.
void AddConstraint2(Constraint,int); //Dodaj oprugu
void CalculateSprings(); //Izračunaj sile opruga
void CalculateAttraction(int sign); //Izracunaj odbojnu/privlačnu silu miša
void ApplyForces(); //v+=a
void ApplyWall(); //Zid prozora
void Gravity(); //Gravitacija
void FrictionWall(); //Trenje sa ivicom prozora
};
Klasa Body predstavlja telo definisano preko niza masa i opruga (Point i Constraint).
Metod koji sam koristio za određivanje preklpanja dva tela isključivo funkcioniše za konveksna tela, zato je bilo potrebno razdvojiti telo na više konveksni poligona i za svaki takav poligon posebno proveravati moguća preklapanja. CollGroup je broj stranica tih poligona. Optimalan broj stranica za većinu tela je četiri ( retki su slučajevi konkavnih četvorouglova ) i pritom imamo duplo manje poligona na kojima trebamo da proveravamo preklop, nego kad bismo delili tela na trouglove.
Važno je uočiti da ovakvom podelom ne moramo obavezno da celokupno prekrijemo prvobitno telo, to jest interesuje nas samo spoljašnji sloj jer su tu sudari najčešći.
CollPoints je jednodimenzionalan niz tih poligona. Važno je napomenuti da redosled kojim se upisuju tačke je bitan. Pre svega imamo da indeksi i, i+1, i+2, i+3 za i=4*k (CollGroup=4) moraju da obrazuju željeni poligon, a pri tom tačke moraju biti orijentisane u smeru kazaljke na satu. Ovo olakšava računanje normala nad parovima tih tačaka.
Primer dva različita ali pojednako validna niza za ilustrovano telo:
0 1 2 CollPoints={0,1,4,3,1,2,5,4,4,5,8,7,3,4,7,6}
3 4 5 CollPoints={2,5,4,1,3,4,7,6,3,0,1,4,4,5,8,7}
6 7 8
Body::Body(int NumPoints, int NumConstraints, int NumCollPoints)
{
PointCloud=new Point[NumPoints];
Constraints=new Constraint[NumConstraints];
CollPoints=new int[NumCollPoints];
this->NumConstraints=NumConstraints;
this->NumPoints=NumPoints;
this->NumCollPoints=NumCollPoints;
this->Outside=new bool[NumPoints];
for(int i=0;iConstraints[i].RelaxDistance
=Dist(PointCloud[A].x,PointCloud[A].y,PointCloud[B].x,PointCloud[B].y);
this->Constraints[i].Coefficient=C.Coefficient;
}
void Body::AddConstraint2(Constraint C, int i)
{
Constraints[i]=C;
}
void Body::AssignCollPoints(int Array[], int len)
{
for(int i=0;i0)PointCloud[i].vx=0;
}
else if(PointCloud[i].x0)PointCloud[i].vy=0;
}
else if(PointCloud[i].y ................
................
In order to avoid copyright disputes, this page is only a partial summary.
To fulfill the demand for quickly locating and searching documents.
It is intelligent file search solution for home and business.