المقالات العلمية

مقالات الشبكة العربية لمطوري الألعاب

تقاطع شعاع مع مجسم

السلام عليكم و رحمة الله و بركاته في هذا الدرس سوف أتناول كيفية إكتشاف بأن مؤشر الفأرة يتقاطع أم لا مع شيئ ثلاثي الأبعاد (3D object or mesh) و أعني بذلك الكائن Microsoft.DirectX.Direct3D.Mesh

بعد ضبط كل الكائنات في البرمجة باستعمال تقنية الدايركت أكس المدارة Managed DirectX ، إتبع الخطوات التالية:

  • أضف كائن "ماش" من اختيارك و ليكن صحيح و قائم و واضح و يظهر على الشاشة لكي تستطيع أن تقارن التقاطع أم لا مع مؤشر الفأرة، في المثال الذي أتناوله "سامبل" إخترت بيت بسيط مع خزانة و هذه الأخيرة هي المستهدفة، ما يعني ذلك، يعني أنك عندما تضع مؤشر الفأرة على تلك الخزانة ستتلون بلون أو أي شيئ آخر و إلا فلا. أنظر إلى الصورتين:

  • الخزانة المدروس عليها هي عبارة عن شيئ في البيئة المرسومة "البيت" مثلها مثل الجدران و الأرضية، لكن دعنا لا نخرج عن الموضوع و نتحدث عن التقنية، كيف يتم التحقق من إحداثيات الماوس X و Y على أنها تقع فوق الخزانة أو أي شيئ آخر.
  • نفترض في هذا المقال بأنك قمت بكل الترتيبات بما فيها :
    • الكائن Direct3D.Device يحب أن يكون صالحا و مستعدا للرسم؛
    • الأشياء أو الكائنات Direct3D.Mesh يجب أن تكون صالحة؛
  • نذهب الآن الى الرياضيات، يجب علينا أن نعلم التحويل من إحداثيات الشاشة إلى إحداثيات البيئة يسمى "عكس الإسقاط" و العكس، يعني التحويل من إحداثيات البيئة إلى إحداثيات الشاشة يسمى "إسقاط" أو Projecting.
    عكس الإسقاط يسمى بالانجليزية في سياق كلامنا بالـ Unprojecting.

    نعلم أن نقطة من الشاشة هي ثنائية الأبعاد (X, Y)، و أن نقطة من البيئة التي نجرب عليها هي ثلاثية الأبعاد (x, y, z)

    من أحد خصائص البنية Microsoft.DirectX.Vector3 الدالة التي إسمها Unproject() التي تقوم بتحويل ... إلى ...
    (أنت قم بإملاء الفراغات).

    بالتفكير ملياً تستطيع أن تخمن ما ستطلبه هذه الدالة عندما نستعملها و ما هي القيمة التي ستعطينا في المقابل.
    ما سترجعه لنا هو القيمة : ... ما تتطلبه هو : .... + قيمة المعلم الحالي الذي توجد فيه الخزانة + قيمة مصفوفة الكاميرا أو العين + قيمة مصفوفة الإسقاط المستعمل في المعلم الحالي. (أكمل الفراغات).

    يجب أن نحول نقطة الماوس إلى نقطة ثلاثية الأبعاد (أبعاد الماوس يمكن الحصول عليها بعدة طرق، سنستعمل طريقة الحدث Me.MouseMove ) مع إنشاء متغيريين لـ y و x.

Public xc As integer
Public yc as integer
Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Me.MouseMove
xc = e.X
yc = e.Y
End Sub
  • النقطة التي سيتم تحويلها إلى ثري دي من الشاشة إلى مستوي القص القريب "البلان و ليس اللفل" (المستوي و ليس المستوى هنا) (م.ق.ق.) بـ n
  • النقطة التي سيتم تحويلها من الشاشة إلى مستوي القص البعيد (م.ق.ب.) بـ f
  • م.ق.ق. = مستوي القص القريب، كل شيئ مرسوم قبله (أعني بذلك المثلث الصغير) لا يرى.
  • م.ق.ب. = مستوي القص البعيد، كل شيئ يرسم ... لا يرى (الجهة اليمنى البيضاء بالنسبة إلى م.ق.ب.) (أكمل الفراغ).
