Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
Juraj

Založen: 06. 12. 2007 Příspěvky: 189
|
Zaslal: 9. únor 2010, 19:02:52 Předmět: Skulz po kolizním objektu |
|
|
Zdravím Vás, po delší době jsem narazil na jeden problém, který se mi nedaří vyřešit.
Pro lepší vysvětlení přikládám obrázek. Konkrétně mě zajímá jak v 3D prostoru vypočítat skluz pohybujícího se objektu (B) pro kolizním objektu (A). Nějaké vlastní řešení jsem již zpracoval, ale vždy mi funguje jen pro nějaké úhly.. Možná jsem začal špatně už od začátku a teď jsem se do toho nějak zamotal.
Díky |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 9. únor 2010, 19:33:13 Předmět: |
|
|
Co jsem dělal, tak OBB kolizní test postavený na SATu, tak jsem ve výsledku použil jednoduché "odhození" kostek z kolize. Výsledek je, že kostky po sobě "klouzají".
Ovšem fyzikálně ten skluz asi úplně přesný není... nicméně vizuálně nevypadá špatně. |
|
Návrat nahoru |
|
 |
Ladis

Založen: 18. 09. 2007 Příspěvky: 1537 Bydliště: u Prahy
|
Zaslal: 9. únor 2010, 20:41:55 Předmět: |
|
|
Jo to odhození je asi nejjednoduší řešení. Pamatuju na něj ve starých hrách . _________________ Award-winning game developer |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 10. únor 2010, 08:41:41 Předmět: |
|
|
Ladis: je i v nových hrách, kamera versus zdi, panák versus zdi..:-)
Jak psal perry, výpočet kolize ti musí vrátit hloubku a směr - to je v případě SAT algoritmu splněno. A to stačí. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
Juraj

Založen: 06. 12. 2007 Příspěvky: 189
|
Zaslal: 10. únor 2010, 13:59:10 Předmět: |
|
|
Mohly by jste mi sem hodin nějaký příklad, třeba i na to odskočení. Díky |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
|
Návrat nahoru |
|
 |
Juraj

Založen: 06. 12. 2007 Příspěvky: 189
|
Zaslal: 10. únor 2010, 20:13:50 Předmět: |
|
|
Tak tento článek jsem již také procházel, ale nijak mi nepomohl. Mnou potřebné kolize mezi OBB už mám vyřešené, nyní mi jde pouze o výpočet toho "sklouznutí" po objectu. |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 11. únor 2010, 09:09:21 Předmět: |
|
|
http://nopaste.ceske-hry.cz/222889 Tímhle kusem kodu dostanu po kolizi kostky od sebe a zajišťuje mi to i skluz.
mtd = minimal translation distance - hodnota získaná ze SAT
ncoll = normala kolize ze SAT |
|
Návrat nahoru |
|
 |
Juraj

Založen: 06. 12. 2007 Příspěvky: 189
|
Zaslal: 11. únor 2010, 20:43:33 Předmět: |
|
|
Mám na vás jednu prosbu, nějak jsem si našel chybu při výpočtu OBB. Nakonec se mi jí podařilo vyřešit. Chybu jsem měl ve výpočtu rotace:
kód: |
Matrix rotM = Matrix.CreateRotationZ(rot.Z) * Matrix.CreateRotationX(rot.X) * Matrix.CreateRotationY(rot.Y);
|
místo původního
kód: |
Matrix rotM = Matrix.CreateRotationX(rot.X) * Matrix.CreateRotationY(rot.Y) * Matrix.CreateRotationZ(rot.Z);
|
Pořád mi ale není jasné jaký rozdíl v tom je? A proč mi nový způsob funguje a starý ne?? |
|
Návrat nahoru |
|
 |
Juraj

