वर्चुअल आर्ट सेशन

आर्ट सेशन की जानकारी

खास जानकारी

वीआर में पेंट करने, डिज़ाइन करने, और मूर्ति बनाने के लिए छह कलाकारों को न्योता दिया गया. यह है के सेशन को रिकॉर्ड करने, डेटा को बदलने, और करने की सुविधा मिलती है.

https://g.co/VirtualArtSessions

ज़िंदा रहने का कितना समय है! उपभोक्ता के तौर पर वर्चुअल रिएलिटी के आने की वजह से प्रॉडक्ट के साथ-साथ, नई और नई संभावनाएं तलाश रही हैं. टिल्ट ब्रश, HTC Vive पर उपलब्ध Google प्रॉडक्ट, आपको तीन ड्रॉर बनाने की सुविधा देता है डाइमेंशन स्पेस. जब हमने पहली बार Tilt Brush को आज़माया, तो ऐसा एहसास जिसमें मोशन-ट्रैक्ड कंट्रोलर की मदद ली गई है. साथ ही, इसमें "एक दिव्यांग लोगों की मदद करें" आपके साथ रहेगा; इस तरह का अनुभव जैसे, अपने आस-पास की खाली जगह में ड्रॉइंग करना.

वर्चुअल आर्ट पीस

Google की डेटा आर्ट टीम को एक चैलेंज शुरू किया गया. बिना वीआर हेडसेट वाले लोगों को ऑनलाइन अनुभव दें, जहां Tilt Brush के साथ काम नहीं करता हमारी तरफ़ से हैं. इसके लिए, टीम ने एक मूर्तिकार, एक चित्रकार, कॉन्सेप्ट डिज़ाइनर, फ़ैशन आर्टिस्ट, इंस्टॉलेशन आर्टिस्ट, और स्ट्रीट आर्टिस्ट ताकि इस नए तरीके से उनकी स्टाइल से एक आर्टवर्क बनाया जा सके.

ड्रॉइंग को वर्चुअल रिएलिटी में रिकॉर्ड करना

Unity में बना Tilt Brush सॉफ़्टवेयर खुद एक डेस्कटॉप ऐप्लिकेशन है आपके सिर की पोज़िशन (हेड माउंटेड डिसप्ले या एचएमडी) को ट्रैक करने के लिए, रूम के हिसाब से वीआर का इस्तेमाल करता है और आपके दोनों हाथों के कंट्रोलर हैं. Tilt Brush में बनाई गई आर्टवर्क बनाने वाली कंपनी का नाम डिफ़ॉल्ट रूप से .tilt फ़ाइल के तौर पर एक्सपोर्ट किया गया. वेब पर इस अनुभव को उपलब्ध कराने के लिए, हम हमें लगा कि हमें सिर्फ़ आर्टवर्क के डेटा की ज़रूरत नहीं है. हमने पब्लिशर के साथ मिलकर Tilt Brush टीम की मदद से Tilt Brush में बदलाव करने की सुविधा मौजूद है, ताकि वह पहले जैसा करने/मिटाने की कार्रवाई को भी एक्सपोर्ट कर सके इससे कलाकार के सिर और हाथ को एक सेकंड में 90 गुना बढ़ाया जाता है.

ड्रॉइंग करते समय, Tilt Brush आपके कंट्रोलर की पोज़िशन और कोण को लेता है और उसे कन्वर्ट करता है समय के साथ "स्ट्रोक" में बदल जाते हैं. इसका एक उदाहरण है: यहां पढ़ें. हमने ऐसे प्लगिन लिखे हैं जो इन स्ट्रोक को एक्सट्रैक्ट करके, रॉ JSON के तौर पर काम करते हैं.

    {
      "metadata": {
        "BrushIndex": [
          "d229d335-c334-495a-a801-660ac8a87360"
        ]
      },
      "actions": [
        {
          "type": "STROKE",
          "time": 12854,
          "data": {
            "id": 0,
            "brush": 0,
            "b_size": 0.081906750798225,
            "color": [
              0.69848710298538,
              0.39136275649071,
              0.211316883564
            ],
            "points": [
              [
                {
                  "t": 12854,
                  "p": 0.25791856646538,
                  "pos": [
                    [
                      1.9832634925842,
                      17.915264129639,
                      8.6014995574951
                    ],
                    [
                      -0.32014992833138,
                      0.82291424274445,
                      -0.41208130121231,
                      -0.22473378479481
                    ]
                  ]
                }, ...many more points
              ]
            ]
          }
        }, ... many more actions
      ]
    }