كل شيئ مرسوم داخل "الشبه المنحرف" يمكنك رأيته على الشاشة إن كان ليس مخفياً من طرف شيئ آخر كجدار إلخ... (لا تكمل الفراغات هنا).

قاعدة : كل شيئ موجود داخل "الشبه المنحرف" (ندعو له بالصلاح من الله) يدخل في خط الرسوميات "قرافيكس بيبلاين" ثم يرسم.

  • شعاعنا الأخضر ينطلق من "شاشتك" ثم "م.ق.ق." ثم "م.ق.ب.".
  • نقطة من "شاشتك" يعني النقطة (xc , yc)
  • نقطة من "م.ق.ق." يعني النقطة (xc , yc, znearPlane)
  • نقطة من "م.ق.ب." يعني النقطة (xc , yc, zfarPlane)
  • = قيمة م.ق.ب. zfarPlane = قيمة م.ق.ق. و znearPlane
d.Transform.Projection = Matrix.PerspectiveFovLH(3.14 / 3, 1366 / 768, 1, 2000)

هتين القيمتين هما نفسهما قيمتين الوسيطين الثالث و الرابع.

.znearPlane = 1 و zfarPlane = 2000

Dim n As Vector3 = Vector3.Unproject(New Vector3(xc, yc, 1), d.Viewport, d.Transform.Projection, d.Transform.View, d.Transform.World)
Dim f As Vector3 = Vector3.Unproject(New Vector3(xc, yc, 2000), d.Viewport, d.Transform.Projection, d.Transform.View, d.Transform.World)

نحسب الآن قيمة كل من z و y و x لمركبة الشعاع الأخضر الذي سنسميه v.

Dim v As Vector3 = Vector3.Subtract(f, n)

يعني الشعاع الأخضر هو المستقيم الذي يمر بـ n و f.

معنى Z near clipping plane و Z far clipping plane مستوي القص القريب و مستوي القص البعيد، الوحدة ليست بالسنتمتر أو المليميتر، بل بالوحدة (unit).
في Microsoft DirectX SDK 2007، نجد كلام يحتوي على تعريف بهذين المستويين:

// For the projection matrix, you set up a perspective transform (which
// transforms geometry from 3-D view space to 2-D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perspective transform, you need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define 
// the distances at which geometry should no longer be rendered).

من Managed DirectX هناك صنف (class) تسمى بالـ Microsoft.DirectX.Direct3D.IntersectInformation، تسمح لنا بإيجاد التالي:

  • Dist = المسافة بين النقطة n و نقطة تقاطع الشعاع v مع الخزانة.
  • FaceIndex = الوجه الناتج عن تقاطع الشعاع v مع الخزانة.
الآن نتأكد من أن الشعاع v يقطع الخزانة في نقطة أم لا باستعمال الدالة Intersect() الموجودة ضمن الكائن من صنف Mesh:
Dim ch As New Direct3D.IntersectInformation() 
If library.Intersect(n, v, ch) = True Then 
d.SetTexture(0, library_texture)القيام بعملية الإكساء ' 
library.DrawSubset(0)
Else
d.SetTexture(0, Nothing) عدم القيام بعملية الإكساء ' 
library.DrawSubset(0)
End If

الدالة Intersect() تطلب شيئين و ترجع لنا شيئين:

تطلب نقطة إحداثيات موقع الشعاع على شكل Microsoft.DirectX.Vector3 و أيضا شعاع التوجيه (يعني احداثياته) على شكل Microsoft.DirectX.Vector3
و ترجع لنا القيمة ch و التي هي عبارة عن كائن يخبأ معلومات رأيناها سابقاً، و ترجع لنا القيمة التي انتظرناها من نوع Boolean التي تدل على أن مؤشر الفأرة يقع فوق أم لا على الخزانة.

أضف تعليقاً

Loading