PerfectVector
लेखक: Irene Kim9 मिनट का पठन

Three.js SVGLoader: सपाट चित्र को 3D मेश बनाएँ

Three.js में SVG पाथ लोड करें, वास्तविक खुला हिस्सा रखें, ऊर्ध्व दिशा ठीक करें और छोटे, दोहराए जा सकने वाले ब्राउज़र उदाहरण से एक्सट्रूडेड मेश का आकार तय करें।

इस पेज पर

सपाट SVG चित्र को Three.js मेश में बदलने के लिए SVG लोड करें, उसके पाथ को आकार में बदलें, फिर वे आकार ExtrudeGeometry को दें। प्रभाव जोड़ने से पहले खाली हिस्से, ऊर्ध्व दिशा और आयाम देखें। पहचानने योग्य बाहरी आकृति में भी भरा हुआ अंदरूनी हिस्सा या उलटा कोना हो सकता है।

यह उदाहरण हाथ से बनाया गया मौलिक बैज इस्तेमाल करता है, जिसमें एक चौकोर खुला हिस्सा और कटा ऊपरी-दायाँ कोना है। असममिति दिशा की गलती दिखाती है। यह ब्राउज़र ज्यामिति उदाहरण है, PerfectVector रूपांतरण परिणाम या निर्माण परीक्षण नहीं।

उन आकारों से शुरू करें जिन्हें गहराई देनी है

पहली कोशिश के लिए बंद, भरे कंटूर वाला छोटा SVG लें। इसे badge.svg में सहेजें:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 180">
  <path fill="#e64b35" fill-rule="evenodd"
    d="M20 20H160L220 80V160H20Z M65 60H115V110H65Z"/>
</svg>

एक पाथ एलिमेंट के अंदर दो बंद सबपाथ हैं: बाहरी सीमा और अंदरूनी चौकोर। evenodd भरण नियम उस अंदरूनी क्षेत्र को खुला हिस्सा बनाता है। अलग सफ़ेद आयत केवल सपाट तस्वीर में सतह ढकता; वह वही खाली क्षेत्र परिभाषित नहीं करता।

चित्र 240 गुणा 180 viewBox के अंदर 200 गुणा 140 निर्देशांक इकाइयाँ घेरता है। मेश का आकार तय करते समय यह अंतर ध्यान में रखें। खाली मार्जिन SVG व्यूपोर्ट का हिस्सा हैं, एक्सट्रूड की गई बाहरी आकृति का नहीं।

यदि संपादन योग्य वेक्टर मूल फ़ाइल पहले से है, तो उसे इस्तेमाल करें। यदि PNG या JPG ही एकमात्र स्रोत है, तो PerfectVector का छवि से वेक्टर कार्यप्रवाह SVG पाथ चित्र तैयार करने में मदद कर सकता है। Three.js में लोड करने से पहले पूर्वावलोकन और डाउनलोड किए कंटूर, खासकर खाली जगहें, देखें। वेक्टराइज़ेशन 2D चित्र देता है; नीचे का कोड गहराई, मटेरियल, रोशनी और स्थिति देता है।

SVG लोड करके मेश रेंडर करें

उदाहरण Three.js 0.186.0 से जाँचा गया था। मुख्य लाइब्रेरी और ऐडऑन का संस्करण समान रखें। पैकेज आयात वाले ब्राउज़र प्रोजेक्ट में three@0.186.0 इंस्टॉल करें, फ़ाइलें HTTP पर उपलब्ध करें और कंटेनर बनाएँ:

<div id="viewer"></div>
<script type="module" src="./main.js"></script>

आपके बिल्ड टूल को three आयातों के लिए संबंधित मॉड्यूल खोज पाने चाहिए। बिना बिल्ड टूल के सामान्य ब्राउज़र पेज में मॉड्यूल स्क्रिप्ट से पहले यह इम्पोर्ट मैप रखें, उसी इंस्टॉल किए पैकेज की फ़ाइलें इस्तेमाल करके:

<script type="importmap">
{
  "imports": {
    "three": "./node_modules/three/build/three.module.js",
    "three/addons/": "./node_modules/three/examples/jsm/"
  }
}
</script>

HTML पेज के पास badge.svg रखें। नीचे का सापेक्ष लोडिंग URL उस पेज के URL के अनुसार तय होता है। फिर इसे main.js में सहेजें:

import * as THREE from 'three';
import { SVGLoader } from 'three/addons/loaders/SVGLoader.js';
 
