Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Khaj
Založen: 16. 01. 2008 Příspěvky: 49
|
Zaslal: 10. červenec 2008, 12:46:02 Předmět: Elipsoidní problém |
|
|
Momentálně se zabývám kolizemi a rád bych si kolizoval elipsoid (daný svými vektory bez posunu, takže maticí 3x3) a tu je problém.
Zatím jediné řešení co mě napadlo je udělat z elipsoidu zpět kouli použitím inverzní matice(m. elipsoidu x m. objektu co má elipsoid) a jejím aplikováním na objekt se kterým potřebuji kolizi, čímž situaci převedu na kolizi s koulí o poloměru 1 se středem ve středu soustavy souřadnic (nemelu doufám hlouposti? ).
Ale inverzní matice je každopádně pomalá operace a tedy se ptám jestli to nelze řešit nějak elegantněji ... ?
PS. ]semo[, "Kolize a následná reakce" DÍKY !, do té doby bych zjišťoval kolize jednotlivých trojúhelníků (z kvádrů). |
|
Návrat nahoru |
|
|
MD
Založen: 29. 07. 2007 Příspěvky: 437 Bydliště: Praha
|
Zaslal: 10. červenec 2008, 13:25:15 Předmět: |
|
|
Me se reseni s inverzni matici celkem libi, nemuzes si ji tedy u objektu ulozit?
Pokud se elipsoid prubezne meni, muzes aktualizovat i inverzni matici (jen slozis inverzni posun, rotaci a skalovani - radeji nez pocitat inverzi) _________________ - play with objects - www.krkal.org - |
|
Návrat nahoru |
|
|
Khaj
Založen: 16. 01. 2008 Příspěvky: 49
|
Zaslal: 10. červenec 2008, 15:11:55 Předmět: |
|
|
Jo ono to hezký je
Dělat inverzi matice jen když se změní je skvělej nápad (a objektově to je ještě jednodušší) a pokud se nenajde něco ještě rychlejšího, určitě to použuju, dík moc! |
|
Návrat nahoru |
|
|
kerekes
Založen: 29. 07. 2007 Příspěvky: 57
|
Zaslal: 11. červenec 2008, 08:54:46 Předmět: |
|
|
kód: |
Matrix4x4f Matrix4x4f::GetInverse(void)
{
{
Matrix4x4f inversem;
Matrix4x4f tm=*this;
float *inverse=inversem.ma;
int i, j, k;
float t;
for (i = 0; i < 4; i++) {
if (fabsf(tm.m[i][i]) < 0.0005f) {
// Look for non-zero element in column
for (j = i + 1; j < 4; j++) {
if (fabsf(tm.m[j][i])>= 0.0005f ) {
break;
}
}
if (j != 4) {
// Swap rows.
for (k = 0; k < 4; k++) {
t = tm.m[i][k];
tm.m[i][k] = tm.m[j][k];
tm.m[j][k] = t;
t = inverse[i*4+k];
inverse[i*4+k] = inverse[j*4+k];
inverse[j*4+k] = t;
}
}
else {
return Matrix4x4f();
}
}
t = 1.0f / tm.m[i][i];
for (k = 0; k < 4; k++) {
tm.m[i][k] *= t;
inverse[i*4+k] *= t;
}
for (j = 0; j < 4; j++) {
if (j != i) {
t = tm.m[j][i];
for (k = 0; k < 4; k++) {
tm.m[j][k] -= tm.m[i][k]*t;
inverse[j*4+k] -= inverse[i*4+k]*t;
}
}
}
}
return inversem;
}
}
|
Zdroj: nejaky example od intelu upraveny mnou.
Myslim ze dnesne cpu si ani nevsimne ze ratalo nejaku inverznu maticu. Ved je tu len par nasobeni suctov a tie cykly su kratke. Teda pokial ich nebudes ratat stovky/tisice za frame.
Pozn.: .m je tvaru float m[4][4], .ma je tvaru float ma[16]. |
|
Návrat nahoru |
|
|
juroo
Založen: 28. 07. 2007 Příspěvky: 28
|
Zaslal: 13. červenec 2008, 23:43:00 Předmět: |
|
|
ak ma pamat neklame tak sme rovnaky problem riesili kedysi s pcmaster-om presne rovnakym sposobom - prevodom spat na gulu, do pohody to bolo |
|
Návrat nahoru |
|
|
Khaj
Založen: 16. 01. 2008 Příspěvky: 49
|
Zaslal: 4. srpen 2008, 10:23:12 Předmět: |
|
|
Ještě jednou děkuji všem (zvlášť za trknutí, že inveze matice se dá dělat i GEM a ne onou druhou ohavnou metodou ), teď jsem měl čas přemýšlet na prázdninách a poprosil bych ještě o kontrolu následujícího postupu (pokud eventuelně někomu pomůže tím líp):
Základní tělesa: koule r=1, krychle a=1
Každé z těchto těles má svoji matici (4x4 i s posunem tentokrát; kterou se v praxi ještě před tím musí vynásobit matice objektu který má tyto kolizní tělesa), což může vyústit v další tělesa ? elipsoid a kvádr.
Elipsoid A x Elipsoid B (+ Elipsoid A x Koule B + Koule A x Koule B)
A matici vynásobíme invertovanou B maticí, čímž získáme jiný elipsoid A x koule r=1 B.
Vezmeme vektor AB středů, což je vlastně mínus 4. řádek nové matice A, protože invertováním matice B jsme kouli B posunuli do středu soustavy souřadnic.
Velikost tohoto vektoru zmenšíme o jedna za poloměr koule B a získáme vektor od středu elipsoidu A k povrchu koule B. Nakonec tento vektor vydělíme (novou) maticí A (4. složka vektoru je 0, tedy do hry vstupuje pouze část 3x3 matice A). Pokud je jeho velikost menší nebo rovna jedné, nastala kolize.
Lze zrychlit přímou detekcí, jestli jsou všechny velikosti vektorů v matici stejné a tedy se jedná o kouli.
Kvádr/Krychle A x Elipsoid B (+ Kvádr/Krychle A x Koule B)
Matici kvádru A vydělíme maticí B. Následnou modifikovanou matici A upravíme tak aby všechny její vektory (sloupce) měly velikost 1. Délky vektorů si zapamatujeme (bude se jednat o délky hran kvádru).
Takto upravenou matici pak invertujeme (a vynásobíme s novou maticí B což je jednotková matice takže stačí pracovat rovnou s A^-1) a ve 4. řádku budeme mít pozici středu koule r=1 která má kolidovat s osově zarovnaným kvádrem o hranách zapamatovaných délek.
(a dále se odkazuji na ]semúv[ návod)
Opět lze zrychlit stejným způsobem jako u dvou elipsoidů.
Pro dva kvádry je tu SAT. |
|
Návrat nahoru |
|
|
|