PDA

View Full Version : picking in directx



c3d_lover
چهارشنبه 20 اردیبهشت 1385, 21:37 عصر
دوستان می تونید به من الگوریتم picking تو directx رو بدید. البته نه تو فضای پرسپکتیو بلکه تو فضای ایزو متریک. حتی اگه تفاوت ماتریس viewport transformation در این دو حالت رو هم توضیح بدید کافیه!
ماتریس projection ور با متد D3DXMatrixOrthoLH درست کردم.

kochol
دوشنبه 25 اردیبهشت 1385, 17:16 عصر
سلام
من مدتها بود منتظر بودم که یکی یه سوال تخصصی مثل این بکنه چرا چون می فهمم که یکی داره تخصصی کار می کنه.
بار اولی که سوالتو خوندم چیزی نفهمیدم ولی وقتی که داشتم تحقیق می کردم راجع به ray(اشعه) یه چیزهایی متوجه می شم.
البته من خودم هنوز کامل بلد نیستم ولی اطلاعاتم حتما به دردت می خوره.

1. ما می خواهیم از جایی که کلیک می شه رو صفحه که در فضای دو بعدی هست ببینیم که چه جسمی رو کلیک می کنه.

اگه با باندینگ باکس اشنا هستی که هیچی ولی اگه نیستی به نظرم برای تست از چندتا مثلث استفاده کن یعنی برای تست یه مثلث رو انتخاب کن.

عکس که ضمیمه می کنم کاملا می تونه کمک کنه و مخ ادمو راه بندازه. البته خود D3DX یه چیزهایی داره برای این کار ولی من بلد نیستم.

2. کاری که اول باید بکنی اینه که نقطه ای که رو صفحه هست رو به فضای سه بعدی ببری این نقطه روی صفحه جلویی هست.



KGERay CalcPickingRay(int x, int y)
{
float px = 0.0f;
float py = 0.0f;

D3DVIEWPORT9 vp;
Device->GetViewport(&vp);
D3DXMATRIX proj;
Device->GetTransform(D3DTS_PROJECTION, &proj);

px = ((( 2.0f*x) / vp.Width) - 1.0f) / proj(0, 0);
py = (((-2.0f*y) / vp.Height) + 1.0f) / proj(1, 1);

KGERay ray;
ray.vcOrig = KGEVector(0.0f, 0.0f, 0.0f);
ray.vcDir = KGEVector(px, py, 1.0f);

return ray;
}


نکته: البته شاید در بالا منبع اشعه اشتباه باشه اگه دیدی درست کار نکرد اون نقطه رو با نقطه ی مکان دوربین مختصاتشو یکی کن.

3. هر شی ای ممکن هست که در فضای مخصوص خودش باشه که بهش می گن model space نه تو فضای view space که این در محاسبه برخورد ها اشکال می اندازه دو کار می شه کرد

3.1 شی رو از فضای مدل به فضای ویو بیاری که به دلیل زیاد بودن نقاط خیلی کند می شه

3.2 اشعه رو از فضای ویو به فضای مدل ببریم که به دلیل اینکه اشعه تنها تشکیل شده از دو تا نقطه این کار به صرفه تر هست. پس همین کارو می کنیم.



void KGERay::DeTransform(const KGEMatrix &_m)
{
KGEMatrix mInv;
KGEMatrix m=_m;

// inverse translation
m_vcOrig.x-=m._41;
m_vcOrig.y-=m._42;
m_vcOrig.z-=m._43;

// delete translation in the matrix
m._41=0.0f;
m._42=0.0f;
m._43=0.0f;

// invert matrix
mInv.Inverse(m);

// apply invers matrix
m_vcOrig = m_vcOrig * mInv;
m_vcDir = m_vcDir * mInv;
}


4. در آخر هم می مونه محاسبه برخورد اشعه با مثلث.



