أساسيات تنسيق GLTF و GLB ، الجزء 1

ما هي GLTF و GLB؟


GLTF (GL Transmission Format) هو تنسيق ملف لتخزين المشاهد والنماذج ثلاثية الأبعاد ، وهو سهل الفهم للغاية (الهيكل مكتوب في معيار JSON) ، قابل للتوسيع ويتفاعل بسهولة مع تقنيات الويب الحديثة. يضغط هذا التنسيق على المشاهد ثلاثية الأبعاد جيدًا ويقلل معالجة وقت تشغيل التطبيقات باستخدام WebGL وواجهات برمجة التطبيقات الأخرى. يتم الترويج لـ GLTF بنشاط من قبل مجموعة Khronos كـ JPEG من العالم ثلاثي الأبعاد. يستخدم GLTF الإصدار 2.0 حاليا. يوجد أيضًا إصدار ثنائي لهذا التنسيق يسمى GLB ، والفرق الوحيد هو أن كل شيء يتم تخزينه في ملف واحد بملحق GLB.


هذا المقال جزء 1 من 2. في ذلك ، سوف ننظر في هذه التحف الفنية وخصائصها مثل Scene و Node و Buffer و BufferView و Accessor و Mesh . وفي المقالة الثانية سوف نلقي نظرة على البقية: المواد والملمس والرسوم المتحركة والجلد والكاميرا. يمكن العثور على مزيد من معلومات التنسيق العامة هنا .
إذا كنت ترغب في العمل شخصيًا مع هذا التنسيق أثناء عرض مقال ، يمكنك تنزيل نماذج GLTF 2.0 من مستودع Khronos الرسمي على GitHub


صورة


القضية وحلها


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


صورة

حاليًا ، يتم استخدام GLTF وشقيقها الثنائي GLB كتنسيقات موحدة في برامج CAD (Autodesk Maya و Blender ، وما إلى ذلك) ، في محركات الألعاب (Unreal Engine و Unity وغيرها) وتطبيقات AR / VR والخدمات الاجتماعية. الشبكات ، الخ


ذكر ممثلو مجموعة خرونوس ما يلي:


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

تنسيق النظام والوحدات


يستخدم GLTF نظام الإحداثيات الأيمن ، أي المنتج المتقاطع لـ + X و + Y يعطي + Z ، حيث + Y هو المحور العلوي. تواجه واجهة أصل 3D GLTF محور + Z. وحدات القياس لجميع المسافات الخطية هي متر ، ويتم قياس الزوايا بالراديان ، والدوران الإيجابي للأجسام عكس اتجاه عقارب الساعة. تعد تحويلات العقدة ومسارات قنوات الرسوم المتحركة متجهات ثلاثية الأبعاد أو رباعيات لها أنواع البيانات ودلالاتها التالية:


الترجمة : متجه ثلاثي الأبعاد يحتوي على الترجمة على طول المحاور x و y و z
الدوران : رباعي (س ، ص ، ض ، ث) ، حيث ث هو عدد
scale : متجه ثلاثي الأبعاد يحتوي على عوامل قياس x و y و z
صورة


GLTF - نظرة من الداخل


كما ذكر أعلاه ، يتكون GLTF ، كقاعدة عامة ، من ملفين: الأول بتنسيق .gltf ، الذي يخزن بنية المشهد ثلاثي الأبعاد في شكل JSON والملف الثاني بتنسيق .bin ، الذي يخزن مباشرة جميع بيانات هذا المشهد.


بنية التنسيق هرمية تمامًا ولها النموذج التالي:


صورة


للتحدث أكثر عن الهيكل ، سأستخدم أمثلة لأبسط ملف GLTF ، الذي يخزن مثلثًا أحادي الجانب مع المادة الافتراضية. إذا كنت تريد ، فيمكنك نسخه ولصقه في أي عارض GLTF "ليشعر" بمحتويات الملف شخصيًا. في ممارستي ، كنت أستخدم أخرى مختلفة ، لكنني استقرت على هذا ، والذي يستخدم Three.js تحت الغطاء. سيكون الخيار الجيد أيضًا هو استخدام Visual Studio Code مع البرنامج المساعد GLTF. لذلك سيكون لديك خيار على الفور من 3 محركات: Babylon.js ، Cesium ، Three.js


عناصر المشهد والعقدة


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


