जनरेट किए गए मेश में छेद कहाँ से आते हैं
Oleg Sidorkin, Cinevva के CTO और सह-संस्थापक द्वारा

मैंने TRELLIS.2 से एक पक्षी जनरेट किया, उसे रिग किया, और जैसे ही एनीमेशन चला, दोनों पंखों के नीचे छेद दिखाई देने लगे। ऐसी चमकीली झिर्रियाँ, जिनसे शरीर के आर-पार सीधे देखा जा सकता था। सबसे पहले रिगर को दोष मिला, और उसमें अपनी एक समस्या थी भी, लेकिन किसी भी हड्डी के मेश को छूने से पहले ही उसमें छेद मौजूद थे। यह पोस्ट उसके बाद हुई जाँच के बारे में है: ये छेद असल में क्या हैं, वे नौ चीज़ें जिन्होंने इन्हें ठीक नहीं किया, वे क्यों नाकाम रहीं, और वह एक चीज़ जिसने काम किया। मैं जानबूझकर नाकाम कोशिशें भी शामिल कर रहा हूँ। उनमें से अधिकतर वही स्पष्ट उपाय हैं जिन्हें आप पहले आज़माते, और हर एक से हमें कुछ ऐसा पता चला जिस पर अंतिम समाधान निर्भर था।
पहला चरण: तय करें कि छेद किसे कहेंगे
हमारे मेश चेकर ने शून्य बाउंड्री एज रिपोर्ट किए, और रे-पैरिटी टेस्ट के अनुसार सतह बंद थी। इसलिए मैंने टीम से कहा कि मेश साफ़ है। वह साफ़ नहीं था, और जिस व्यक्ति ने झिर्रियों को लाल रंग से चिह्नित किया था, उसका इस बात पर ज़ोर देना सही था। कोई मेश बंद होते हुए भी उसमें सुरंगें हो सकती हैं। इन्हें पकड़ने वाला एकमात्र माप यूलर कैरेक्टरिस्टिक है—V घटा E जमा F—जो हर शेल में हैंडल की संख्या देता है। पक्षी में ऐसे 69 हैंडल थे। एक्सपोर्ट में हर दीवार दोहरी थी, इसलिए बाहरी दीवार की कोई दरार यदि उसके पीछे की कैविटी से जुड़ती है, तो वह खुला हिस्सा नहीं बल्कि एक हैंडल है, और खुली एज खोजने वाला कोई भी तरीका उसे कभी नहीं देख पाएगा।
दूसरा सबक, जो थोड़ा अधिक शर्मनाक था: मैंने कुछ समय तक गहरे पिक्सेलों में छेद खोजे, क्योंकि छेद गहरे होते हैं, जब तक कि मुझसे पहले तस्वीर देखने को नहीं कहा गया। छेद चमकीले थे। वे धूसर मोड़ के पार दिखाई दे रही दूर वाली दीवार की हरी टेक्सचर की झिर्रियाँ थीं। जिस एल्गोरिदम को आपने सही चीज़ पर लक्षित ही नहीं किया, वह आपको कुछ नहीं बताता, और उसे सही दिशा दिखाने का सबसे सस्ता तरीका है—खुद देखकर जाँचना।
दूसरा चरण: पता लगाएँ कि वे किस चरण में बनते हैं
TRELLIS.2 तीन चरणों में मेश बनाता है। एक डिकोडर 1024 क्यूब्ड रेज़ोल्यूशन पर कच्ची सतह निकालता है। फिर नैरो-बैंड ड्यूल कॉन्टूरिंग पास उसे रीमेश करता है। इसके बाद एक डेसिमेटर उसे घटाकर एक लाख फेस तक लाता है और टेक्सचर बेक की जाती है। हमने हर चरण के बाद ज्योमेट्री डंप की और हर बार पंख की जड़ से किरणों का वही बंडल गुज़ारा।
समस्या कच्ची सतह से ही शुरू होती है। वह खुली शीटों का ढेर है: 266,242 बाउंड्री लूप, जिनमें से अधिकतर एक गायब क्वाड के बराबर हैं, और 65,371 नॉन-मैनिफोल्ड एज। पंख की जड़ पर परीक्षण की एक-तिहाई किरणें सीधे आर-पार निकल गईं। इसके बाद चलने वाला होल-फिल लगभग कुछ भी बंद नहीं करता—पचास लाख में से केवल 144 फेस। रीमेशर अनसाइन्ड डिस्टेंस फील्ड पर काम करता है, क्योंकि उसके पास और कोई विकल्प नहीं है। उसके पास काम करने के लिए अंदर या बाहर की जानकारी नहीं होती, इसलिए वह हर शीट के चारों ओर एक पतला ऑफसेट शेल लपेट देता है। इसी कारण हर दीवार दोहरी होती है, लगभग चार वॉक्सेल की दूरी पर, और इसी तरह हर छिद्रपूर्ण पट्टी एक ऐसे मोड़ में बदल जाती है जिसमें दरार होती है। फिर डेसिमेशन इसे और खराब करता है, वह भी अनियमित रूप से: उसी कच्चे मेश को दो बार डेसिमेट करने पर 69 और 107 सुरंगें मिलीं।

