.[ ČeskéHry.cz ].
Skulz po kolizním objektu
Jdi na stránku 1, 2  Další
 
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> 3D API / 3D Enginy
Zobrazit předchozí téma :: Zobrazit následující téma  
Autor Zpráva
Juraj



Založen: 06. 12. 2007
Příspěvky: 189

PříspěvekZaslal: 9. únor 2010, 19:02:52    Předmět: Skulz po kolizním objektu Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
perry



Založen: 28. 07. 2009
Příspěvky: 879

PříspěvekZaslal: 9. únor 2010, 19:33:13    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Ladis



Založen: 18. 09. 2007
Příspěvky: 1537
Bydliště: u Prahy

PříspěvekZaslal: 9. únor 2010, 20:41:55    Předmět: Odpovědět s citátem

Jo to odhození je asi nejjednoduší řešení. Pamatuju na něj ve starých hrách Smile.
_________________
Award-winning game developer
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 10. únor 2010, 08:41:41    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Juraj



Založen: 06. 12. 2007
Příspěvky: 189

PříspěvekZaslal: 10. únor 2010, 13:59:10    Předmět: Odpovědět s citátem

Mohly by jste mi sem hodin nějaký příklad, třeba i na to odskočení. Díky
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
perry



Založen: 28. 07. 2009
Příspěvky: 879

PříspěvekZaslal: 10. únor 2010, 19:18:50    Předmět: Odpovědět s citátem

Se SATem jsem začal tady http://newwiki.ceske-hry.cz/Kolize_a_n%C3%A1sledn%C3%A1_reakce

Pak jsem hodně googlil a procházel diskuzi na gamedev.
Návrat nahoru
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Juraj



Založen: 06. 12. 2007
Příspěvky: 189

PříspěvekZaslal: 10. únor 2010, 20:13:50    Předmět: Odpovědět s citátem

perry napsal:
Se SATem jsem začal tady http://newwiki.ceske-hry.cz/Kolize_a_n%C3%A1sledn%C3%A1_reakce

Pak jsem hodně googlil a procházel diskuzi na gamedev.


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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
perry



Založen: 28. 07. 2009
Příspěvky: 879

PříspěvekZaslal: 11. únor 2010, 09:09:21    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Juraj



Založen: 06. 12. 2007
Příspěvky: 189

PříspěvekZaslal: 11. únor 2010, 20:43:33    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
Juraj



Založen: 06. 12. 2007
Příspěvky: 189

PříspěvekZaslal: 11. únor 2010, 22:39:57    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 12. únor 2010, 10:05:54    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 879

PříspěvekZaslal: 12. únor 2010, 12:59:12    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 12. únor 2010, 14:17:11    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
perry



Založen: 28. 07. 2009
Příspěvky: 879

PříspěvekZaslal: 12. únor 2010, 15:24:54    Předmět: Odpovědět s citátem

No jako, že mam narotovaný ten box Smile 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ý Very Happy

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
Zobrazit informace o autorovi Odeslat soukromou zprávu Zobrazit autorovi WWW stránky
]semo[



Založen: 29. 07. 2007
Příspěvky: 1526
Bydliště: Telč

PříspěvekZaslal: 12. únor 2010, 16:49:38    Předmět: Odpovědět s citátem

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
Zobrazit informace o autorovi Odeslat soukromou zprávu
Zobrazit příspěvky z předchozích:   
odeslat nové téma   Odpovědět na téma    Obsah fóra České-Hry.cz -> 3D API / 3D Enginy Časy uváděny v GMT + 1 hodina
Jdi na stránku 1, 2  Další
Strana 1 z 2

 
Přejdi na:  
Nemůžete odesílat nové téma do tohoto fóra
Nemůžete odpovídat na témata v tomto fóru
Nemůžete upravovat své příspěvky v tomto fóru
Nemůžete mazat své příspěvky v tomto fóru
Nemůžete hlasovat v tomto fóru


Powered by phpBB © 2001, 2005 phpBB Group


Vzhled udelal powermac
Styl "vykraden" z phpBB stylu MonkiDream - upraveno by rezna