الطوبولوجيا والتحليل الشامل لمطور الألعاب المطمئن: ضغط المتجهات ثلاثية الأبعاد الفردية

صورة

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

  • العملية واضحة بما فيه الكفاية
  • إنه أسرع بكثير من الأسلوب المعتاد الذي يؤدي نفس المهمة
  • يستخدم خاصية غير عادية جدًا تمثل أرقام الفاصلة العائمة في تنسيق الفاصلة العائمة ، مما يعني أن ...
  • أنها لا تعمل في التحليل الكلاسيكي . لكي تعمل هذه الخوارزمية من الناحية النظرية ، تحتاج إلى الدخول في عالم رائع من الرياضيات غير الكلاسيكية! وإذا كان هذا لم يوقظ فضولك ، فلن أعرف ماذا أفعل.

هذه المقالة طويلة جدًا ونظرية ، لأنها تتطلب دراسة متعمقة للتفسيرات ، لذلك خذ وقتك وأعد قراءة الأجزاء التي بدت غير واضحة لك في المرة الأولى.

قليلا عن السياق (GPU)


أحد الجوانب المهمة التي يجب الانتباه إليها في تطوير الألعاب ، وبمعنى أوسع - في أي منطقة مع الاستخدام الفعال للرسومات - هو عرض النطاق الترددي لجرافيك. المعالج المركزي و GPU هما جهازان منفصلان ، ويحتاجان إلى التزامن لتبادل البيانات. إذا كنت قد قمت بالفعل بمعالجة متوازية ، فأنت تعلم أنه عندما يحتاج الجهازان إلى المزامنة ، فهذا يعني فقد قدر كبير من الوقت. لا يختلف تفاعل CPU-GPU في هذا الصدد ، لذلك نحن نسعى جاهدين لتقليل نقل البيانات ، سواء في عدد العمليات أو في كمية البيانات المنقولة.

عادة ما يتم إجراء تقليل عدد عمليات نقل البيانات باستخدام التخزين المؤقت: نحن نسعى جاهدين لملاءمة جميع البيانات في أصغر عدد ممكن من المصفوفات ، ثم نقل كل شيء مرة واحدة حتى لا نحتاج إلى القلق بشأنهم. يعد تقليل حجم البيانات في عمليات النقل موضوعًا مختلفًا تمامًا ، كما أن حلول هذه المشكلة دائمًا ما تكون فردية. وكمثال على ذلك ، يمكنك أن ترى كيف يدير محرك تقديم Destiny ليناسب الموضع ، والمعايير الطبيعية للسطح ، وعلامات المواد ، ومعلمات BSDF متباينة الخواص الكاملة 96 بت ، أي ثلاثة أرقام النقطة العائمة (ص 62 وما بعده). ومع ذلك ، يمكن تحقيق نتائج جيدة من خلال الطرق العامة ، التي يتم بعدها إضافة الحلول الفردية للتحسين.

اليوم سنناقش ضغط ضياع ناقلات 3D الفردية . تحتوي هذه الجملة على عدة كلمات رئيسية:

  • متجهات ثلاثية الأبعاد مفردة : متجهات ثلاثية الأبعاد ذات طول 1
  • ضغط ضياع : تقليل حجم أوصاف ناقلات ثلاثية الأبعاد واحدة دون فقدان الدقة. هذا هو عكس ضغط ضياع.
  • منفصل : يتم تنفيذ تشفير وفك تشفير المتجه بدون معلومات عن جيرانه. إذا كان الوضع عكس ذلك ، فقد يكون ذلك مثل ضغط الدُفعات ، حيث لا يتم ضغط الناقلات الفردية ، ولكن صفائفها

قبل الانتقال ، يجب أن أذكر المقالة الممتازة "مسح للتمثيلات الفعالة لمتجهات الوحدة المستقلة " التي أجراها Cigolle و Donow و Evangelakos و Mara و McGuire و Meyer ، والتي استلهمت منها مقالتي. يجب أن أقول على الفور أن الخوارزمية التي سأتحدث عنها أقل كفاءة من الخوارزمية الثمانية المقدمة في المقالة . إذا كنت تريد أقصى قدر من الكفاءة ، فاقرأ المقال واستخدم oct . الغرض من مشاركتي هو إظهار جمال استخدام الرياضيات غير المعتادة للغاية ، مع إنشاء ، كما سنرى لاحقًا ، خوارزمية ملائمة جدًا.