वह मैप पहला वास्तविक सुराग था। छिद्रयुक्त क्षेत्र बेतरतीब नहीं हैं। वे हिस्सों के बीच हर जंक्शन पर मौजूद हैं और कहीं नहीं।
वे चीज़ें जिन्होंने काम नहीं किया
हमने उन्हें लगभग इस क्रम में आज़माया कि वे कितनी स्पष्ट लगती थीं।
| प्रयास | परिणाम |
|---|---|
| 1024 के बजाय 1536 रेज़ोल्यूशन | पाँच परीक्षण मॉडल में से तीन पर परिणाम बदतर रहा। अधिक रेज़ोल्यूशन अधिक पतले संपर्कों को हल करता है, और हर संपर्क एक नया जंक्शन बन जाता है |
| बिल्ट-इन क्लीनअप लैडर | नॉन-मैनिफोल्ड एज कम होने के बजाय बढ़ गए |
| MeshLib से हर छोटे छेद को भरना | 266k लूप भरे गए, लेकिन पंख की जड़ नहीं बदली। वहाँ स्किन कभी निकाली ही नहीं गई थी, इसलिए भरने के लिए कोई लूप नहीं था |
| वाइंडिंग नंबर से साइन्ड रीमेश | मेश टूटकर हज़ारों शेल में बिखर जाता है। कच्चे आउटपुट में साइन निर्धारित करने के लिए कोई इंटीरियर नहीं है |
| 2 और 3 वॉक्सेल का अधिक चौड़ा कॉन्टूरिंग बैंड | कुल सुरंगें कम हुईं, लेकिन दरार संकरी होने के बजाय चौड़ी हो गई। छोटी सुरंगें मिलकर बड़ी बन जाती हैं |
| वॉक्सेल संरचना की मॉर्फोलॉजिकल क्लोज़िंग | शेल ठोस हो जाता है, फिर डिकोडर हर आंतरिक वॉक्सेल के भीतर सतह निकालता है—चार गुना फेस और 969 सुरंगें |
| अंतिम मेश का ग्लोबल वॉक्सेल रीमेश | जीनस 0 और दरार सील हो गई। साथ ही हर पंख का किनारा मुलायम पड़ गया। देखते ही इसे अस्वीकार कर दिया गया—और सही किया गया |
| डिकोडर के क्रॉसिंग थ्रेशोल्ड को बायस करना | ओपन एज 65k से घटकर 58k। केवल शोर |
| गायब पड़ोसी वॉक्सेल पूरे करना | पूरे पक्षी में केवल 560 मामले। केवल शोर |

ग्लोबल क्लोज़िंग पर थोड़ा और ध्यान देना ज़रूरी है, क्योंकि कोई मॉडलर सबसे पहले यही उपाय अपनाता: गैप से थोड़ा बड़ा आकार चुनकर वॉक्सेल रीमेश कर देना। टोपोलॉजी के स्तर पर यह काम करता है। लेकिन यह मॉडल के बारे में एक झूठ भी है। जनरेटर ने पंखों के तीखे किनारे बनाए थे और हम सील की हुई पंख-जड़ के बदले उन्हें खो देते। नौ प्रयासों में से दो ने सुरंगों की संख्या घटाई, और जैसे ही किसी ने संख्या के बजाय पक्षी को देखा, दोनों को अस्वीकार कर दिया गया।
कोड पढ़ना
उस समय एकमात्र ईमानदार कदम यह था कि डिकोडर को ब्लैक बॉक्स मानना बंद किया जाए और पढ़ा जाए कि उसका आउटपुट मेश में कैसे बदलता है। TRELLIS.2, O-Voxel नामक रिप्रेज़ेंटेशन का उपयोग करता है, और उसका एक्सट्रैक्शन छोटा है। हर सक्रिय वॉक्सेल में एक ड्यूल वर्टेक्स और तीन लॉजिट होते हैं—उसके कोने से निकलने वाली हर ग्रिड एज के लिए एक—और हर लॉजिट का अर्थ है, "सतह इस एज को पार करती है।" शून्य से अधिक लॉजिट उस एज के चारों ओर मौजूद चार वॉक्सेल को जोड़ने वाला क्वाड निकालता है। यदि चार में से कोई एक भी गायब हो, तो क्वाड बिना किसी सूचना के हटा दिया जाता है। बस इतना ही। मॉडल में कहीं भी कोई साइन फील्ड, ऑक्यूपेंसी, अंदर या बाहर की जानकारी नहीं है।
हमने डिकोडर को पैच किया ताकि वह थ्रेशोल्ड से पहले उन्हीं लॉजिट को, उसी पक्षी पर, डंप करे, और फिर हमने उनकी गिनती की।
गायब पड़ोसी: 27 लाख वॉक्सेल में से 560। शून्य के पास मौजूद लॉजिट: 80 लाख में से 8,600। इनमें से कोई भी असली समस्या नहीं है। समस्या तब दिखाई देती है जब आप हर ग्रिड फेस के चारों ओर की चार एज देखते हैं। कोई बंद सतह किसी फेस की बाउंड्री को सम संख्या में पार करती है। 126,542 फेस पर—कुल का 2.3%—चारों फ्लैग एक-दूसरे से असहमत हैं, और परिभाषा के अनुसार हर विषम फेस एक ओपन या नॉन-मैनिफोल्ड एज है। और उनकी असहमति बहुत आत्मविश्वासपूर्ण है। काउंट-वन फेस पर अकेला फ्लैग +10 लॉजिट पर होता है, जबकि उसके पड़ोसी -4 पर होते हैं। एक फ्लैग पलटकर पैरिटी बहाल करने की माध्यिका लागत 2.3 लॉजिट है। यह केवल थोड़ा गलत थ्रेशोल्ड नहीं है। मॉडल ऐसी सतह के बारे में आश्वस्त है जो बंद हो ही नहीं सकती।