bool KGERay::Intersects(const KGEVector &vc0, const KGEVector &vc1,
const KGEVector &vc2, bool bCull, float *t)
{
KGEVector pvec, tvec, qvec;

KGEVector edge1 = vc1 - vc0;
KGEVector edge2 = vc2 - vc0;

pvec.Cross(m_vcDir, edge2);

// if close to 0 ray is parallel
float det = edge1 * pvec;

// to account for poor float precision use
// so called epsilon value of 0.0001 instead
// of comparing
if ((bCull) && (det<0.0001f))
return false;
else if ((det<0.0001f) && (det>-0.0001f))
return false;

// distance to plane, <0 means ray behinde the plane
tvec = m_vcOrig - vc0;
float u = tvec * pvec;
if (u<0.0f || u>det)
return false;

qvec.Cross(tvec, edge1);
float v = m_vcDir * qvec;
if (v<0.0f || u+v>det)
return false;

if(t)
{
*t = edge2 * qvec;
float fInvDet = 1.0f/det;
*t *= fInvDet;
}
return true;
}


4.1 فقط فکر کنم که پارامتر تی توضیح بخواد. این پارامتر دقیقا فاصله منبع اشع تا نقطه برخورد رو محاسبه می کنه که برای کشیدن جای تیر توی دیوار چیز توپی هست البته اگه نخواهی محاسبه بشه می تونی NULL رو پاس کنی.

می تونی از کلاس های خود دایرکت ایکس استفاده کنی به جای کلاس های انجین ما ولی من سورس این سه تا کلاسی که استفاده کردم رو هم می زارم.

موفق باشی.

c3d_lover
دوشنبه 25 اردیبهشت 1385, 19:56 عصر
از لطفت ممنون.:چشمک: :قلب: :قلب:
البته به خاطر غم نان الان فرصت تست ندارم! ولی بعدا حتما نگاش می کنم.این پیغام رو هم برای تشکر میزارم. البته تو یه نگاه سطحی به نظرم اومد که بخشی از کد ها شبیه کد کتاب
Introduction to 3D game programming with DirectX 9.0
باشه که خودم قبلا ازش جواب نگرفته بودم.
البته من خودم OpenGl ای هستم ولی جای افسوس داره که directX یه روش ساده برای انتخاب اشیا مثل gl نداره. ببینم اطلاعی نداری که با vertex shader یا pixel shader میشه این کار رو انجام داد یا نه؟ چون 100% تو بازی ها از این روش استفاده نمیشه!

kochol
سه شنبه 26 اردیبهشت 1385, 20:28 عصر
سلام
خیلی ممنون شما لطف دارید درسته من اون تکه کد اول رو از روی اون کتاب نوشتم بقیه قسمتها هم از خودم نیست بالاخره هر کسی که این صنعتو یاد می گیره خودش برای خودش یه الگوریتم جدا نداره که البته من فکر کنم خود اون تکه کدی که از اون کتاب هست وقتی جواب بده که دوربین رو نقطه مبدا باشه و مستقیم به محور زدها نگاه کنه.

خلاصه من نخواستم فقط یه لینک به مقاله های خارجی بزارم و بی خیال بشم و بگم اگه جواب نگرفتی تو فروم های خارجی بپرس یا یه گوگل رو سرچ کن. خواستم خودم هم کمی به این موضوع فکر کنم. اگه مردی بیا این تاپیک رو اونقدر ادامه بدیم که بصورت یه مقاله در بیاد و همه با خوندن این تاپیک بتونند یه برنامه پیکینگ بنویسند.

البته من امروز یه نگاهی به انجام دادن این کار با اپن جی ال انداختم خیلی اسون بود.

vertex shader یا pixel shader هم که تکنیک ها رندر گرفتن هستند و هیچ ربطی به این مساله ندارن ولی مطمین باش 100% از همین روش هم برای بازی ها استفاده می شه چون خیلی سریع هست.
موفق باشی.