طوبولوجيا الحق في لعبة الفيديو الخاصة بك



في حالة المجال الكروي ، فقط θ و φ مهمان ، لأن ρ دائمًا 1 ، وبالتالي لا لزوم لهما.

تتمثل نقطة البداية في الخوارزمية في ملاحظة أن متجهات الوحدة ثلاثية الأبعاد تعادل النقاط الموجودة في الكرة. كما تعلمون ، الكرة هي سطح ثنائي الأبعاد ، أي ، من أجل التحديد الفريد للنقاط على الكرة ، لا يلزم سوى اثنين من الإحداثيات. مثال شائع على ذلك هو الإحداثيات الكروية ، حيث يتم تعريف نقطة على الكرة بواسطة زاويتين ، θ و φ.

ومن المثير للاهتمام أن خاصية غير سارة إلى حد ما هي أنه على الرغم من أن الكرة والساحة المملوءة (مساحة واحدة ممكنة للإحداثيات ثنائية الأبعاد) عبارة عن كائنات ثنائية الأبعاد ، إلا أنه لا توجد بالفعل مراسلات بينهما. هذا يعني أنه لا توجد وسيلة لربط نقطة فريدة على الكرة بكل نقطة فريدة من نوعها في المربع (على الأقل بطريقة مستمرة) ؛ يقال إنها غير متجانسة (بمعنى آخر ، أحدهما له حدود والآخر لا). والنتيجة غير السارة لذلك هي أن بعض الإحداثيات ثنائية الأبعاد تضيع ، بمعنى أن الإحداثيات المختلفة تتوافق مع نقاط متطابقة في الكرة (على سبيل المثال ، في حالة الإحداثيات الكروية ، عندما تكون φ تساوي 0 ، ستكون النقطة المقابلة هي القطب الشمالي ، بصرف النظر عن الإحداثي θ). فيما يتعلق بالضغط ، نفقد أنماط البت القيمة التي يمكننا من خلالها وصف نقاط الكرة!

إذا كنت تريد المزيد من الرياضيات وتريد أن تثبت أن المربع والكرة ليسا متماثلين ، فيمكنك استخدام حقيقة أن الكرة ، على عكس المربع ، غير قابلة للانقباض ، وتعد الانقباضة خاصية طوبولوجية ؛ يمكن أيضًا استخدام نظرية Borsuk-Ulam كدليل. أخبروني أيضًا أن مجموعات homotopy يمكن أن تساعد في الإثبات ، لكن هذا بالفعل خارج نطاق خبرتي.

ومع ذلك ، تنشأ هذه المشكلة ليس فقط مع الإحداثيات الكروية. أي تمثيل ثنائي الأبعاد مستمر لنقاط الكرة سيعاني منه. ومع ذلك ، تذكر هذا للمستقبل.

الإحداثيات الكروية لها أيضًا خصائص سيئة أخرى:

  • لديهم توزيع ضعيف على الكرة. إذا تم إنشاء إحداثيات كروية عشوائية وتحويلها مرة أخرى إلى نقاط ثلاثية الأبعاد ، فإنها تشكل مجموعات حول القطبين وستكون نادرة للغاية بالقرب من خط الاستواء. ويرجع ذلك إلى حقيقة أن المتجهات ثلاثية الأبعاد بالقرب من خط الاستواء ستكون أقل تمييزًا بدقة.


    توزيع على مجال من 10،000 الإحداثيات كروية موزعة بشكل موحد
  • التعبئة والتغليف والتفريغ مكلفة. للتعبئة (3D → 2D) ، هناك حاجة إلى acos عملية واحدة و atan2 واحدة ، وهي وظائف مثلثية معكوسة باهظة الثمن للغاية ، وللتعبئة (2D → 3D) عمليتين للتشغيل كوس وخطوتين عمليتين ، وهما بعيدتان عن الاقتصاد أيضاً.

راجع المقال أعلاه للتعرف على مقارنات أخرى للإحداثيات الكروية وطرق الضغط الأخرى.

مهمة الحفاظ على أنماط بت ... والسرعة


تتميز الطريقة التي سنأخذها في الاعتبار بميزة كبيرة - حسابه أسرع بكثير ، أي أكثر من ضعف المعيار الساذج غير الأمثل (تم اختباره على العبوة وتفريغ 10 ملايين ناقل عشوائي في C ++ في Visual Studio 19 على Intel Core i5 7th gen). بالإضافة إلى ذلك ، لا تحتوي الطريقة على تفرد ، أي أن كل نقطة معبأة تقابل نقطة مفرغة واحدة ، على عكس الإحداثيات الكروية المذكورة أعلاه.

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