फिर हमने उसी सतह-बिंदु पर पट्टी को मापा, जिसे हमारा स्थिर कैमरा पूरे सप्ताह देख रहा था। उसके बारह वॉक्सेल के भीतर, एक सपाट शीट के लिए आवश्यक सक्रिय वॉक्सेलों से 2.1 गुना अधिक सक्रिय वॉक्सेल हैं। तुलना के लिए, छाती पर यह अनुपात 1.2 है। पंख की निचली सतह और शरीर—दो स्किन—एक ही वॉक्सेल परत के भीतर चल रहे हैं। इस रिप्रेज़ेंटेशन में हर वॉक्सेल के लिए केवल एक वर्टेक्स है, इसलिए यह दोनों को रख ही नहीं सकता। ट्रेनिंग के दौरान ऐसे वॉक्सेल का ग्राउंड ट्रुथ दोनों स्किन का लीस्ट-स्क्वेयर औसत होता है, साथ में "कोई भी क्रॉसिंग" फ्लैग, जो अपने आप में असंगत है। इसलिए मॉडल ने पूरी निष्ठा से वहाँ कंघी जैसी संरचना निकालना सीख लिया है। रीमेशर उस कंघी को लपेटकर स्लैब बना देता है, और उस स्लैब में सुरंगें होती हैं।
पट्टी की चौड़ाई ज्योमेट्री से निकलती है: लगभग एक वॉक्सेल को संपर्क कोण के टैनजेंट से भाग देने पर। नब्बे डिग्री पर मिलने वाली दो सतहें एक-वॉक्सेल की सिलवट बनाती हैं और कोई समस्या नहीं होती। शरीर पर सपाट पड़ा पंख, पंख पर पंख, ज़मीन पर पंजों की उँगलियाँ—ये सभी दस या पंद्रह वॉक्सेल चौड़ी पट्टी बनाते हैं। इसी से छिद्रयुक्तता का मैप समझ में आता है।
मैंने सैद्धांतिक रूप से सही रिपेयर भी आज़माया: हर कोने के लिए अंदर/बाहर का ऐसा साइन अनुमानित करना जो फ्लैग को सबसे अच्छी तरह समझाए, और फिर उनसे फ्लैग दोबारा बनाना। यह काम नहीं कर सकता। साइन फील्ड केवल डिकोडर द्वारा निकाले गए एक-वॉक्सेल शेल पर मौजूद है, और उस शेल से बाहर किया गया कोई भी विस्तार अनियंत्रित हो जाता है। इसके बारह राउंड ने बेकार डेटा के साथ वॉक्सेल संख्या दोगुनी कर दी।
कोई मॉडलर क्या करता
कोई मॉडलर दो स्किन को बाल जितनी दूरी पर कभी नहीं छोड़ता। वह पंख को शरीर में यूनियन कर देता और वहाँ एक सिलवट रहने देता। ग्लोबल क्लोज़िंग हर जगह यही करती है, और वही समस्या है। इसलिए इसे केवल वहीं करें जहाँ दोनों स्किन मौजूद हैं।
डिटेक्टर के पीछे का विचार एक पंक्ति में है। चार वॉक्सेल के भीतर हर वॉक्सेल के सक्रिय पड़ोसियों की गिनती करें। एकल शीट पर यह संख्या हर जगह समान होती है और वही माध्यिका होती है। जहाँ दो शीट एक ही परत साझा करती हैं, वहाँ यह लगभग दोगुनी होती है। माध्यिका के 1.5 गुना से अधिक हर मान को फ़्लैग करें, फ़्लैग किए गए सेट को एक वॉक्सेल बढ़ाएँ, और हर स्थान पर एक यूनिट क्यूब रख दें। दोनों स्किन के बीच की जगह ठोस हो जाती है, कॉन्टूरिंग पास को एक ही दीवार दिखाई देती है, और मॉडल के किसी अन्य हिस्से को छुआ नहीं जाता।