Založen: 06. 12. 2007 Příspěvky: 189
|
Zaslal: 11. únor 2010, 22:39:57 Předmět: |
|
|
perry napsal: |
http://nopaste.ceske-hry.cz/222889 Tímhle kusem kodu dostanu po kolizi kostky od sebe a zajišťuje mi to i skluz.
mtd = minimal translation distance - hodnota získaná ze SAT
ncoll = normala kolize ze SAT |
Moje kolize vypadá takto:
kód: |
Matrix matB = b.rotation * this.inverseRotation;
Vector3 vPosB = Vector3.Transform(b.center - this.center,
this.inverseRotation);
Vector3 XAxis = new Vector3(matB.M11, matB.M21, matB.M31);
Vector3 YAxis = new Vector3(matB.M12, matB.M22, matB.M32);
Vector3 ZAxis = new Vector3(matB.M13, matB.M23, matB.M33);
//15 tests
//1 (Ra)x
if ((float)Math.Abs(vPosB.X) >
(this.bounds.X +
b.bounds.X * (float)Math.Abs(XAxis.X) +
b.bounds.Y * (float)Math.Abs(XAxis.Y) +
b.bounds.Z * (float)Math.Abs(XAxis.Z)))
{
return false;
}
//2 (Ra)y
if ((float)Math.Abs(vPosB.Y) >
(this.bounds.Y +
b.bounds.X * (float)Math.Abs(YAxis.X) +
b.bounds.Y * (float)Math.Abs(YAxis.Y) +
b.bounds.Z * (float)Math.Abs(YAxis.Z)))
{
return false;
}
//3 (Ra)z
if ((float)Math.Abs(vPosB.Z) >
(this.bounds.Z +
b.bounds.X * (float)Math.Abs(ZAxis.X) +
b.bounds.Y * (float)Math.Abs(ZAxis.Y) +
b.bounds.Z * (float)Math.Abs(ZAxis.Z)))
{
return false;
}
//4 (Rb)x
if ((float)Math.Abs(vPosB.X * XAxis.X +
vPosB.Y * YAxis.X +
vPosB.Z * ZAxis.X) >
(b.bounds.X +
this.bounds.X * (float)Math.Abs(XAxis.X) +
this.bounds.Y * (float)Math.Abs(YAxis.X) +
this.bounds.Z * (float)Math.Abs(ZAxis.X)))
{
return false;
}
//5 (Rb)y
if ((float)Math.Abs(vPosB.X * XAxis.Y +
vPosB.Y * YAxis.Y +
vPosB.Z * ZAxis.Y) >
(b.bounds.Y +
this.bounds.X * (float)Math.Abs(XAxis.Y) +
this.bounds.Y * (float)Math.Abs(YAxis.Y) +
this.bounds.Z * (float)Math.Abs(ZAxis.Y)))
{
return false;
}
//6 (Rb)z
if ((float)Math.Abs(vPosB.X * XAxis.Z +
vPosB.Y * YAxis.Z +
vPosB.Z * ZAxis.Z) >
(b.bounds.Z +
this.bounds.X * (float)Math.Abs(XAxis.Z) +
this.bounds.Y * (float)Math.Abs(YAxis.Z) +
this.bounds.Z * (float)Math.Abs(ZAxis.Z)))
{
return false;
}
//7 (Ra)x X (Rb)x
if ((float)Math.Abs(vPosB.Z * YAxis.X -
vPosB.Y * ZAxis.X) >
(this.bounds.Y * (float)Math.Abs(ZAxis.X) +
this.bounds.Z * (float)Math.Abs(YAxis.X) +
b.bounds.Y * (float)Math.Abs(XAxis.Z) +
b.bounds.Z * (float)Math.Abs(XAxis.Y)))
{
return false;
}
//8 (Ra)x X (Rb)y
if ((float)Math.Abs(vPosB.Z * YAxis.Y -
vPosB.Y * ZAxis.Y) >
(this.bounds.Y * (float)Math.Abs(ZAxis.Y) +
this.bounds.Z * (float)Math.Abs(YAxis.Y) +
b.bounds.X * (float)Math.Abs(XAxis.Z) +
b.bounds.Z * (float)Math.Abs(XAxis.X)))
{
return false;
}
//9 (Ra)x X (Rb)z
if ((float)Math.Abs(vPosB.Z * YAxis.Z -
vPosB.Y * ZAxis.Z) >
(this.bounds.Y * (float)Math.Abs(ZAxis.Z) +
this.bounds.Z * (float)Math.Abs(YAxis.Z) +
b.bounds.X * (float)Math.Abs(XAxis.Y) +
b.bounds.Y * (float)Math.Abs(XAxis.X)))
{
return false;
}
//10 (Ra)y X (Rb)x
if ((float)Math.Abs(vPosB.X * ZAxis.X -
vPosB.Z * XAxis.X) >
(this.bounds.X * (float)Math.Abs(ZAxis.X) +
this.bounds.Z * (float)Math.Abs(XAxis.X) +
b.bounds.Y * (float)Math.Abs(YAxis.Z) +
b.bounds.Z * (float)Math.Abs(YAxis.Y)))
{
return false;
}
//11 (Ra)y X (Rb)y
if ((float)Math.Abs(vPosB.X * ZAxis.Y -
vPosB.Z * XAxis.Y) >
(this.bounds.X * (float)Math.Abs(ZAxis.Y) +
this.bounds.Z * (float)Math.Abs(XAxis.Y) +
b.bounds.X * (float)Math.Abs(YAxis.Z) +
b.bounds.Z * (float)Math.Abs(YAxis.X)))
{
return false;
}
//12 (Ra)y X (Rb)z
if ((float)Math.Abs(vPosB.X * ZAxis.Z -
vPosB.Z * XAxis.Z) >
(this.bounds.X * (float)Math.Abs(ZAxis.Z) +
this.bounds.Z * (float)Math.Abs(XAxis.Z) +
b.bounds.X * (float)Math.Abs(YAxis.Y) +
b.bounds.Y * (float)Math.Abs(YAxis.X)))
{
return false;
}
//13 (Ra)z X (Rb)x
if ((float)Math.Abs(vPosB.Y * XAxis.X -
vPosB.X * YAxis.X) >
(this.bounds.X * (float)Math.Abs(YAxis.X) +
this.bounds.Y * (float)Math.Abs(XAxis.X) +
b.bounds.Y * (float)Math.Abs(ZAxis.Z) +
b.bounds.Z * (float)Math.Abs(ZAxis.Y)))
{
return false;
}
//14 (Ra)z X (Rb)y
if ((float)Math.Abs(vPosB.Y * XAxis.Y -
vPosB.X * YAxis.Y) >
(this.bounds.X * (float)Math.Abs(YAxis.Y) +
this.bounds.Y * (float)Math.Abs(XAxis.Y) +
b.bounds.X * (float)Math.Abs(ZAxis.Z) +
b.bounds.Z * (float)Math.Abs(ZAxis.X)))
{
return false;
}
//15 (Ra)z X (Rb)z
if ((float)Math.Abs(vPosB.Y * XAxis.Z -
vPosB.X * YAxis.Z) >
(this.bounds.X * (float)Math.Abs(YAxis.Z) +
this.bounds.Y * (float)Math.Abs(XAxis.Z) +
b.bounds.X * (float)Math.Abs(ZAxis.Y) +
b.bounds.Y * (float)Math.Abs(ZAxis.X)))
{
return false;
}
|
Nyní nějak nevím jak, jak zde doplnit výpočet normály a minimální vzdálenosti, nějaké rady? |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 12. únor 2010, 10:05:54 Předmět: |
|
|
přepsat to
k těm rotacím: přečti si něco o rotacích. Přeskládáním násobení těch matic, se to možná bude chovat v tvém případě lépe, ale ne vždy. Každá další přinásobená rotace už rotuje orotovanou věc, takže první rotujue podle světových souřadnic, další už ne. _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 12. únor 2010, 12:59:12 Předmět: |
|
|
U OBB rotace kumuluju přes Quaterniony. A až ve výsledku Quaternion převedu na matici. Je to přesnější, než použití matic (a zabírá míň místa).
Tvoje oboje rotace budou nejspíš pokaždé fungovat jinak. Takhle kumulovat rotace je dost "nebezpečné", protože kolem bodu [0,0,0] to pojede OK, ale jakmile se posuneš někam do prostoru, tak už se to po první rotace rozhází a začne to rotovat kolem jiné osy. Dalo by se to řešit tak, že nejdřív provedeš translaci do počátku, rotuješ a posunuješ, aby se držel střed rotace pořád v počátku. Pak by neměl být v pořadí rotací rozdíl.
Jinak ta kolize, to je na přepsání.
V kostce získání MTD.
0) jedna z osA x osB
1) Provedeš projekci boxuA a boxuB na osu kterou testuješ. To jsem počítal takhle
kód: |
axis - osa na kterou se promita
boxOrientationX - orientace boxu v ose X - aka jak je narotovany
position - pozice stredu bodu
half(...) - poloviční rozměry boxu
float C;
float R;
C = Vector3.Dot(this.position, axis);
R = Math.Abs(Vector3.Dot(axis, this.boxOrientationX)) * this.HalfWidth +
Math.Abs(Vector3.Dot(axis, this.boxOrientationY)) * this.HalfHeight +
Math.Abs(Vector3.Dot(axis, this.boxOrientationZ)) * this.HalfDepth;
min = C - R;
max = C + R;
|
2)
Vypočteš
kód: |
minB - zacatek pruniku na ose pro boxB
obdobne zbyle.
float maxBminA = (maxB - minA); //d0
float maxAminB = (maxA - minB); //d1
|
3)
kód: |
if ((minA > maxB) || (minB > maxA))
{
return false; //neni prunik boxu
}
|
4) Je kolize
Výpočet MTD
kód: |
float axisLengthSquare = Vector3.Dot(axis, axis);
float overlap = (maxBminA < maxAminB) ? maxBminA : -maxAminB;
Vector3 mtdTemp = axis * (overlap / axisLengthSquare);
float axisLengthSquareTemp = Vector3.Dot(mtdTemp, mtdTemp);
if (axisLengthSquareTemp < this.mtdLength || this.mtdLength < 0.0f)
{
this.mtdLength = axisLengthSquareTemp; //velikost prekryvu
this.mtd = mtdTemp; //osa prekryvu
}
|
Znova navrat k 0)
Nakonec ti po všech testech zustane min mtd
jako ncoll muzes pouzit vektor mtd a normalizovat ho. Budu to většinou fungovat.
tenhle "postup" neřeší nijak tzv. SWEPT Test. Neboli, když se ti ty kostky budou pohybovat tak rychle, že se proskočí a mtd a ncoll vyjdou na druhou stranu, než z jaké došlo ke kolizi. |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 12. únor 2010, 14:17:11 Předmět: |
|
|
perry:
Tím posunem do 0 se to nevyřeší.
Co myslíš tím "OBB rotace"? Rotace jako rotace, ne? :) _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 12. únor 2010, 15:24:54 Předmět: |
|
|
No jako, že mam narotovaný ten box Rotuje se během jednoho framu třeba okolo y, pak okolo z... a všechno kumuluju do Quaterniony.. a pak udělam matici.. no.. je to takovy nejaky divně vysvětlený
Ad. Posun do 0.. Asi blbý dotaz, ale proč to nevyřeší ? Navíc pokud se rotuje podle středu a ten je v [0,0,0] , tak by výsledek nemel byt ovlivnen poradim |
|
Návrat nahoru |
|
 |
]semo[

Založen: 29. 07. 2007 Příspěvky: 1526 Bydliště: Telč
|
Zaslal: 12. únor 2010, 16:49:38 Předmět: |
|
|
Jenže bude ovlivněn pořadím. Například nejdřív narotuješ okolo světový souřadnice X o 90 stupňů. Tim se ti třeba ze Z udělá Y. Další rotace rádoby okolo Z je ale už okolo Y. Zkus třeba najít něco o "Gimbal Lock".
EDIT: prostě..násobení matic neni komutativní, takže z toho polezou opravdu různý výsledky _________________ Kdo jede na tygru, nesmí sesednout.
---
http://www.inventurakrajiny.cz/sipka/
Aquadelic GT, Mafia II, simulátory
Naposledy upravil ]semo[ dne 12. únor 2010, 17:24:47, celkově upraveno 1 krát |
|
Návrat nahoru |
|
 |
|