قمنا "بتسوية" نصف الكرة الشمالي في القرص ، متجاهلين الإحداثي Z لكل نقطة (أو نخصص له قيمة 0).

لقد وجدنا طريقة لربط كل نقطة في نصف الكرة الشمالي بكل نقطة في قرص واحد. بعض النقاط الجديرة بالملاحظة:

  • القطب الشمالي يقع في (0 ، 0).
  • كل نقطة على حدود نصف الكرة تبقى كما هي. وبشكل أكثر تحديدًا ، يوجد في نصف الكرة والقرص نفس الحدود. هذا منطقي ، نظرًا لأن النقاط الموجودة على حدود نصف الكرة لديها Z = 0 ، أي عند تجاهل إحداثي Z ، لا نغير أي شيء.

ضغط القرص: مهمة معقدة بسيطة


البناء التالي يتطلب مقدمة صغيرة. فقط في حالة القول بأن الأرقام المعقدة هي امتداد لمساحة الأرقام الحقيقية (الأرقام العادية مثل 0 ، 1 ، 129 ، 43 ، pi ، 335/117 ، الجذر التربيعي 2 ، وما إلى ذلك) ، والذي يستخدم رقمًا خاصًا أسميته وهمي وحدة . تحتوي الأرقام المركبة على النموذج a + ib ، حيث a و b هي بعض الأرقام الحقيقية (على التوالي ، الأجزاء الحقيقية والخيالية) ، ولدي الخاصية i ² = -1. هذا يتيح لنا مطابقة الأرقام المعقدة بالنقاط على متن طائرة ثنائية الأبعاد. إذا أخذنا z عددًا معقدًا من النموذج z = a + ib ، فيمكننا تمثيل z كنقطة مع الإحداثيات ( a ، b ) على المستوى. يرمز Re (z) و Im (z) إلى وظائف استخراج "الجزء الحقيقي" و "الجزء التخيلي" للرقم المركب z .


الرقم المركب z وقيمه.

بالإضافة إلى الأجزاء الحقيقية والخيالية للرقم المركب ، يمكن أيضًا أخذ الطول والزاوية التي تشكلها مع المحور X في الاعتبار ، وهذا ما يسمى التمثيل القطبي . طول القطبية وزاوية القطبية هي القاعدة | z | وسيطة Arg (z) . خاصية مريحة لكلا التمثيلين هي أن إضافة أرقام معقدة تتم عن طريق إضافة الأجزاء الحقيقية والخيالية ، ويتم ضرب الأعداد المركبة بضرب المعايير وإضافة الوسيطات .

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


على اليسار توجد عدة أرقام معقدة في نصف القرص مع الجزء الحقيقي الإيجابي (إحداثي X). على اليمين هو نتيجة تربيع كل هذه النقاط. نصف القرص الآن يملأ القرص بأكمله!

ترتبط إحدى الخدع بـ "مضاعفة حجة": تعتمد على جانب المحور X الذي تكمن عليه النقطة. القاعدة مبينة أدناه.


يدور عدد معقد مع جزء تخيلي موجب (إحداثي Y) إلى اليسار ، بينما يدور رقم معقد مع جزء تخيلي سلبي (إحداثي Y) إلى اليمين.

كما في حالة الأعداد الحقيقية ، فإن الجذر التربيعي هو معكوس التربيع: بالنسبة للرقم المركب z المعطى ، فإن الجذر التربيعي (اثنان منهم) هو الأعداد c ، مثل c² = z . كما في حالة الأعداد الحقيقية ، إذا كانت c هي الجذر التربيعي لـ z ، فإن c هي أيضًا. تسمى تلك الخاصة بالأرقام c و -c ، التي تساوي الوسيطة نصف الوسيطة z ، القيمة الرئيسية للجذر التربيعي (يشبه ذلك أخذ الجذر التربيعي الموجب للرقم الحقيقي بدلاً من الجذر التربيعي السالب).