ऊपर दिया गया स्निपेट, स्केच JSON के फ़ॉर्मैट के बारे में बताता है.

यहां हर स्ट्रोक को कार्रवाई के तौर पर सेव किया जाता है. इसका टाइप है: "STROKE". इसके अलावा हम यह दिखाना चाहते हैं कि किस तरह कलाकार से गलतियां हो रही हैं. स्केच न बनाएं, इसलिए "मिटाएं" को सेव करना ज़रूरी था वे कार्रवाइयां जो मिटाने या कार्रवाई को पहले जैसा करने का विकल्प होता है.

हर स्ट्रोक की बुनियादी जानकारी सेव होती है. इससे ब्रश का टाइप, ब्रश का साइज़, और रंग आरजीबी के लिए डेटा इकट्ठा किया जाता है.

आखिर में, स्ट्रोक के हर वर्टेक्स को सेव कर लिया जाता है और इसमें पोज़िशन, ऐंगल, समय, और कंट्रोलर के ट्रिगर किए गए दबाव की स्ट्रेंथ (p के तौर पर बताया गया है) हर पॉइंट के अंदर).

ध्यान दें कि घुमाव एक 4-घटक चतुर्भुज है. बाद में ऐसा करना ज़रूरी है हम स्ट्रोक को रेंडर करते हैं, ताकि गिंबल लॉक से बचा जा सके.

WebGL की मदद से बैक स्केच चलाना

स्केच को वेब ब्राउज़र में दिखाने के लिए, हमने THREE.js पर साइन इन किया और ज्यामिति जनरेट करने वाला कोड लिखा Tilt Brush के तहत काम करने की सुविधा देता है.

टिल्ट ब्रश, उपयोगकर्ता के हाथ के आधार पर रीयल-टाइम में ट्राईऐंगल स्ट्रिप बनाता है तो पूरा स्केच पहले ही "खत्म" हो चुका है उसे दिखाने के समय तक वेब पर. इसकी मदद से, हम रीयल-टाइम कैलकुलेशन और रेसिपी को बायपास करने में काफ़ी मदद करते हैं लोड करने के लिए ज्यामिति चुनें.

WebGL स्केच

एक स्ट्रोक में शीर्ष का हर जोड़ा एक दिशा सदिश (नीली रेखाएं) बनाता है ऊपर दिखाए गए तरीके से हर पॉइंट को जोड़कर, नीचे दिए गए कोड स्निपेट में moveVector). हर पॉइंट में एक ओरिएंटेशन भी होता है, एक क्वाटरनियन कंट्रोलर का मौजूदा ऐंगल. त्रिकोण पट्टी बनाने के लिए, हम हर बार दोहराते हैं ये बिंदु, दिशा के लंबवत रूप से नॉर्मल प्रॉडक्ट तैयार करते हैं और कंट्रोलर ओरिएंटेशन.

हर स्ट्रोक के लिए त्रिकोण स्ट्रिप की गणना करने की प्रक्रिया करीब-करीब एक जैसी है टिल्ट ब्रश में इस्तेमाल किए गए कोड में:

const V_UP = new THREE.Vector3( 0, 1, 0 );
const V_FORWARD = new THREE.Vector3( 0, 0, 1 );

function computeSurfaceFrame( previousRight, moveVector, orientation ){
    const pointerF = V_FORWARD.clone().applyQuaternion( orientation );

    const pointerU = V_UP.clone().applyQuaternion( orientation );

    const crossF = pointerF.clone().cross( moveVector );
    const crossU = pointerU.clone().cross( moveVector );

    const right1 = inDirectionOf( previousRight, crossF );
    const right2 = inDirectionOf( previousRight, crossU );

    right2.multiplyScalar( Math.abs( pointerF.dot( moveVector ) ) );

    const newRight = ( right1.clone().add( right2 ) ).normalize();
    const normal = moveVector.clone().cross( newRight );
    return { newRight, normal };
}

