2012-07-04 13 views
5

मैं एक फ़ाइल से तीन.जेएस में एक दृश्य लोड करने का प्रयास कर रहा हूं (कस्टम प्रारूप, जो कि तीन.जेएस समर्थन नहीं करता है)। यह विशेष प्रारूप एक दृश्य ग्राफ का वर्णन करता है जहां पेड़ में प्रत्येक नोड में 4x4 मैट्रिक्स के रूप में निर्दिष्ट एक रूपांतरण होता है। Three.js में धकेलने के लिए प्रक्रिया कुछ इस तरह दिखता है:थ्री.जेएस दृश्य ग्राफ को बदलने के लिए मैट्रिस का उपयोग

// Yeah, this is javascript-like psuedocode 
function processNodes(srcNode, parentThreeObj) { 
    for(child in srcNode.children) { 
     var threeObj = new THREE.Object3D(); 

     // This line is the problem 
     threeObj.applyMatrix(threeMatrixFromSrcMatrix(child.matrix)); 

     for(mesh in child.meshes) { 
      var threeMesh = threeMeshFromSrcMesh(mesh); 
      threeObj.add(threeMesh); 
     } 

     parentThreeObj.add(threeObj); 

     processNodes(child, threeObj); // And recurse! 
    } 
} 

या कम से कम है कि मैं चाहता हूँ कि यह होना करने के लिए है। जैसा कि मैंने बताया, applyMatrix लाइन उस तरीके से काम नहीं करती जिसकी मैं अपेक्षा करता हूं। दृश्य का बहुमत ठीक दिखता है, लेकिन घुमाए गए कुछ तत्व ठीक से संरेखित नहीं होते हैं (जबकि अन्य हैं, यह अजीब है)।

कोलाडा लोडर के माध्यम से देख रहे हैं (जो लगभग वही काम करता है जो मैं करने की कोशिश कर रहा हूं) ऐसा लगता है कि वे decompose the matrix अनुवाद/घुमाने/स्केल में और प्रत्येक व्यक्तिगत रूप से लागू होते हैं।

var props = threeMatrixFromSrcMatrix(child.matrix).decompose(); 
threeObj.useQuaternion = true; 
threeObj.position = props[ 0 ]; 
threeObj.quaternion = props[ 1 ]; 
threeObj.scale = props[ 2 ]; 

यह, एक बार फिर, एक दृश्य है, जहां ज्यादातर तत्वों सही जगह में हैं पैदावार लेकिन meshes कि पहले गलत संरेखित कर रहे थे अब कहीं और अब गुमनामी में तब्दील कर दिया गया है: मुझे लगता है कि applyMatrix के स्थान पर ऊपर दिखाए करने की कोशिश की बिल्कुल दिखाई देते हैं। तो अंत में यह ऊपर से applyMatrix से बेहतर नहीं है।

विषय के बारे में कई ऑनलाइन चर्चाओं को देखते हुए ऐसा लगता है कि आपके परिवर्तनों के लिए मैट्रिस का उपयोग करने के लिए अनुशंसित तरीका उन्हें सीधे ज्यामिति पर लागू करना है, नोड्स नहीं, इसलिए मैंने मैन्युअल रूप से ट्रांसफॉर्म मैट्रिक्स को मैन्युअल रूप से बनाने की कोशिश की:

function processNodes(srcNode, parentThreeObj, parentMatrix) { 
    for(child in srcNode.children) { 
     var threeObj = new THREE.Object3D(); 

     var childMatrix = threeMatrixFromSrcMatrix(child.matrix); 
     var objMatrix = THREE.Matrix4(); 
     objMatrix.multiply(parentMatrix, childMatrix); 

     for(mesh in child.meshes) { 
      var threeMesh = threeMeshFromSrcMesh(mesh); 
      threeMesh.geometry.applyMatrix(objMatrix); 
      threeObj.add(threeMesh); 
     } 

     parentThreeObj.add(threeObj); 

     processNodes(child, threeObj, objMatrix); // And recurse! 
    } 
} 

यह वास्तव में सही परिणाम देता है! (मानदंडों के साथ कुछ quirks घटाएं, लेकिन मैं इसे बाहर निकाल सकता हूं) यह बहुत अच्छा है, लेकिन समस्या यह है कि अब हम दृश्य पदानुक्रम को प्रभावी ढंग से चपटा कर चुके हैं: माता-पिता पर परिवर्तन बदलने से बच्चों पर अप्रत्याशित परिणाम मिलेंगे क्योंकि पूर्ण ढेर को बदलना अब मेस के लिए "बेक्ड" है। इस मामले में यह दृश्य के बारे में जानकारी का एक अस्वीकार्य नुकसान है।

तो एक ही तर्क करने के लिए तीन.जेएस को कहने के बारे में कोई कैसे हो सकता है, लेकिन दृश्य ग्राफ में उपयुक्त बिंदु पर?

(क्षमा करें, मैं महंगा कुछ लाइव कोड उदाहरण पोस्ट करने के लिए प्यार होता है लेकिन यह है कि दुर्भाग्य से इस मामले में एक विकल्प नहीं है।)

उत्तर

5

आप उपयोग कर सकते हैं matrixAutoUpdate = Three.js scenegraph स्थिति/पैमाने/रोटेशन सामान छोड़ झूठी। फिर ऑब्जेक्ट.मैट्रिक्स को अपने इच्छित मैट्रिक्स पर सेट करें और सभी को बांधा होना चाहिए (ठीक है, यह अभी भी पैरेंट नोड मैट्रिस द्वारा गुणा हो जाता है, इसलिए यदि आप पूर्ण मॉडलव्यू मैट्रिक्स का उपयोग कर रहे हैं तो आपको ऑब्जेक्ट 3 डी पर अद्यतन मैट्रिक्सवर्ल्ड विधि हैक करने की आवश्यकता है।)

object.matrixAutoUpdate = false; 
object.matrix = myMatrix; 

अब, यदि आप तीन के शीर्ष पर एक कस्टम रूपांतरण मैट्रिक्स लागू करना चाहते हैं।जेएस स्थिति/स्केल/रोटेशन सामान, आपको ऑब्जेक्ट 3 डी # अपडेटमैट्रिक्स को कुछ ऐसा करने की आवश्यकता है।

THREE.Object3D.prototype._updateMatrix = THREE.Object3D.prototype.updateMatrix; 
THREE.Object3D.prototype.updateMatrix = function() { 
    this._updateMatrix(); 
    if (this.customMatrix != null) 
    this.matrix.multiply(this.customMatrix); 
}; 

https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L209

+0

एक ही जवाब है, के अलावा एक मिनट देखें। :) वैसे भी, धन्यवाद! अद्यतनमैट्रिक्स बिट बहुत दिलचस्प है। – Toji

5

साई ...

ट्विटर पर बदल Qualia pointed out the solution के मिनटों के भीतर मैं इसे पोस्ट कर रहा हूँ।

यह एक साधारण एक-पंक्ति तय है: ऑब्जेक्ट 3 डी उदाहरणों पर झूठी करने के लिए बस matrixAutoUpdate सेट करें और पहले कोड नमूना उद्देश्य के अनुसार काम करता है।

threeObj.matrixAutoUpdate = false; // This fixes it 
threeObj.applyMatrix(threeMatrixFromSrcMatrix(child.matrix)); 

यह हमेशा मूर्ख थोड़ा चीजें हैं जो आप प्राप्त है ...

संबंधित मुद्दे