{ "scenes" : [ { "nodes" : [ 0 ] } ], "nodes" : [ { "mesh" : 0 } ], "scene": 0 

كل عقدة هي "نقطة دخول" لوصف الكائنات الفردية. إذا كان الكائن معقدًا ويتألف من عدة شبكات ، فسيتم وصف هذا الكائن من خلال العقد "الأصل" و "التابع". على سبيل المثال ، يمكن وصف السيارة ، التي تتكون من جسم وعجلات ، على النحو التالي: العقدة الرئيسية تصف السيارة ، وعلى وجه الخصوص جسمها. تحتوي هذه العقدة على قائمة "العقد الفرعية" ، والتي بدورها تصف المكونات المتبقية ، مثل العجلات على سبيل المثال. ستتم معالجة جميع العناصر بشكل متكرر. يمكن أن تحتوي العقد على رسوم متحركة لـ TRS (الترجمة ، الدوران ، المقياس المسمى الإزاحة ، التدوير ، القياس). بالإضافة إلى حقيقة أن هذه التحولات تؤثر بشكل مباشر على الشبكة نفسها ، فإنها تؤثر أيضًا على العقد الفرعية بنفس الطريقة تمامًا. بالإضافة إلى كل ما سبق ، أعتقد أنه من الجدير بالذكر أن "الكاميرات" الداخلية ، إن وجدت ، المسؤولة عن عرض الكائن في الإطار للمستخدم ، يتم إرفاقها أيضًا بكائن Node. تشير الكائنات إلى بعضها البعض باستخدام السمات المناسبة: مشهد له سمة عقدة ، كائن عقدة لديه سمة شبكة. لفهم أبسط ، تم توضيح كل ما سبق في الشكل التالي.


صورة


المخزن المؤقت ، BufferView والملحق


كائن المخزن المؤقت يعني تخزين البيانات الثنائية ، غير المجهزة ، بدون بنية ، بدون وراثة ، بدون قيمة. يقوم المخزن المؤقت بتخزين معلومات حول الهندسة والرسوم المتحركة والتسلق. الميزة الرئيسية للبيانات الثنائية هي أنه يتم معالجتها بكفاءة عالية بواسطة GPU ، كما لا تحتاج إلى تحليل إضافي ، باستثناء ، ربما ، إلغاء الضغط. يمكن العثور على البيانات الموجودة في المخزن المؤقت بواسطة سمة URI ، مما يوضح بوضوح مكان وجود البيانات وهناك فقط خياران: إما أن يتم تخزين البيانات في ملف خارجي بتنسيق .bin ، أو تكون مضمنة داخل JSON نفسها. في الحالة الأولى ، يحتوي URI على ارتباط إلى ملف خارجي ، وفي هذه الحالة ، يعتبر المجلد الذي يوجد به ملف GLTF هو الجذر. في الحالة الثانية ، سيكون للملف تنسيق .glb ، والذي يشير بنا إلى التنسيق أكثر ، من حيث عدد الملفات ، GLTF twin brother ، تنسيق GLB. يتم تخزين البيانات في الملف الثنائي كما هي ، بايت بايت.



ستبدو JSON في مثال المثلث الخاص بنا كما يلي:
مثال على base64 ترميز المخزن المؤقت:


 "buffers" : [ { "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAA=", "byteLength" : 44 } ], 

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


 "buffers" : [ { "uri" : "duck.bin", "byteLength" : 102040 } ], 

تحتوي كتلة Buffers أيضًا على سمة بايت إضافية ، والتي تخزن قيمة حجم المخزن المؤقت.


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


  "bufferViews" : [ { "buffer" : 0, "byteOffset" : 0, "byteLength" : 6, "target" : 34963 }, { "buffer" : 0, "byteOffset" : 8, "byteLength" : 36, "target" : 34962 } ], 

كما ترون ، يحتوي هذا المثال على 4 سمات رئيسية:


  1. يشير المخزن المؤقت إلى فهرس المخزن المؤقت (رقم التسلسل في صفيف المخزن المؤقت يبدأ في 0).
  2. يحدد byteOffset "التحول" في الأصل بالبايت لهذه الشريحة
  3. byteLength - يحدد طول "الشريحة"
  4. الهدف - يحدد نوع البيانات الموجودة في bufferView
    يحتوي BufferView الأول على أول 6 بايتات من المخزن المؤقت ولا يحتوي على أي تغيير. مع "الشريحة" الثانية ، كل شيء أكثر تعقيدًا: كما ترون ، تحوله في البايت الثامن ، بدلاً من الباقي السادس. هذه البايتات 2 فارغة وتمت إضافتها أثناء عملية إنشاء المخزن المؤقت بفضل عملية تسمى "الحشو". من الضروري أن تقوم القيمة بضبط قيمة بايت الحدود إلى 4 بايت. هذه الخدعة ضرورية لقراءة البيانات بشكل أسرع وأسهل من المخزن المؤقت.

صورة


تجدر الإشارة إلى بضع كلمات حول السمة الهدف. يتم استخدامه لتصنيف نوع المعلومات المشار إليها بواسطة bufferView. لا يوجد سوى خياران: إما ستكون القيمة 34962 ، والتي تُستخدم للإشارة إلى سمات الرأس (سمات الرأس - 34962 - ARRAY_BUFFER) أو 34963 ، والتي تُستخدم لمؤشرات قمة الرأس (مؤشرات قمة الرأس - 34963 - ELEMENT_ARRAY_BUFFER). إن اللمسة الأخيرة لفهم وتنظيم جميع المعلومات في المخزن المؤقت هي كائن Accessor.


Accessor هو كائن يصل إلى BufferView ويحتوي على سمات تحدد نوع وموقع البيانات من BufferView. يتم تشفير نوع بيانات الموصل في النوع و componentType. قيمة السمة type عبارة عن سلسلة ولها القيم التالية: SCALAR للقيم العددية ، VEC3 للناقلات ثلاثية الأبعاد و MAT4 لمصفوفة 4 × 4 أو رباعي ، والذي يستخدم لوصف التدوير.


ComponentType ، بدوره ، يشير إلى نوع مكون هذه البيانات. هذا هو ثابت GL ، والذي يمكن أن يحتوي على قيم مثل 5126 (FLOAT) أو 5123 (UNSIGNED_SHORT) ، على سبيل المثال ، للإشارة إلى أن العناصر تحتوي على نقطة عائمة ، إلخ.


يمكن استخدام مجموعات مختلفة من هذه الخصائص لوصف أنواع البيانات التعسفية. مثال على أساس المثلث لدينا.


  "accessors" : [ { "bufferView" : 0, "byteOffset" : 0, "componentType" : 5123, "count" : 3, "type" : "SCALAR", "max" : [ 2 ], "min" : [ 0 ] }, { "bufferView" : 1, "byteOffset" : 0, "componentType" : 5126, "count" : 3, "type" : "VEC3", "max" : [ 1.0, 1.0, 0.0 ], "min" : [ 0.0, 0.0, 0.0 ] } ], 

دعنا نحلل السمات الممثلة في JSON:


  1. bufferView - يشير إلى رقم تسلسل BufferView من صفيف BufferView الذي يستخدمه Accessor. BufferView ، بدوره ، يخزن معلومات حول الفهارس.
  2. byteOffset - تحول البايت لبدء قراءة البيانات من Accessor الحالي. يمكن الوصول إلى كائنات Accessor متعددة BufferView واحد.
  3. componentType هو ثابت يشير إلى نوع العناصر. يمكن أن تحتوي على قيم 5123 ، والتي تتوافق مع نوع البيانات UNSIGNED_SHORT ، أو 5126 لـ FLOAT.
  4. عدد - يعرض عدد العناصر المخزنة في المخزن المؤقت.
  5. النوع - يحدد نوع البيانات: العددية ، المتجه ، المصفوفة.
  6. الخصائص القصوى والدقيقة التي تحدد الحد الأدنى والحد الأقصى لقيمة موضع هذه العناصر في الفضاء.

شبكة


يحتوي كائن Meshes على معلومات حول الشبكات الموجودة في المشهد. يمكن تخزين عقدة واحدة (كائن عقدة) شبكة 1 فقط. يحتوي كل كائن من النوع mesh على صفيف من type mesh.primitive ، بدوره ، البدائيون هم كائنات بدائية (على سبيل المثال ، مثلثات) تتكون منها الشبكة نفسها. يحتوي هذا الكائن على العديد من السمات الإضافية ، ولكن يخدم كل هذا غرضًا واحدًا - التخزين الصحيح للمعلومات حول عرض الكائن. السمات الرئيسية للشبكة:


  1. الموقع - موضع الرؤوس على طول محاور XYZ
  2. عادي - تطبيع XYZ Vertex Normals
  3. الظل - XYZW الظل من الرؤوس. يشير W إلى مكان توجيه الظل ويكون له قيمة إما +1 أو -1.
  4. TEXCOORD_0 - إحداثيات نسيج الأشعة فوق البنفسجية. عدة مجموعات يمكن تخزينها.
  5. COLOR_0 - ألوان RGB أو RGBA من القمم.
  6. JOINTS_0 - تحتوي هذه السمة على فهارس المفاصل / المفاصل من مجموعة المفاصل المقابلة ، والتي يجب أن تؤثر على قمة الرأس (قمة الرأس).
  7. WEIGHTS_0 - تحدد بيانات هذه السمة الأوزان التي تشير إلى مقدار تأثير المفصل على الرأس.
  8. الأوزان - السمة المسؤولة عن تحوير الأوزان.
  9. المواد - تحتوي على الفهرس ، وهو عدد المواد في مجموعة المواد

سيكون لهذا الكائن النموذج التالي لحالتنا:


  "meshes" : [ { "primitives" : [ { "attributes" : { "POSITION" : 1 }, "indices" : 0 } ] } ], 

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


استمرار في الجزء الثاني: https://habr.com/en/post/448298/

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


All Articles