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

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 16. prosinec 2011, 16:27:46 Předmět: WM_INPUT a balistika kurzoru myši |
|
|
Zdravím,
věděl by někdo jak nasimulovat balistiku kurzoru myši ve Windows? Přes WndProc totiž dostávám zprávu WM_INPUT, a získávám "hrubou" pozici myši (přes funkci GetRawInputData), tedy bez transformací.
Zkouším teď emulovat DirectInput (a DirectDraw), a potřeboval bych, aby ten pohyb by stejně "rychlý" jako ve Windows. Můj problém je právě ten, že se mi kurzor ve hře pohybuje jinou rychlostí než ve Windows.
Našel jsem tyto odkazy:
MSDN: Pointer Ballistics for Windows XP
MSDN: Taking Advantage of High-Definition Mouse Movement
Pokud jsem to pochopil správně, tak ta pozice co dostávám je transformovaná podle toho prvního vzorce v tom prvním odkaze, takže by mělo jen stačit dokončit tu transformaci podle toho druhého vzorce.
Zkouším tu rychlost vypočítat takto...
kód: |
fCursorXVel = ((FLOAT(dm.dmDisplayFrequency) / ::GetDeviceCaps(hDC, LOGPIXELSX)));
fCursorYVel = ((FLOAT(dm.dmDisplayFrequency) / ::GetDeviceCaps(hDC, LOGPIXELSY))); |
..a pak transformovat tu pozici ve WM_INPUT takto:
kód: |
POINT& pCursorPos = directDraw->m_pCursorPos;
if ((rawMouse.usFlags & MOUSE_MOVE_RELATIVE) == MOUSE_MOVE_RELATIVE)
{
if (rawMouse.lLastX != 0)
pCursorPos.x += INT((FLOAT(rawMouse.lLastX) * fCursorXVel) /*+ 0.5f*/);
if (rawMouse.lLastY != 0)
pCursorPos.y += INT((FLOAT(rawMouse.lLastY) * fCursorYVel) /*+ 0.5f*/);
}
else if ((rawMouse.usFlags & MOUSE_MOVE_ABSOLUTE) == MOUSE_MOVE_ABSOLUTE)
{
POINT& pWindowCenter = directDraw->m_pWindowCenter;
pCursorPos.x = pWindowCenter.x + rawMouse.lLastX;
pCursorPos.y = pWindowCenter.y + rawMouse.lLastY;
} |
Věděl by si s tím někdo rady? Zkoušel to už někdo?  _________________
 |
|
Návrat nahoru |
|
 |
Al
Založen: 23. 10. 2007 Příspěvky: 196
|
Zaslal: 17. prosinec 2011, 00:01:49 Předmět: |
|
|
Zkoušel jsi stackoverflow? |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 17. prosinec 2011, 06:31:41 Předmět: |
|
|
Al napsal: |
Zkoušel jsi stackoverflow? |
Tam jsem se zatím nezkoušel zeptat, hledal jsem ale hodiny přes google a nic k tomu jsem právě nenašel, zdá se že nikdo se nesnaží zachovávat stejnou rychlost, a rovnou používají ty hrubé data.  _________________
 |
|
Návrat nahoru |
|
 |
Mnemonic

Založen: 28. 07. 2007 Příspěvky: 93
|
Zaslal: 17. prosinec 2011, 13:55:39 Předmět: |
|
|
No a nedosáhneš stejného efektu použitím WM_MOUSEMOVE? |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 17. prosinec 2011, 14:33:33 Předmět: |
|
|
Mnemonic napsal: |
No a nedosáhneš stejného efektu použitím WM_MOUSEMOVE? |
Právě že zprávu WM_MOUSEMOVE vůbec nedostávám, a když už jí náhodou dostanu, tak je pořád stejná, tj. ukazuje na střed okna.
Způsobuje to právě DirectInput, který si ty zprávy odchytává na nižší úrovni, a jediný způsob jak přinutit Windows předávávat zprávy o uživatelském vstupu hostující aplikaci, je právě přes RegisterRawInputDevices. (Funkce SetWindowsHookEx nepřipadá v úvahu...) _________________
 |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 18. prosinec 2011, 11:20:47 Předmět: |
|
|
Vypadá to, že musím akumulovat tu pozici včetně toho zbytku po "dělení", takže bych měl zřejmě ukládat tu pozici do floatu. V tom prvním odkaze se zmiňují že Windows použivá datový typ s fixní desetinnou čárkou, takže to tam určitě taky akumulují.
Edit: Tak jsem upravil ten kód tak aby se nikde nic nezaokrouhlovalo, a ta rychlost kurzoru je teď hodně podobná té ve Windows, ale stále to není ono.
V tom vzorci buď něco chybí, a nebo nedostávám všechny zprávy WM_INPUT, těžko říct...  _________________
 |
|
Návrat nahoru |
|
 |
if.then
Založen: 13. 04. 2008 Příspěvky: 579
|
Zaslal: 18. prosinec 2011, 15:49:39 Předmět: Re: WM_INPUT a balistika kurzoru myši |
|
|
Crypton napsal: |
Pokud jsem to pochopil správně, tak ta pozice co dostávám je transformovaná podle toho prvního vzorce v tom prvním odkaze, takže by mělo jen stačit dokončit tu transformaci podle toho druhého vzorce. |
citace: |
The disadvantage is that WM_INPUT has no ballistics applied to its data, so if you want to drive a cursor with this data, extra effort will be required to make the cursor behave like it does in Windows. For more information about applying pointer ballistics, see Pointer Ballistics for Windows XP |
citace: |
Internally, DirectInput creates a second thread to read WM_INPUT data, and using the DirectInput APIs will add more overhead than simply reading WM_INPUT directly. Overall, using DirectInput offers no advantages when reading data from mouse or keyboard devices, and the use of DirectInput in these scenarios is discouraged. |
Tudíž DirectInput je jenom obalení WM_INPUT a potřebuješ aplikovat nastavení popsaná v tvém prvním odkaze. _________________ For guns and glory, go to www.ceske-hry.cz.
For work and worry, execute VC++. |
|
Návrat nahoru |
|
 |