c3d_lover
پنج شنبه 28 اردیبهشت 1385, 04:39 صبح
سلام علیکم.
من حرفی ندارم اگه بتونم، پابه پای تو و هر کسی که می خواد همکاری کنه جلو می یام. ولی در مورد اینکه گفتی کد کتاب کار میکنه، یه لطفی کن لبه های داخلی و خارجی تصویرت رو کلیک کن ببین جواب میده. چون تا اونجایی که من یادمه وقتی محیط انتخاب کاملا با خروجی که نمایش داده میشه یکسان نبود و مثلا ممکن بود تو فضای خالی لبه شی کلید کنی ولی شی انتخاب بشه یا لبه داخلی رو کلیک کنی ولی انتخاب نشه بسته به موقعیت دوربین. ببین انتقالات تو این حالات تاثیر داره یا نه! چون من فکر میکنم این مسیر هارو رفته باشم و باز هم جواب نگرفته باشم و دلیلش هم همون عدم تطابق شکل با فضای انتخاب بود. به این خاطر مطمئن نیستم چون این آزمایشات رو 4-5 ماه قبل انجام دادم و وقتی جواب نگرفتم کارم رو با OpenGL انجام دادم. اما یه مشکلاتی داره مثل درایور و ...
البته قول می دم به زودی دوباره اونو تست کنم تا کنار شما (نه جلوی شما!)کم نیارم:متفکر: :شیطان:
در مورد روش دیگه انتخاب، ببین من تو بعضی بازی های استراتژیک دیدم که وسط ابجکت خالی و با کلیک کردن روی اون قسمت خالی شی انتخاب نمیشه و فقط باید رو سطح نمایان شی کلیک کرد. با اون چیزی که قبلا گفتیم این کار قابل انجام نیست هرچند تو کتاب
Core Techniques and Algorithms in Game Programming
یکسری الگوریتم در مورد انتخاب داده ولی میزان محاسبات اونا انقدر زیاده که برای یه بازی با کمینه حدود 600 تا ابجکت قابل انتخاب سرعت رو کم میکنه و کاملا نمایان میشه.برای همین فکر میکنم از روش دیگه ای استفاده میشه. یه احساس پیچیده به من میگه جواب رو میشه تو vertex shader یا pixel shader پیدا کرد.البته منظورم این نیست که تمام کار با اونا انجام بشه.
ممنون
یا علی

kochol
شنبه 30 اردیبهشت 1385, 13:13 عصر
سلام
من فکر کنم شما دقیقا می خواهید که وقتی رو خود جسم کلیک کردید انتخاب کنید.
البته می شه نوشت ولی خیلی کند می شه البته با این راهی که من گفتم.
ولی برای همین که یه باندینگ باکس رو انتخاب کنه کافیه.
من فکر کنم انتقالات تاثیر داشته باشه.

kochol
یک شنبه 31 اردیبهشت 1385, 13:43 عصر
سلام
پست قبلی ام رو که می خوندم دیدم چقدر مبهمه پس دو باره می نویسمش.
1. شما نمی خواهید یک باندینگ باکس شی تونو محصور کنه شما دقیقا می خواهید که وقتی روی خود جسم کلیک کردید انتخاب بشه.
2. که البته با کدهایی که من در بالا گذاشتم می شه تمام مثلث های یک شی رو چک کنی و ببینی که انتخاب می شه یا نه که خیلی کند می شه.
3. انتقالات تو انتخاب حتما تاثیر دارند.
4. من رو pixel shader فکر کردم البته من اطلاعاتم در این مورد شاید به زور به 10 خط برسه ولی فکر کنم که pixel shader می یاد و بر روی تمام نقاطی که از یک جسم رندر شده اند رنگ امیزی می کنه شاید وقتی کلیک می کنیم بشه مختصات را نگه داشت و وقتی می خواهیم فریم بعدی رو رندر بگیریم با مختصات Pixel shader چک کنیم.
البته بعید می دونم که بشه چنین کاری رو کرد ولی خوب با اطلاعات کم ما می تونه یه فرض باشه.