const data = await new SVGLoader().loadAsync('./badge.svg');
const artwork = new THREE.Group();
for (const path of data.paths) {
  if (path.userData.style.fill === 'none') continue;
  for (const shape of path.toShapes()) {
    const geometry = new THREE.ExtrudeGeometry(shape, {
      depth: 20, bevelEnabled: false, steps: 1
    });
    const material = new THREE.MeshStandardMaterial({
      color: path.color, roughness: 0.65, metalness: 0
    });
    artwork.add(new THREE.Mesh(geometry, material));
  }
}
if (!artwork.children.length) throw new Error('No filled shapes found');
 
// SVG y grows down; this scene uses y up.
artwork.scale.y = -1;
const bounds = new THREE.Box3().setFromObject(artwork);
const size = bounds.getSize(new THREE.Vector3());
const center = bounds.getCenter(new THREE.Vector3());
const scale = 4 / size.x;
artwork.scale.multiplyScalar(scale);
artwork.position.copy(center).multiplyScalar(-scale);
 
const scene = new THREE.Scene();
scene.background = new THREE.Color('#f1f3f5');
scene.add(artwork);
scene.add(new THREE.HemisphereLight(0xffffff, 0x596477, 2));
const light = new THREE.DirectionalLight(0xffffff, 3);
light.position.set(-3, 5, 7);
scene.add(light);
const camera = new THREE.PerspectiveCamera(35, 800 / 600, 0.1, 100);
camera.position.set(4, 3, 9);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(800, 600);
document.querySelector('#viewer').append(renderer.domElement);
renderer.render(scene, camera);

SVGLoader अलग आयात होने वाला ऐडऑन है। loadAsync() फ़ाइल पढ़ता है; SVG मार्कअप पहले से स्ट्रिंग में हो तो parse(svgText) दूसरा विकल्प है।

r186 में path.toShapes() इस्तेमाल करें। पुराने उदाहरण अक्सर SVGLoader.createShapes(path) बुलाते हैं। वह सहायक r185 में अप्रचलित घोषित हुआ और जाँचे संस्करण में toShapes() को काम सौंपता है। अलग ट्यूटोरियल के अंश मिलाने से पहले इंस्टॉल किया संस्करण देखें।

लूप जानबूझकर fill="none" छोड़ता है। यह इस उदाहरण के ठोस भरण संभालता है; पूरा SVG रेंडरर नहीं है। ग्रेडिएंट, मास्क, एम्बेडेड छवियाँ, स्ट्रोक, अपारदर्शिता और एक-दूसरे पर चढ़ी रंग परतों के लिए अलग निर्णय चाहिए; यह न मानें कि सपाट रूप हूबहू 3D ज्यामिति बन जाएगा।

वास्तविक ब्राउज़र कैप्चर में चौकोर खुले हिस्से और कटे ऊपरी-दाएँ कोने वाले मूल SVG बैज की उसके Three.js एक्सट्रूडेड मेश से तुलना
Three.js r186 में हाथ से लिखे परीक्षण नमूने का वास्तविक WebGL रेंडर। खुला हिस्सा खाली रहता है, कटा कोना ऊपरी दाएँ रहता है और समान स्केलिंग से 4 गुणा 2.8 गुणा 0.4 मेश बनता है।

मापने और केंद्रित करने से पहले दिशा तय करें

SVG के ऊर्ध्व निर्देशांक नीचे की ओर बढ़ते हैं। इस दृश्य में चित्र को देखते समय धनात्मक y ऊपर की ओर है, इसलिए artwork.scale.y = -1 अपेक्षित दिशा बहाल करता है। कटा कोना जाँच का संकेत है: वह ऊपरी दाएँ होना चाहिए।

यह धनात्मक से ऋणात्मक चिह्न में बदलाव इसी निर्देशांक सेटअप का हिस्सा है। कैमरा या पैरेंट ऑब्जेक्ट घुमाने के बाद मेश गलत दिखे तो केवल इसलिए दूसरा फ़्लिप न जोड़ें। पहले स्रोत की ज्ञात असममित विशेषता को रेंडर दृश्य से मिलाएँ।

अगली पंक्तियाँ फ़्लिप हुए समूह को मापती हैं, समान पैमाना निकालती हैं और स्केल हुए केंद्र को मूल बिंदु तक खिसकाती हैं। Box3.setFromObject() चाइल्ड ऑब्जेक्ट और उनके ट्रांसफ़ॉर्म सहित सीमाएँ मापता है। यहाँ मापते समय समूह का ट्रांसफ़ॉर्म हुआ पैरेंट नहीं है और चित्र घूमा नहीं है।