إذا كنت تفهم أنه عندما يكون الرقم المركب مربّعًا ، يتم تربيع المعيار الخاص به وتتضاعف حجهته ، فيمكنك بسهولة تخمين أن القيمة الرئيسية للجذر التربيعي تأخذ الجذر التربيعي من القاعدة وتقلل الوسيطة إلى النصف (مع اتباع القاعدة الموضحة أعلاه ، ولكن مع قلب الأسهم للأسفل) . كما في حالة التربيع ، عند أخذ الجذر التربيعي لرقم مركب مع قاعدة أقل من 1 ، تظل القاعدة أقل من 1 ؛ لذلك ، "يضغط" قرص الوحدة إلى نصف أرقامها الحقيقية الإيجابية.


على اليسار توجد عدة نقاط على قرص واحد. يظهر الجانب الأيمن نتيجة أخذ الجذر التربيعي لكل هذه النقاط. القرص كله يناسب الآن في نصف نفسه!

هذا هو أساس الخوارزمية: في الواقع ، نقوم بضغط قرص الوحدة بالكامل إلى نصف - النصف مع الجزء الحقيقي الإيجابي. كما تتذكر ، قمنا مؤخرًا بتسوية النصف العلوي من الكرة في قرص واحد ؛ الآن يستحق الأمر رؤية ما سنفعله به.

وضع كل ذلك معا


دعونا نلخص ما قمنا به للتو: لقد قمنا بتسوية نصف الكرة في قرص وحدة واحدة ، وتجاهل إحداثي Z لجميع نقاطه ، وقمنا بضغط قرص الوحدة إلى النصف الخاص به باستخدام الجزء الحقيقي الإيجابي باستخدام قيمة الجذر التربيعي الأساسي المعقدة. في الواقع ، لقد قمنا بتسوية نصف الكرة إلى نصف القرص! الآن مع بعض التغييرات ، يمكننا أن نفعل الشيء نفسه لضغط النصف المتبقي من الكرة في النصف المتبقي من القرص.

يتم تسطيح النصف السفلي من الكرة (جميع نقاط الكرة ذات إحداثي Z سلبي) بالمثل في قرص وحدة عن طريق إسقاط إحداثيات Z بشكل متكرر ، ولكن بالنسبة لجميع الأرقام المعقدة z في القرص ، فإننا نأخذ القيمة المقابلة للجذر التربيعي الرئيسي لـ z (أي ، نأخذ -c بدلاً من c ). نظرًا لأن القيمة الرئيسية للجذر التربيعي تحتوي دائمًا على جزء حقيقي إيجابي ، فإن القيمة المقابلة لها دائمًا جزء حقيقي سلبي ؛ في الواقع ، قمنا بتسوية النصف المتبقي من الكرة في النصف المتبقي من القرص ، وقد اكتملت الآن مرحلة الضغط!


خطوة ضغط كاملة. لاحظ أن نصفي الكرة الشمالي والجنوبي (الأزرق والبرتقالي) يتم تسويتهما في نسختين من قرص واحد ، ثم يتم ضغطهما في نصفين من قرص واحد.

خوارزمية الضغط هي كما يلي:

function packUnitVector(unit) disk = new Complex(unit.x, unit.y) packed = principalSquareRoot(disk) return unit.z < 0 ? -packed : packed 

وهكذا ، في ثلاثة سطور فقط من الكود الكاذب ، طبقنا النظرية كلها التي درسناها لإنشاء خوارزمية فعالة. إذا كانت بيئتك لا تحتوي على صيغة للقيمة الرئيسية للجذر التربيعي ، فيمكنك العثور عليها في ويكيبيديا (يجب إيلاء اهتمام خاص لاختيار علامة الجزء التخيلي). إليكم تطبيق C ++ المرجعي الذي أستخدمه في الكود:

 // Principal complex square root of 'x + iy' float2 csqrt(float x, float y) { float r = sqrt(x * x + y * y); return float2(sqrt((r + x) / 2), (y < 0 ? -1 : 1) * sqrt((r - x) / 2)); } 

ارجع


لقد تعاملنا مع الضغط ، والآن ننتقل إلى فك الضغط.

يتكون التفريغ بالترتيب العكسي لجميع خطوات الضغط:

  • نقوم بتوسيع كلا نصفي الإيجابية والسلبية للأجزاء المادية من قرص واحد إلى قرصين كاملين
  • تطابق كل قرص كامل مع نصف الكرة المقابل