हमने पहले एक क्रॉप पर इसका परीक्षण किया, जहाँ GPU कॉन्टूरिंग की जगह MeshLib इस्तेमाल किया गया। तिरपन शेल और उन्नीस हैंडल घटकर दो शेल और पाँच रह गए। फिर हमने इसे वास्तविक पाइपलाइन में, डिकोडर और एक्सपोर्ट के बीच, जोड़ा और उसी पक्षी को वास्तविक रीमेशर और वास्तविक टेक्सचर बेक से गुज़ारा।

| सुरंगें | नॉन-मैनिफोल्ड एज | पंख की जड़ का फ्लैप | पीठ पर छेद | |
|---|---|---|---|---|
| जैसा है वैसा | 79.5 | 318 | मौजूद | मौजूद |
| फिल, त्रिज्या 3 | 84.5 | 97 | गायब | गायब |
| फिल, त्रिज्या 4 | 72 | 38 | गायब | गायब |
फ्लैप गायब हो गया है। पक्षी की पीठ पर दूसरा छेद भी गायब है—पीछे से दिखाई देने वाला वही जंक्शन—जिसका मैं पीछा भी नहीं कर रहा था। पंख अलग रहते हैं, पंजों की उँगलियाँ अलग रहती हैं, टेक्सचर सामान्य रूप से बेक होती है क्योंकि क्यूब शेल के अंदर वहाँ मौजूद हैं जहाँ एट्रिब्यूट वॉल्यूम में पहले से डेटा है। चार मिनट के काम में इससे छह सेकंड जुड़ते हैं। अब यह डिफ़ॉल्ट रूप से चालू है, त्रिज्या चार के साथ।

यह क्या ठीक नहीं करता, और इससे आपको क्या पता चलता है
सुरंगों की संख्या लगभग नहीं बदली, और मैं इसका कारण ईमानदारी से बताना चाहता हूँ। बची हुई सुरंगें पंखों और पंजों की उँगलियों के सिरों पर हैं, जहाँ कोई पतला हिस्सा समाप्त होता है और दोहरी दीवार दबकर बंद हो जाती है। वे छोटी हैं, दिखाई नहीं देतीं, और उनकी वजह अलग है। यह फिल हिस्सों के बीच संपर्कों को लक्षित करता है, क्योंकि दिखाई देने वाले छेद वहीं थे। असल समाधान अपस्ट्रीम में है। ऐसा डिकोडर जो प्रति-एज फ़्लैग के बजाय प्रति-कोने के चिह्नों का अनुमान लगाए, अपनी संरचना से ही पैरिटी-संगत होगा। इस मॉडल की पिछली पीढ़ी इसी तरह काम करती थी और इसीलिए उसकी मेश जलरोधी थीं। यह प्रशिक्षण में किया जाने वाला बदलाव है, ऐसा कुछ नहीं जिसे हम इन्फ़रेंस के समय पैच कर सकें। तब तक, स्ट्राइप फ़ॉर्मूला से दो व्यावहारिक निष्कर्ष निकलते हैं। यदि आप कोई कैरेक्टर जनरेट कर रहे हैं, तो ऐसी पोज़ जिसमें हाथ-पैर शरीर से अलग हों, उस पोज़ की तुलना में अधिक साफ़ मेश बनेगी जिसमें वे शरीर से सटे हों। और यदि आप ऐसे किसी जनरेटर के ऊपर अपना सिस्टम बना रहे हैं, तो किसी संख्या पर भरोसा करने से पहले यूलर अभिलक्षण से अपनी मेश को मापें और नतीजे को अपनी आँखों से देखें। संख्या ने कहा कि सब साफ़ था। वह दो बार ग़लत निकली।
इंस्ट्रूमेंट किया हुआ डिकोडर, हर चरण के डंप, पैरिटी विश्लेषण और फ़िल—ये सभी अब हमारी पाइपलाइन में हैं, इसलिए अगली बार किसी मॉडल से छेद वाली मेश निकलने पर उसका यही विश्लेषण एक सप्ताह के बजाय कुछ ही मिनटों में हो जाएगा।