मूल एक्सट्रूज़न 200 गुणा 140 गुणा 20 है। चौड़ाई 4 रखने से पैमाना 4 / 200, यानी 0.02 मिलता है। क्योंकि यह पैमाना तीनों अक्षों पर लागू है, अंतिम सीमाएँ 4 गुणा 2.8 गुणा 0.4 हैं। कन्स्ट्रक्टर में 20 की गहराई समूह स्केल करने के बाद 20 नहीं रहती।

ये दृश्य इकाइयाँ हैं। उदाहरण यह दावा नहीं करता कि एक इकाई एक मिलीमीटर है। यदि एप्लिकेशन को विशेष भौतिक अर्थ चाहिए, तो उसे स्पष्ट तय करें और गंतव्य कार्यप्रवाह से सत्यापित करें।

सतह सजाने से पहले खाली हिस्सा सुनिश्चित करें

परीक्षण में एक लोड किया पाथ, एक आकार और एक खाली हिस्सा मिला। हमने चौकोर खुले हिस्से और ठोस क्षेत्र से किरण भी भेजी: खुले हिस्से में मेश से टकराव नहीं मिला, जबकि ठोस क्षेत्र में मिला। कटे ऊपरी-दाएँ और ठोस निचले-दाएँ कोनों से भेजी किरणों ने तिरछे दृश्य से स्वतंत्र रूप में ऊर्ध्व दिशा सुनिश्चित की।

अपने दृश्य में सरल दृश्य जाँच से शुरू कर सकते हैं: सतह सीधे सामने से देखें, फिर विपरीत रंग वाली पृष्ठभूमि पर तिरछे कोण से। खुले हिस्से में पृष्ठभूमि दिखनी चाहिए और कैमरा चलने पर उसकी साइड दीवारें दिखनी चाहिए। क्षेत्र ढकती सफ़ेद सतह अलग परिणाम है।

यदि अंदरूनी खाली हिस्सा भरता है, तो उस एक आकार को अलग करें। देखें कि स्रोत सबपाथ, अलग भरे ऑब्जेक्ट, क्लिपिंग पाथ या मास्क इस्तेमाल करता है। मटेरियल रंग से समस्या छिपाने की कोशिश न करें। भर जाने वाले SVG खाली हिस्सों की मार्गदर्शिका स्रोत फ़ाइल के अंतर बताती है; एक्सट्रूज़न निदान मूल चित्र खराब होने पर कंटूर सुधार बताता है।

साधारण एक्सट्रूज़न सही होने के बाद ही गहराई प्रभाव जोड़ें

उदाहरण में बेवल बंद हैं ताकि शुरुआती आयाम जाँचना आसान हो। ExtrudeGeometry विकल्प गहराई, बेवल आकार, बेवल मोटाई और वक्र सैंपलिंग अलग नियंत्रित करते हैं। बेवल चालू करने पर छोटे खुले हिस्से और सीमाएँ फिर देखें। सजावटी किनारा अभी मापी गई ज्यामिति बदलता है।

वक्र चित्र में एप्लिकेशन के इस्तेमाल वाले आकार और कैमरा दूरी पर मेश की बाहरी आकृति जाँचें। केवल खंडों वाले किनारे में ज़रूरत होने पर वक्र सैंपलिंग बढ़ाएँ; इनपुट के अनावश्यक नोड घटाना अलग संपादन कार्य है। कोई सेटिंग स्रोत में अनुपस्थित बारीकी वापस नहीं लाती।

केवल स्ट्रोक वाली ड्रॉइंग को भी अलग निर्णय चाहिए। लोडर स्ट्रोक ज्यामिति के लिए pointsToStroke() देता है, लेकिन ऊपर भरे आकारों वाला लूप जानबूझकर वे पाथ छोड़ता है। यदि दिखने वाली लाइन एक्सट्रूडेड पट्टी बननी है, तो पहले तय करें कि कौन सी बंद आउटलाइन वह पट्टी परिभाषित करती है। यदि वह दृश्य में लाइन ही रहनी चाहिए, तो इसके बजाय लाइन या स्ट्रोक प्रस्तुति बनाएँ।