باختصار ، نبدأ بالقيمة المحزومة لـ p ، ونضعها مربعة للرجوع إلى النقطة الموجودة على القرص التي تم الحصول عليها من أحد نصفي الكرة الأرضية ، ثم نستخدم علامة Re (p) لمعرفة أي نصف كرة يتم أخذ النقطة منه على القرص. باستخدام المعادلة x² + y² + z² = 1 ، والتي تحدد النقاط في مجال الوحدة ، يمكننا إعادة إنشاء الإحداثي Z المفقود للنقطة المحزومة.

تجدر الإشارة إلى أن حساب مربع القيمة المعبأة سوف يمنحنا دائمًا النقطة الصحيحة من القرص ، بغض النظر عن نصف الكرة الأولي (العلوي أو السفلي) ، لأن z² = (-z) ² .

خوارزمية الضغط هي كما يلي:

 function unpackUnitVector(packed): disk = packed * packed unit = new Vec3() unit.x = disk.real() unit.y = disk.imag() unit.z = sqrt(1 - unit.x * unit.x - unit.y * unit.y) * (packed.real() < 0 ? -1 : 1) return unit 

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

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

في الواقع ، خوارزمية لدينا لها عيب خطير: إنها تعمل على كل نقطة في المجال بأكمله ، باستثناء نقاط في نصف الكرة الشمالي مع Y = 0 و X <= 0 ، والتي ، عند التعبئة والتفريغ ، تتم مقارنتها عن طريق الخطأ بالنقطة المقابلة في نصف الكرة الشمالي.

والسبب في ذلك هو أنه عندما يتم تجاهل إحداثياتها Z ، فإن الرقم المركب المناظر يكون رقمًا حقيقيًا سالبًا ، ولا يحتوي على جزء وهمي. عندما نأخذ القيمة الرئيسية للجذر التربيعي لرقم حقيقي سالب ، فإننا بدورنا نحصل على رقم معقد خيالي تمامًا لا يحتوي على جزء حقيقي (وهذا مشابه لحقيقة أن القيمة الرئيسية للجذر التربيعي -1 تساوي i ). ثم نحاول الحفاظ على علامة Z بالتنسيق في الصفر.


مشكلة الشريط. يتم تعبئة النقاط ذات Y = 0 و X <= 0 في سطر من الأرقام وهمية بحتة مع أجزاء حقيقية لا يمكن تحديدها.

دعونا نرى ما يحدث عندما نجمع نقطتين من هذه النقاط (لا تنسَ أن x <= 0).

  |  نقطة الشمال |  نقطة الجنوب
  وحدة |  (x ، 0 ، z) |  (x ، 0 ، -z)
  القرص |  x + 0i |  س + 0 ط
 معبأة |  0 + √ (-x) i |  -0 - √ (-x) i 

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

انسى ما تعلمناه


في كل مجال وفرع من الرياضيات التي أعرفها ، يُفترض أن 0 = -0. يتبع هذا تعريف -a ، وهو عكس a ، موضحًا أن "-a هو الرقم الوحيد الذي يعطي 0 عند جمعها بـ" . نظرًا لأن 0 عنصر صفر أيضًا فيما يتعلق بالإضافة ( 0 + a = a + 0 = a ) ، فإن الشيء الوحيد الذي تحتاج إلى إضافته إلى 0 للحصول على 0 هو 0 نفسه.

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

هذا مهم للغاية بالنسبة لنا: يمكن استخدام قيمة الصفر لتخزين معلومات حول العلامة! في الواقع ، يتم تخزينه بشكل صحيح على أي حال. في حالتنا ، المشكلة هي أنه لا يقرأ بشكل صحيح. إذا نظرنا إلى السطر قبل الأخير في خوارزمية التفريغ ، فسنرى ما يلي:

 packed.real() < 0 ? -1 : 1 

تقرأ هذه العملية علامة الجزء الحقيقي من القيمة المعبأة لتحديد نصف الكرة الذي تنتمي إليه النقطة - الشمال أو الجنوب. ومع ذلك ، في حالة عندما تكون package.real () تساوي 0 أو -0 ، يتم تجاهل الحرف من قِبل عامل المقارنة وإرجاع عامل التشغيل الثلاثي دائمًا 1. الطريقة الصحيحة لقراءة الحرف هي طلب حقيقي لحالة بت الإشارة ، على سبيل المثال ، باستخدام std :: signbit من C ++ أو np .signbit من Numpy إلى Python - الوظيفة تعتمد على اللغة. تذكر أن بت الإشارة هي 1 عندما يكون الرقم سالباً ، و 0 عندما يكون الرقم موجبًا.