Mnemonic

Založen: 28. 07. 2007 Příspěvky: 93
|
Zaslal: 18. prosinec 2011, 16:12:12 Předmět: |
|
|
Otázka je, proč teda vůbec používat pro myš DirectInput, když stejně ta surová data chceš přepočítat na to, co vrací WinAPI. |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 18. prosinec 2011, 16:46:38 Předmět: Re: WM_INPUT a balistika kurzoru myši |
|
|
if.then napsal: |
Tudíž DirectInput je jenom obalení WM_INPUT a potřebuješ aplikovat nastavení popsaná v tvém prvním odkaze. |
To já ale přeci už vím Potřebuju s tím ale trochu pomoct s těmi výpočty...
[url="Mnemonic"]Otázka je, proč teda vůbec používat pro myš DirectInput, když stejně ta surová data chceš přepočítat na to, co vrací WinAPI.[/url]
Už jsem to psal v prvním postu: Snažím se emulovat DirectDraw.
Píšu svou vlastní implementaci knihovny DirectDraw (ddraw.dll), která nahrazuje tu původní, ale místo DirectX používá OpenGL.
Hookuju funkci WndProc hostitelské aplikace, takže můžu zpracovávat i zprávy o uživatelském vstupu (myš, klávesnice).
Problém je v tom, že některé hry používají DirectInput, který si ty zprávy odchytává na nižší úrovní, a do funkce WndProc je už nepřeposílá, a jak už jsem zmínil, "jediný" způsob jak přinutit Windows posílat ty zprávy o vstupu té funkci WndProc, je zaregistrováním vstupního zařízení přes funkci RegisterRawInputDevices.
No a "moje" rychlost pohybu kurzoru je jiná než ta u DirectInput, vím to protože se v testované hře vykresluje ten původní kurzor na pozici získané z DirectInput, a přes to pak vykresluju já svůj vlastní kurzor, který má pozici určenou z WM_INPUT, takže poznám kdy ty rychlosti budou zcela totožné.
Nechci zatím "plně" emulovat DirectInput, hlavně protože se chci věnovat implementaci DirectDraw (a taky se mi nechce smolit s force feedback, a těmi effekty).
 _________________
 |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 18. prosinec 2011, 17:03:43 Předmět: |
|
|
Daleko snažší implementace se dá udělat pomocí GetCursorPos a SetCursorPos. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 18. prosinec 2011, 17:28:21 Předmět: |
|
|
Marek napsal: |
Daleko snažší implementace se dá udělat pomocí GetCursorPos a SetCursorPos. |
To jsem zkoušel, dokonce jako první možnost, ale GetCursorPos taky vrací pořád tu stejnou pozici - již ten zmíněný střed okna.  _________________
 |
|
Návrat nahoru |
|
 |
Marek

Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 19. prosinec 2011, 01:42:26 Předmět: |
|
|
Samozřejmě ale bez zachytávání WM zpráv a bez DirectInput. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
 |
Crypton

Založen: 14. 05. 2009 Příspěvky: 306 Bydliště: The Void
|
Zaslal: 19. prosinec 2011, 04:04:29 Předmět: |
|
|
Tak jsem to nakonec vyřešil přes hook té knihovny (dinput.dll), a to přímo z té mojí kníhovny (ddraw.dll).
Problém byl v tom, že ty hry běží ve fullscreenu, a nastavují si pomocí DirectInput přes metodu SetCooperativeLevel exkluzivní mód (vlajka DISCL_EXCLUSIVE), při kterém:
citace: |
"If the system mouse is acquired in exclusive mode, the pointer is removed from the screen until the device is unacquired. This applies only to a mouse created by passing GUID_SysMouse to IDirectInput8::CreateDevice." |
Takže ten kurzor není jen skrytý, ale rovnou odstraněný... a proto mi to pořád ukazovalo pozici na střed obrazovky.
No mělo by mi jen stačit hookovat tu metodu, a hlídat si tu vlajku DISCL_EXCLUSIVE, ale když už to hookuju, tak se na WM_INPUT asi úplně vykašlu. (Mordoval jsem se ale s tím dlouho, hlavně s hookem IAT, a virtuálních tabulek těch rozhraní...)
Stále by mě ale zajímalo jak by ten algoritmus měl správně vypadat...  _________________
 |
|
Návrat nahoru |
|
 |
micky

Založen: 28. 02. 2008 Příspěvky: 348 Bydliště: Plzeň, Praha
|
Zaslal: 19. prosinec 2011, 14:41:28 Předmět: |
|
|
Kdysi jsem četl v internetovém magazínu s pochybným názvem Hakin9 článek o rekonstrukci pohybu kurzoru bezdrátové myši na základě odposlechu. Pro linux dokázali udělat skutečně téměř 1:1, pro Windows to přesně nedokázali. (Ale i tak se dalo odposlechnout leccos ) _________________ https://www.bluepulsar.cz/
https://twitter.com/11thDream_Game/ |
|
Návrat nahoru |
|
 |
|