function inDirectionOf( desired, v ){
    return v.dot( desired ) >= 0 ? v.clone() : v.clone().multiplyScalar(-1);
}

स्ट्रोक की दिशा और ओरिएंटेशन को जोड़कर उसे वापस लाएं गणितीय तौर पर समझ में न आने वाले नतीजे; तो कई नॉर्मल डिटेक्ट किए जा सकते हैं और अक्सर एक "नया मोड़" दे देता है, पढ़ें.

स्ट्रोक के बिंदुओं पर दोहराते समय, हम एक "पसंदीदा अधिकार" बनाए रखते हैं वेक्टर और इसे computeSurfaceFrame() फ़ंक्शन में पास करें. यह फ़ंक्शन एक सामान्य दिखाता है जिससे हम क्वाड स्ट्रिप में क्वाड प्राप्त कर सकते हैं. स्ट्रोक की दिशा (पिछले पॉइंट से मौजूदा पॉइंट तक) और कंट्रोलर का ओरिएंटेशन (क्वाटर्नियन). सबसे अहम बात, यह एक नया "पसंदीदा अधिकार" कंप्यूटेशन के अगले सेट के लिए वेक्टर.

स्ट्रोक

हर स्ट्रोक के कंट्रोल पॉइंट पर आधारित क्वाड जनरेट करने के बाद, हम क्वाड को उनके कोनों पर इंटरपोलेट करके, एक क्वाड से दूसरे क्वाड में ले जाते हैं.

function fuseQuads( lastVerts, nextVerts) {
    const vTopPos = lastVerts[1].clone().add( nextVerts[0] ).multiplyScalar( 0.5
);
    const vBottomPos = lastVerts[5].clone().add( nextVerts[2] ).multiplyScalar(
0.5 );

    lastVerts[1].copy( vTopPos );
    lastVerts[4].copy( vTopPos );
    lastVerts[5].copy( vBottomPos );
    nextVerts[0].copy( vTopPos );
    nextVerts[2].copy( vBottomPos );
    nextVerts[3].copy( vBottomPos );
}
एक-दूसरे से जुड़े हुए क्वाड
मिले-जुले क्वाड.

हर क्वाड में यूवी भी होते हैं, जो अगले चरण में जनरेट होते हैं. कुछ ब्रश उसमें कई तरह के स्ट्रोक पैटर्न होते हैं, ताकि हर स्ट्रोक में पेंट ब्रश के अलग स्ट्रोक की तरह महसूस हुआ. ऐसा करने के लिए इसका इस्तेमाल किया जाता है _texture एटलेसिंग, _जहां हर ब्रश टेक्सचर में अलग-अलग वर्शन. सही टेक्स्चर चुनने के लिए, आघात है.

function updateUVsForSegment( quadVerts, quadUVs, quadLengths, useAtlas,
atlasIndex ) {
    let fYStart = 0.0;
    let fYEnd = 1.0;

    if( useAtlas ){
    const fYWidth = 1.0 / TEXTURES_IN_ATLAS;
    fYStart = fYWidth * atlasIndex;
    fYEnd = fYWidth * (atlasIndex + 1.0);
    }

    //get length of current segment
    const totalLength = quadLengths.reduce( function( total, length ){
    return total + length;
    }, 0 );

    //then, run back through the last segment and update our UVs
    let currentLength = 0.0;
    quadUVs.forEach( function( uvs, index ){
    const segmentLength = quadLengths[ index ];
    const fXStart = currentLength / totalLength;
    const fXEnd = ( currentLength + segmentLength ) / totalLength;
    currentLength += segmentLength;

    uvs[ 0 ].set( fXStart, fYStart );
    uvs[ 1 ].set( fXEnd, fYStart );
    uvs[ 2 ].set( fXStart, fYEnd );
    uvs[ 3 ].set( fXStart, fYEnd );
    uvs[ 4 ].set( fXEnd, fYStart );
    uvs[ 5 ].set( fXEnd, fYEnd );

    });

}
ऑयल ब्रश के लिए, एक टेक्सचर एटलस में चार टेक्सचर
ऑयल ब्रश के लिए, टेक्सचर एटलस में चार टेक्सचर
Tilt Brush में
टिल्ट ब्रश में
WebGL में
WebGL में