وبالتالي ، نحصل على وظيفة تصحيح مائة في المئة والعمل:

 function unpackUnitVector(packed): disk = packed * packed unit = new Vec3() unit.x = disk.real() unit.y = disk.imag() unit.z = sqrt(1 - unit.x * unit.x - unit.y * unit.y) * (signbit(packed.real()) ? -1 : 1) return unit 

هذا كل شئ! الآن الخوارزمية كاملة. تتجلى الرياضيات غير الكلاسيكية في حقيقة أننا نستخدم حقيقة أن 0 تختلف عن -0 ، وهذا خطأ بالنسبة لجميع مجالات الرياضيات التي أعرفها. ومع ذلك ، هناك طريقة لجعل هذا الغرابة منطقياً بالمعنى النظري الصارم رياضياً.

المساحات التي لا تلعب بها القواعد: خط مستقيم مع نقطتين أصليتين


لفهم ما يلي بشكل أفضل ، يجب أن تعرف مفاهيم فئات التكافؤ والأحياء. هذا اختياري ، لكنه سيكون أكثر وضوحًا.

يمكننا أن نضمن اتساق هذا الغريب مع "علامة الصفر" ، بدءًا من مساحة طوبولوجية مثيرة للاهتمام: خط مستقيم مع نقطتين أصليتين.


الخط المستقيم ذو النقطتين الأصليتين هو محور عددي حقيقي عادي ، والذي نما بطريقة أو بأخرى صفر إضافي لنفسه.

يتم الحصول على خط مستقيم بنقطتين أصليتين عندما نأخذ محورين عدديين حقيقيين ولصق كل رقم بعكسه ، باستثناء 0. من الناحية الرسمية ، يكون الخط المستقيم ذو النقطتين الأصليتين عبارة عن مسافة حاصل عليها R² مع وجود علاقة تكافؤ تحدد رقمين إذا كانا متساوين و ليست 0. والنتيجة هي خط مستقيم من الأرقام الحقيقية مع اثنين من الأصفار مختلفة متساوية من أي نقطة ، ولكن في الوقت نفسه مختلفة عن بعضها البعض. رسميا ، أي حيين من كل من الأصفار دائما تقاطع غير فارغ.

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

وفي الواقع ، لم نجد انحرافًا (رسمًا واحدًا لواحد) بين الكرة وقرص الوحدة ، ولكن وجدنا انحرافًا بين الكرة وقرص الوحدة مع نقطتي المنشأ. لم أتحقق مما إذا كان هذا التناقض يمثل تماثلًا متماثلًا (التماثل التعددي هو التناقض المستمر في كلا الاتجاهين) ، لكن ربما سأفعل ذلك في يوم من الأيام.

قليلا من الطوبولوجيا في النهاية


في الختام ، أود أن أؤكد أنه على الرغم من أن الطائرة المعقدة التي استخدمناها بنقطتين أصليتين لا تتبع نفس البنية مثل الخط المستقيم ذي الأصلين ، في الواقع ، فهي تعادل مستوى الطائرة المعقدة الأخرى مع نقطتي المنشأ مشابهتين لخط مستقيم مع أصلان.

في حالة وجود خط مستقيم بنقطتين أصليتين ، قمنا بلصق نسختين من المحور العددي الحقيقي في جميع الأماكن باستثناء 0. يمكننا أن نفعل الشيء نفسه مع نسختين من المستوى المركب ، ونجمع كل زوج من الأعداد المركبة المتساوية التي ليست 0 ، وبالمثل نحصل على تعقيد طائرة مع نقطتين المنشأ. يختلف هذا البناء عن بناء طائرة معقدة جديدة من خط مستقيم بنقطتين أصليتين ومحور رقمي حقيقي حقيقي: الأول هو عامل مساحة ، والأخير هو نتاج مسافات. ومع ذلك ، فإن الاختلاف الوحيد بين الفراغين الناتجين هو طريقة كتابة أصفار مختلفة في كل مسافة: في البداية يتم حسابها على أنها ( 0 + 0i) و ( 0 + 0i) b (اثنين من الأصفار مأخوذان من مسافتين مختلفتين لا يتم لصقهما معًا) ، وفي الأخير يتم قراءتها كـ (0a + 0i) و (0b + 0i) . في الواقع ، كلا المساحات متماثلان ، بحيث يمكنك استخدام أحدهما بأمان عند الحاجة إلى الآخر.

استنتاج


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

Source: https://habr.com/ru/post/ar482348/


All Articles