لو سمحت لو حد يعرف هنا طريقة عامة للربط بين ضغطة الماوس التو دي و اى مجسم ثري دي و محدش يقول الطريقة ديه مستحيلة لأنها موجودة في العاب كثيرة زى الالعاب الاستراتيجية
و شكرا
لو سمحت لو حد يعرف هنا طريقة عامة للربط بين ضغطة الماوس التو دي و اى مجسم ثري دي و محدش يقول الطريقة ديه مستحيلة لأنها موجودة في العاب كثيرة زى الالعاب الاستراتيجية
و شكرا
نعم انا سمعت انو بيخرج ray و بيتحقق من مكان الcollision حاجة زى كدة حد يعرف اكواد او كدة ؟ :)
و اكون شاكر له جدا
السلام عليكم, :)
سأحاول ان اشرح الفكرة العامة التي تستطيع من خلالها عمل Mouse Picking مع تقديم معلومات مختصرة عن الأساسيات المطلوبة, يجب أن تكون قد فهمت كيفية رسم المشاهد المجسمة لكي تستطيع فهم وإستخدام الطريقة بحسب الأدوات التي تستخدمها (DirectX, OpenGL, Irrlicht, ...).
لنبدأ, هنالك عدة أنواع من الفضاءات Spaces التي يجب إستخدامها لحساب المشهد المجسم الذي تراه في النهاية في نافذة ثنائية الأبعاد, وهي مرتبطة بالـ Graphics Pipeline, المقصود بالفضاء هنا هو موقع الأشياء بالنسبة لبعضها, مثلاً موقع صندوق مرسوم بالنسبة للكاميرا المستخدمة للرسم, أي إن الفضاء هو أشبه ما يكون بمعادلة تستطيع إستخدامها لتحويل الأشكال المرسومة من مكانها الحالي إلى مكانها المرغوب, يمثل الفضاء رياضياً بمصفوفة من القيم تمثل النقل, الدوران, والتحجيم المطلوب.
الفضاءات التي تهمنا هنا (وهي الأساسية), هي كالتالي:
والآن لأوضح الصورة أكثر, سأشرح مالذي يجب أن يحصل لكي تتمكن من رسم نموذج للشاشة:
والآن يتم الرسم ويكون ما يظهر على الشاشة في فضاء الشاشة.
عندما تضغط بالماوس على أي جزء من الشاشة الموجود فيها المشهد, فإن كل ما تحصل عليه من نظام الإدخال هو الإحداثيات ثنائية الأبعاد لموقع الماوس بالنسبة للنافذة التي يتم رسم المشهد فيها, تلك الإحداثيات موجودة في فضاء الشاشة.
ما يجب أن تقوم به الآن هو تقريباً عكس عملية تحويل الصندوق المبينة سابقاً, أول خطوة هي تحويل الإحداثيات من فضاء الشاشة إلى فضاء الإسقاط, وذلك عن طريق معادلة تحتسب من مصفوفة الإسقاط.
بعدها نقوم بإحتساب مقلوب مصفوفة العرض, ثم نستخدمها لتحويل إحداثيات الماوس التي حصلنا عليها من فضاء الإسقاط إلى فضاء العرض, سنولد شعاعاً Ray يبدأ من نقطة إحداثي الماوس ويتجه بشكل عمودي إلى داخل الشاشة.
سأبين العملية بإستخدام Direct3D (كود عام):
المصفوفات الرئيسية التي سيتم إستخدامها:
D3DXMATRIX viewMat; // View Matrix D3DXMATRIX projMat; // Projection Matrix //.....etc
لنفترض إننا حصلنا الآن على موقع الماوس, وهو إحداثي بالمدى (0,0) - (width,height) بالنسبة للنافذة, كما إن لدينا إرتفاع وعرض النافذة المستخدمة:
float mx; // Mouse X position float my; // Mouse Y position float width; // Window width float height; //Window height
إنتبه إلى إن عرض وإرتفاع نافذة الرسم الحقيقية لا يكون دائماً مساوي لعرض وإرتفاع نافذة الوندوز المستخدمة بالنسبة لـ Direct3D (بسبب شريط العنوان, والقوائم التي يجب أن لا تحتسب), لكي تحصل على القيم الصحيحة, إستخدم
D3DVIEWPORT9 viewport_structure; d3dDevic->GetViewport( &viewport_structure ); width = viewport_structure.Width; height = viewport_structure.Height;
لنحسب موقع الماوس بالنسبة لمصفوفة الإسقاط (أو لنحول النقطة من فضاء الشاشة إلى فضاء الإسقاط):
tx = ( ( ( 2.0f * mx ) / width ) - 1.0f ) / projMat._11; // projMat_11: العنصر الموجود في العمود الأول الصف الأول ty = - ( ( ( 2.0f * my ) / height ) - 1.0f ) / projMat_22;
والآن سنحسب مركز الشعاع وإتجاهه بإستخدام النقطة التي حسبناها:
D3DXVECTOR3 rayPos, rayDir; // الشعاع موجود حالياً في فضاء العرض rayPos = D3DXVECTOR3( 0.0f, 0.0f, 0.0f ); rayDir = D3DXVECTOR3( tx, ty, 1.0f );
والآن, الخطوة الأخيرة هي تحويل الشعاع من فضاء العرض إلى فضاء العالم عن طريق ضربه بمقلوب مصفوفة العرض:
D3DXMATRIX vim; // ستمثل مقلوب مصفوفة العرض D3DXMatrixInverse( &vim, NULL, &viewMat ); // حول الشعاع إلى فضاء العالم D3DXVec3TransformCoord( &rayPos, &rayPos, &vim ); D3DXVec3TransformNormal( &rayDir, &rayDir, &vim ); D3DXVec3Normalize( &rayDir, &rayDir );
تهانينا! لديك الآن شعاع في العالم.
يجب عليك الآن أن تقوم بعملية فحص جميع النماذج الموجودة في المشهد لمعرفة ما إذا كانت تتقاطع مع الشعاع (بإستخدام الصندوق المحيطي Bounding Box أو الكرة المحيطية Bounding Sphere) ثم إذا كانت تتقاطع حساب المسافة بينها وبين مركز الشعاع, أقرب جسم يتقاطع مع الشعاع هو الجسم الذي تم الضغط عليه...
أتمنى أن تستفيد من هذا الرد... كان الأفضل أن أضع موضوعاً جديداً يبين الطريقة بدل وضع رد طويل عريض هنا, قد أقوم بذلك في المستقبل.
تم تعديل هذه المشاركة بواسطة SandHawk في 12 مارس 2008 في 22:54