سؤال

لقد كنت أعاني من هذا من أجل الخير أثناء الآن. أحاول تحديد إحداثيات الشاشة للبرامج في نموذج على شاشة NDS باستخدام DevkitPro. يبدو أن المكتبة تنفذ بعض وظائف OpenGL ، ولكن على وجه الخصوص ، فإن وظيفة Gluproject مفقودة ، والتي ستسمح لي (أفترض) بالقيام بذلك بسهولة.

لقد كنت أحاول خيرًا الآن لحساب إحداثيات الشاشة يدويًا باستخدام مصفوفة الإسقاط التي يتم تخزينها في سجلات DS ، لكنني لم أحصل على الكثير من الحظ ، حتى عند محاولة بناء مصفوفة الإسقاط من نقطة الصفر بناءً وثائق OpenGL. إليك الرمز الذي أحاول استخدامه:

void get2DPoint(v16 x, v16 y, v16 z, float &result_x, float &result_y)
{
 //Wait for the graphics engine to be ready
 /*while (*(int*)(0x04000600) & BIT(27))
  continue;*/

 //Read in the matrix that we're currently transforming with
 double currentMatrix[4][4]; int i; 
 for (i = 0; i < 16; i++)
  currentMatrix[0][i] = 
  (double(((int*)0x04000640)[i]))/(double(1<<12));

 //Now this hurts-- take that matrix, and multiply it by the projection matrix, so we obtain
 //proper screen coordinates.
 double f = 1.0 / tan(70.0/2.0);
 double aspect = 256.0/192.0;
 double zNear = 0.1;
 double zFar = 40.0;
 double projectionMatrix[4][4] = 
 {
  { (f/aspect), 0.0, 0.0, 0.0 },
  { 0.0, f, 0.0, 0.0 },
  { 0.0, 0.0, ((zFar + zNear) / (zNear - zFar)), ((2*zFar*zNear)/(zNear - zFar)) },
  { 0.0, 0.0, -1.0, 0.0 },
 };

 double finalMatrix[4][4];
 //Ugh...
 int mx = 0; int my = 0;
 for (my = 0; my < 4; my++)
  for (mx = 0; mx < 4; mx++)
   finalMatrix[mx][my] = 
   currentMatrix[my][0] * projectionMatrix[0][mx] + 
   currentMatrix[my][1] * projectionMatrix[1][mx] + 
   currentMatrix[my][2] * projectionMatrix[2][mx] + 
   currentMatrix[my][3] * projectionMatrix[3][mx] ;

 double dx = ((double)x) / (double(1<<12));
 double dy = ((double)y) / (double(1<<12));
 double dz = ((double)z) / (double(1<<12));

 result_x = dx*finalMatrix[0][0] +  dy*finalMatrix[0][1] + dz*finalMatrix[0][2] + finalMatrix[0][3];
 result_y = dx*finalMatrix[1][0] +  dy*finalMatrix[1][1] + dz*finalMatrix[1][2] + finalMatrix[1][3];

 result_x = ((result_x*1.0) + 4.0)*32.0;
 result_y = ((result_y*1.0) + 4.0)*32.0;


 printf("Result: %f, %f\n", result_x, result_y);

} 

هناك الكثير من التحولات المعنية ، تعمل DS داخليًا باستخدام تدوين النقطة الثابتة وأحتاج إلى تحويل ذلك إلى الزوجي للعمل معها. يبدو أن ما أحصل عليه صحيحًا إلى حد ما- يتم ترجمة وحدات البكسل تمامًا إذا كنت أستخدم رباعيًا مسطحًا يواجه الشاشة ، لكن الدوران متزعزع. أيضًا ، نظرًا لأنني ذاهب إلى مصفوفة الإسقاط (التي تمثل عرض/ارتفاع الشاشة؟) الخطوات الأخيرة التي أحتاج إلى استخدامها لا تبدو صحيحة على الإطلاق. ألا ينبغي أن تنجز مصفوفة الإسقاط خطوة لأعلى لقرار الشاشة بالنسبة لي؟

أنا جديد على كل هذا ، لقد حصلت على فهم عادل على Matrix Math ، لكنني لست ماهرًا كما أرغب في أن أكون في رسومات ثلاثية الأبعاد. هل يعرف أي شخص هنا طريقة ، بالنظر إلى الإحداثيات ثلاثية الأبعاد غير المنقولة لبرامج رأس النموذج ، وأيضًا بالنظر إلى المصفوفات التي سيتم تطبيقها عليها ، للتوصل إلى إحداثيات الشاشة ، دون استخدام وظيفة Gluproject الخاصة بـ OpenGL؟ هل يمكنك رؤية شيء واضح بشكل صارخ أنني أفتقد في الكود الخاص بي؟ (سأوضح عندما يكون ذلك ممكنًا ، أعرف أنه صعب ، هذا نموذج أولي أعمل عليه ، فإن النظافة ليست أولوية عالية)