हर स्केच में असीमित स्ट्रोक होते हैं, और स्ट्रोक को तो हम स्ट्रोक की ज्यामिति का पहले से ही आकलन करते हैं और उसे मर्ज कर देते हैं उन्हें एक जाल में जोड़ लें. हालांकि, हर नए ब्रश टाइप का अपना होना चाहिए साथ ही, जो अब भी हमारे ड्रॉ कॉल को कम करके एक ब्रश पर कर देता है.

ऊपर बताए गए पूरे स्केच को WebGL में सिर्फ़ एक ड्रॉ कॉल में पूरा किया जाता है
ऊपर दिए गए पूरे स्केच को WebGL में एक ही ड्रॉ कॉल में पूरा किया जाता है

सिस्टम की जांच करने के लिए, हमने एक स्केच बनाया है. इसमें हमें 20 मिनट में बनाना संभव हो गया था. नतीजाें वाला स्केच अब भी यहां चलाया जा रहा है WebGL में 60fps.

चूंकि एक स्ट्रोक के हर मूल शीर्ष में भी समय था, इसलिए हम आसानी से डेटा को वापस चला सकता है. हर फ़्रेम के लिए, स्ट्रोक की दोबारा गणना करना इसलिए, लोड होने के बाद पूरे स्केच का पहले से ही आकलन किया और हमें सिर्फ़ हर क्वाड को चुन लिया जाएगा.

किसी क्वाड को छिपाने का मतलब है कि इसके सिरों को 0,0,0 पॉइंट तक छोटा करना. जब समय उस सीमा तक पहुंच गया है जब क्वाड को प्रदर्शित किया जाना चाहिए था, हमें लगा कि शीर्षों को वापस उनकी जगह पर रखें.

सुधार का एक क्षेत्र है, जीपीयू के वर्टेक्स को पूरी तरह से बदलना शेडर. मौजूदा लागू करने की प्रक्रिया उन्हें वर्टेक्स से लूप में निकालकर, उन्हें सही जगह पर रखती है मौजूदा टाइमस्टैंप से कलेक्शन बनाएं. इससे यह पता लगाया जा सकता है कि कौनसे वर्टेक्स दिखने चाहिए और फिर ज्यामिति को अपडेट करना. इससे सीपीयू पर बहुत ज़्यादा लोड पड़ता है. इसकी वजह से जिससे बैटरी लाइफ़ खराब होती है.

वर्चुअल आर्ट पीस

कलाकारों को रिकॉर्ड करना

हमें लगा कि स्केच ही काफ़ी नहीं होंगे. हम यह दिखाना चाहते थे कि और हर ब्रशस्ट्रोक को पेंट करते हुए, अपने स्केच में कलाकार को शामिल करते हैं.

कलाकारों की फ़ोटो लेने के लिए, हमने Microsoft Kinect कैमरे का इस्तेमाल किया कलाकारों का डेटा अंतरिक्ष में मौजूद हैं. इससे हम उन्हें यह दिखा सकते हैं कि ड्रॉइंग उसी स्पेस में त्रिविमीय आकृतियों के बीच प्रदर्शित होती है.

ऐसा इसलिए होता है, क्योंकि कलाकार का शरीर खुद को रोक देता है, जिससे हम यह नहीं देख पाते कि इसके पीछे, हमने डबल Kinect सिस्टम का इस्तेमाल किया है. ये दोनों, कमरे के दूसरी तरफ़ हैं ध्यान दें.

गहराई से जानकारी पाने के अलावा, हमने इसकी रंग की जानकारी भी ली है स्टैंडर्ड DSLR कैमरों वाले सीन में. हमने बेहतरीन कैलिब्रेट और मर्ज करने के लिए, DepthKit सॉफ़्टवेयर और कलर कैमरों से लिया गया फ़ुटेज शामिल है. Kinect में सक्षम है लेकिन हमने DSLR का उपयोग करना चुना क्योंकि हम एक्सपोज़र सेटिंग, सुंदर हाई-एंड लेंस का इस्तेमाल करें, और हाई डेफ़िनिशन में रिकॉर्ड करें.