React एप्लिकेशन में केवल ब्राउज़र वाली लोडिंग और रेंडरर का काम क्लाइंट पर चलाएँ तथा दृश्य हटने पर अपनी ज्यामिति, मटेरियल और रेंडरर के संसाधन मुक्त करें। संक्षिप्त उदाहरण निश्चित आकार पर एक बार रेंडर करता है; प्रोडक्शन व्यूअर को आकार बदलना सँभालना और अपना संसाधन जीवनचक्र भी चाहिए।

स्रोत और गंतव्य जाँच अलग रखें

ब्राउज़र मेश इंटरैक्टिव बैज, लोगो पूर्वावलोकन या दृश्य सजावट के लिए उपयोगी है। यह सिद्ध नहीं करता कि परिणाम पूरी तरह बंद और आयामों के हिसाब से उपयुक्त निर्माण भाग है। यदि गंतव्य फ़ैब्रिकेशन है, तो अलग 3D प्रिंटिंग के लिए छवि से SVG कार्यप्रवाह अपनाएँ और वहाँ आयातित मॉडल जाँचें।

स्क्रीन कार्यप्रवाह में तीन फ़ाइलें या चरण अलग रखें: संपादन योग्य स्रोत SVG, उससे बना मेश और दृश्य प्रस्तुति। इससे समझना आसान है कि खराब परिणाम पाथ ज्यामिति, मेश निर्माण या कैमरा और रोशनी से आया। जब लोड करने से पहले चित्र सुधारना हो, तो अधिक SVG कार्यप्रवाह मार्गदर्शिकाएँ स्रोत वाला पक्ष समझाती हैं।

अक्सर पूछे जाने वाले प्रश्न

Three.js में मेरा SVG उलटा क्यों है? SVG ऊर्ध्व निर्देशांक नीचे की ओर बढ़ते हैं। धनात्मक y ऊपर रखने और चित्र के सामने देखने वाले दृश्य में चित्र समूह का y पैमाना फ़्लिप करने से स्रोत दिशा बहाल हो सकती है। दूसरा फ़्लिप या घुमाव जोड़ने से पहले असममित विशेषता जाँचें।

createShapes इस्तेमाल करूँ या toShapes? यह उदाहरण Three.js 0.186.0 के साथ path.toShapes() इस्तेमाल करता है। SVGLoader.createShapes() r185 में अप्रचलित घोषित हुआ। प्रोजेक्ट में इंस्टॉल संस्करण का दस्तावेज़ वाला API इस्तेमाल करें और मुख्य पैकेज तथा ऐडऑन एक ही संस्करण पर रखें।

क्या SVGLoader SVG के अंदर PNG को मेश बना देता है? एम्बेडेड रास्टर तस्वीर इस उदाहरण के भरे कंटूर नहीं देती। पहले उपयुक्त पाथ चित्र लें, या यदि वास्तविक उद्देश्य उसका रूप सुरक्षित रखना हो तो छवि को टेक्सचर के रूप में इस्तेमाल करें।

क्या एक्सट्रूज़न SVG स्ट्रोक चौड़ाई सुरक्षित रखता है? यह उदाहरण भरे आकार एक्सट्रूड करता है और fill को none रखे पाथ छोड़ता है। स्ट्रोक ज्यामिति का कार्यप्रवाह अलग है; मोटी रंगी लाइन अपने आप एक्सट्रूडेड पट्टी की बंद आउटलाइन नहीं बनती।

स्रोत

  1. Three.js — SVGLoader — ऐडऑन आयात, पार्सिंग और लोडिंग विधियाँ, स्ट्रोक सहायक तथा createShapes का अप्रचलित होना बताता है।
  2. Three.js — ShapePath — toShapes से पाथ संग्रह को आकार में बदलने का दस्तावेज़ देता है।
  3. Three.js — ExtrudeGeometry — आकार एक्सट्रूज़न, गहराई, बेवल और वक्र सैंपलिंग विकल्प परिभाषित करता है।
  4. Three.js — Box3 — ट्रांसफ़ॉर्म हुए ऑब्जेक्ट की सीमा मापना और उसका आकार तथा केंद्र पाना बताता है।

केवल रास्टर प्रतीक से काम कर रहे हैं? एक प्रारंभिक SVG तैयार करें, उसके भरे कंटूर और खुले हिस्से जाँचें, फिर पूरा व्यूअर बनाने से पहले उस फ़ाइल को इस छोटे दृश्य में परखें।

Blog से और

ऐसे साफ़ SVG से शुरुआत करें
जिसे एडिट करना आसान हो