اشكرك كثيرا!

ملاحظة: كما أفهمها ، CurrentMatrix ، التي أسحبها من سجلات DS ، ينبغي أعطني مصفوفة الإسقاط والترجمة والدوران مجتمعة ، حيث يجب أن تكون المصفوفة الدقيقة التي سيتم استخدامها للترجمة بواسطة أجهزة DS الخاصة ، على الأقل وفقًا للمواصفات في GBATEK. في الممارسة العملية ، لا يبدو أن إحداثيات الإسقاط تطبق عليها ، والتي أفترض أن لها علاقة بمشكلاتي. لكنني لست متأكدًا ، لأن حساب الإسقاط بنفسي لا يولد نتائج مختلفة.

هل كانت مفيدة؟

المحلول

هذا صحيح تقريبا.

الخطوات الصحيحة هي:

  • اضرب ModelView مع مصفوفة الإسقاط (كما فعلت بالفعل).

  • قم بتوسيع قمة ثلاثية الأبعاد إلى إحداثي متجانس عن طريق إضافة مكون W ذي القيمة 1. على سبيل المثال ، يصبح المستنقع (X ، Y ، z)-

  • اضرب هذا المتجه مع منتج المصفوفة. يجب أن تكون المصفوفة الخاصة بك 4 × 4 ومتجهك من الحجم 4. ستكون النتيجة متجهًا بحجم 4 أيضًا (لا تسقط W حتى الآن!). نتيجة هذا الضرب هو المتجه الخاص بك في الفضاء المقطع. لمعلوماتك: يمكنك بالفعل القيام بضعة أشياء مفيدة للغاية هنا مع هذا المتجه: الاختبار إذا كانت النقطة على الشاشة. الظروف الست هي:

    x < -w : Point is outside the screen (left of the viewport)
    x >  W : Point is outside the screen (right of the viewport)
    y < -w : Point is outside the screen (above the viewport)
    y >  w : Point is outside the screen (below the viewport)
    z < -w : Point is outside the screen (beyond znear)
    z >  w : Point is outside the screen (beyond zfar)
  • عرض وجهة نظرك في الفضاء 2D. للقيام بهذا الفجوة x و y بواسطة w:
  x' = x / w;
  y' = y / w;
  • إذا كنت مهتمًا بالقيمة العمق (على سبيل المثال ، ما يتم كتابته إلى Zbuffer) ، فيمكنك عرض Z أيضًا:
 z' = z / w
  • لاحظ أن الخطوة السابقة لن تعمل إذا كانت W صفر. هذه الحالة تحدث إذا كانت وجهة نظرك مساوية لموضع الكاميرا. أفضل ما يمكنك القيام به في هذه الحالة هو تعيين X 'و Y' على الصفر. (سوف ينقل النقطة إلى مركز الشاشة في الخطوة التالية ..).

  • الخطوة الأخيرة: احصل على إحداثيات OpenGL Viewport وتطبيقها:

  x_screen = viewport_left + (x' + 1) * viewport_width  * 0.5;
  y_screen = viewport_top  + (y' + 1) * viewport_height * 0.5;
  • هام: قد يكون إحداثيات Y لشاشتك رأسًا على عقب. على عكس معظم واجهات برمجة تطبيقات الرسوم الأخرى في OpenGL y = 0 تشير إلى أسفل الشاشة.

هذا كل شئ.

نصائح أخرى

سأضيف المزيد من الأفكار إلى إجابة نيلز الشاملة.

  1. لا تستخدم الزوجي. لست على دراية بـ NDS ، لكنني أشك في أنه يحتوي على أي أجهزة للرياضيات المزدوجة.
  2. أنا أيضًا أشك في أن عرض النموذج والإسقاط لا يتضاعفان بالفعل إذا كنت تقرأ سجلات الأجهزة. لا يزال يتعين علي رؤية منصة الأجهزة التي لا تستخدم MVP الكامل في السجلات مباشرة.
  3. قد يكون أو لا يكون تخزين المصفوفة في السجلات في نفس الترتيب مثل OpenGL. إذا لم يكن الأمر كذلك ، فيجب القيام بمصفوف مصفوفة الضرب بالترتيب الآخر.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top