फ़ुटेज रिकॉर्ड करने के लिए, हमने HTC Vive नाम के कलाकार एचटीसी वाइव के लिए एक खास कमरा बनाया और कैमरा. सभी सतहें ऐसी सामग्री से ढकती हैं जो इन्फ़्रारेड अवशोषित करती है जिससे हमें ज़्यादा साफ़-साफ़ मिलने वाला पॉइंट मिल जाता है (दीवारों पर डुवेट, रिब्ड रबड़) फ़र्श पर मैटिंग. अगर कॉन्टेंट, पॉइंट क्लाउड में दिख रहा हो, तो हमने ब्लैक मटीरियल चुना है, ताकि इससे लोगों का ध्यान न भटके. यह सफ़ेद रंग का था.

रिकॉर्डिंग कलाकार

इन वीडियो रिकॉर्डिंग से हमें इतनी जानकारी मिली कि कोई कण प्रोजेक्ट किया जा सकता है सिस्टम. हमने इसमें कुछ अतिरिक्त टूल लिखे हैं openFrameworks की मदद से, खास तौर पर, फ़्लोर, दीवार, और छत को हटाया जा सकता है.

रिकॉर्ड किए गए वीडियो सेशन के सभी चार चैनल (ऊपर दिए गए दो रंगीन चैनल और दो
गहराई नीचे दी गई है)
रिकॉर्ड किए गए वीडियो सेशन के सभी चार चैनल (ऊपर दो रंगीन चैनल और दो जानकारी नीचे देखें)

कलाकारों को दिखाने के अलावा, हम एचएमडी और 3D में भी डाउनलोड कर सकते हैं. यह न सिर्फ़ एचएमडी को दिखाने के लिए ज़रूरी था, बल्कि वीडियो का आखिरी आउटपुट साफ़ तौर पर दिख रहा था. हालांकि, HTC Vive के रिफ़्लेक्टिव लेंस ठीक से काम नहीं कर रहे थे Kinect की आईआर रीडिंग), उसने कण को डीबग करने के लिए हमें संपर्क के बिंदु दिए आउटपुट और वीडियो को स्केच के साथ एक लाइन में जोड़ो.

सिर पर पहनने वाले डिवाइस, कंट्रोलर, और एक लाइन में मौजूद पार्टिकल
हेड माउंटेड डिसप्ले, कंट्रोलर, और लाइन में मौजूद पार्टिकल

इसके लिए Tilt Brush में एक कस्टम प्लगिन लिखना होता है. यह प्लगिन, हर फ़्रेम के लिए HMD और कंट्रोलर की पोज़िशन क्या है. जैसा कि Tilt Brush 90 एफ़पीएस (फ़्रेम प्रति सेकंड) पर चलता है, बहुत सारा डेटा बाहर चला गया और एक स्केच का इनपुट डेटा 20 एमबी से ज़्यादा था और कंप्रेस की गई फ़ाइल को कंप्रेस नहीं किया जाएगा. हमने इस तकनीक का इस्तेमाल उन इवेंट को कैप्चर करने के लिए भी किया है जिन्हें रिकॉर्ड नहीं किया गया है Tilt ब्रश की मदद से सेव की गई फ़ाइल में. जैसे, जब कलाकार कोई विकल्प चुनता है और मिरर विजेट की जगह पर.

हमने 4 टीबी डेटा इकट्ठा किया, जिसे प्रोसेस करने में सबसे बड़ी चुनौती यह थी कि सभी अलग-अलग विज़ुअल/डेटा सोर्स को अलाइन कर रहा है. डीएसएलआर कैमरे से लिया गया हर वीडियो काइनेक्ट के साथ अलाइन होना चाहिए, ताकि पिक्सल एक-दूसरे से अलाइन हो सकें समय है. फिर इन दो कैमरा रिग के फ़ुटेज को एक-दूसरे से अलाइन करते हैं. फिर हमें 3d को अलाइन करने की ज़रूरत थी अपनी ड्रॉइंग से इकट्ठा किए गए डेटा को कलाकार के तौर पर देखना. वाह! हमने ब्राउज़र के आधार पर तैयार की टूल, जिनकी मदद से इनमें से ज़्यादातर कामों को पूरा किया जा सकता है. आपके पास इन्हें खुद आज़माने का भी विकल्प है यहां

रिकॉर्डिन आर्टिस्ट

डेटा अलाइन होने के बाद, हमने उसे प्रोसेस करने के लिए NodeJS में लिखी गई कुछ स्क्रिप्ट का इस्तेमाल किया है सभी आउटपुट, एक वीडियो फ़ाइल और JSON फ़ाइलों की सीरीज़ जनरेट करते हैं. सभी ट्रिम और सिंक किया गया. फ़ाइल का साइज़ कम करने के लिए, हमने तीन काम किए. पहले हमने लोगों की हर फ़्लोटिंग पॉइंट नंबर की सटीक वैल्यू, ताकि वह ज़्यादा से ज़्यादा 3 हो के सटीक होने के दशमलव अंक के बराबर होनी चाहिए. दूसरा, हमने पॉइंट की संख्या को एक तिहाई घटाकर 30fps और क्लाइंट-साइड की स्थितियों के बीच इंटरपोलेट किया. आख़िर में, हमने डेटा इसलिए है, इसलिए कुंजी/वैल्यू पेयर के साथ सामान्य JSON का इस्तेमाल करने के बजाय, वैल्यू का क्रम इसे एचएमडी और कंट्रोलर की पोज़िशन और रोटेशन के लिए बनाया गया है. इससे फ़ाइल कट जाएगी आकार में 3 एमबी तक का आकार कम करें, जो वायर के ऊपर वितरण के लिए स्वीकार्य था.

रिकॉर्ड करने वाले कलाकार

वीडियो को एक HTML5 वीडियो एलिमेंट के तौर पर दिखाया जाता है, जिसे कण बनने के लिए WebGL की बनावट, वीडियो को गुप्त मोड में चलाने की ज़रूरत होती है बैकग्राउंड शामिल करें. शेडर, डेप्थ इमेज के रंगों को उनकी पोज़िशन में बदल देता है 3D स्पेस. जेम्स जॉर्ज ने एक बेहतरीन उदाहरण शेयर किया है सीधे depthKit से फ़ुटेज के साथ आप कैसे कर सकते हैं.

iOS पर इनलाइन वीडियो चलाने की सुविधा पर पाबंदियां लगी हैं. हमारा मानना है कि अपने-आप चलने वाले वेब वीडियो विज्ञापनों से उपयोगकर्ताओं को परेशान होने से बचाना. हमने एक तकनीक का इस्तेमाल किया इस मामले में अन्य समाधानों की तरह हैं, वेब, जो कि कॉपी करने के लिए और वीडियो फ़्रेम को कैनवस में बदलें और वीडियो के दिखने में लगने वाले समय को मैन्युअल तौर पर अपडेट करें, हर 1/30 पर एक सेकंड.

videoElement.addEventListener( 'timeupdate', function(){
    videoCanvas.paintFrame( videoElement );
});

function loopCanvas(){

    if( videoElement.readyState === videoElement.HAVE\_ENOUGH\_DATA ){

    const time = Date.now();
    const elapsed = ( time - lastTime ) / 1000;

    if( videoState.playing && elapsed >= ( 1 / 30 ) ){
        videoElement.currentTime = videoElement.currentTime + elapsed;
        lastTime = time;
    }

    }

}

frameLoop.add( loopCanvas );

हमारे काम करने के तरीके का खराब असर iOS को काफ़ी हद तक कम करना पड़ा. फ़्रेमरेट, क्योंकि वीडियो से कैनवस पर पिक्सल बफ़र को कॉपी करने की प्रोसेस बहुत ज़्यादा होती है सीपीयू (CPU) का इस्तेमाल किया जाता है. इसके काम करने के लिए, हमने केवल ये वही वीडियो होते हैं जो iPhone 6 पर कम से कम 30fps

नतीजा

वीआर सॉफ़्टवेयर डेवलपमेंट के लिए 2016 तक की आम सहमति ज्यामितीय और शेडर को आसान बनाता है, ताकि आप एक HMD में 90+fps पर चला सकें. यह के रूप में भी जाना जाता है. Tilt Brush मैप में भी इसे काफ़ी अच्छी तरह से जोड़ दिया गया.

जबकि जटिल 3D मेश प्रदर्शित करने वाले वेब ब्राउज़र यह इस बात का सबूत था कि वीआर के काम के लिए क्रॉस-परागेशन और वेब पर संभव है.