2016-05-25 33 views
0

Ich habe ein Array mit einer 4x4-Transformationsmatrix, die Rotations- und Positionsdaten codiert (ich habe bereits bestätigt, dass diese Matrix eine gültige Transformation in Octave darstellt). Ich möchte die Eigenschaft matrixWorld eines three.js-Objekts (Object3D) mit dem Inhalt dieses Arrays festlegen, d. H. Die Position und Drehung des Objekts basierend auf der Transformationsmatrix festlegen.MatrixWorld-Eigenschaft eines three.js-Objekts setzen

Nach this page aus der three.js Dokumentation und verschiedenen hier gestellten Fragen (zum Beispiel this one und this one), so scheint es der Schlüssel nameOfObject.matrixAutoUpdate auf false gesetzt ist. Mit dieser Berechnung habe ich verschiedene Ansätze versucht, nameOfObject.matrixWorld zu setzen, und keiner von ihnen ändert den Ort, an dem das Objekt gerendert wird: Es bleibt im Ursprung ohne Drehung, wie es der Fall ist, wenn matrixWorld die 4x4-Identität ist Matrix.

Hier ist, was ich versucht habe (dieser Code innerhalb einer Update-Methode vor render() genannt wird):

// Setting up a three.js matrix 
var tempMatrix = new THREE.Matrix4(); 
tempMatrix.fromArray(arrayContainingTransformationMatrix); 

// Values are set as expected 
console.log(tempMatrix.elements); 

// Note that the approaches below were tried one at a time 

// First approach (doesn't work) 
nameOfObject.matrixAutoUpdate = false; 
nameOfObject.matrixWorld.copy(tempMatrix); 

// Second approach (also doesn't work) 
// Based on the second SO question linked above 
nameOfObject.matrixAutoUpdate = false; 
nameOfObject.matrix.copy(tempMatrix); 
nameOfObject.updateMatrixWorld(true); 

// Third approach (this doesn't work either, unfortunately) 
nameOfObject.matrixAutoUpdate = false; 
nameOfObject.matrixWorld.fromArray(arrayContainingTransformationMatrix); 

// Appears to be set correctly regardless of which approach is used 
console.log(sphere1.matrixWorld.elements); 

Ein paar Anmerkungen:

  • Ich würde erwarten, dass es eigentlich nicht notwendig ist, innerhalb jeder Iteration matrixAutoUpdate auf false zu setzen, aber jetzt habe ich es getan, nur um auf Nummer sicher zu gehen.
  • Wenn nameOfObject.position basierend auf den Werten in der vierten Spalte der Transformationsmatrix geändert wird, anstatt matrixWorld zu ändern, ändert sich die Position des Objekts wie erwartet, sodass dies kein Renderingproblem zu sein scheint.
  • Ich habe in mehreren Standorten gelesen, dass updateMatrix() nicht aufgerufen werden sollte, wenn Sie die Matrix manuell festlegen, wie es auf den Eigenschaften position und rotation überschreibt. Ich würde annehmen, updateMatrixWorld() unterliegt ähnlichen Überlegungen, aber ich habe nicht so viel Diskussion darüber gefunden, was es tut.

Irgendwelche Vorschläge würden geschätzt! Im schlimmsten Fall schaue ich mir die Quelle an, aber three.js war bisher ziemlich einfach zu benutzen und ich vermute, dass ich einfach etwas vermisse.

+0

Sie können nur die Matrix des Objekts festlegen. Sie können die Weltmatrix des Objekts nicht festlegen.Ist das deine Frage? "Wie kann ich' object.matrix' so einstellen, dass es zu einer bestimmten 'object.matrixWorld' führt - unter Berücksichtigung der Transformationen der Eltern des Objekts?" – WestLangley

+0

Wenn die Welt-Matrix des Objekts schreibgeschützt ist, beantwortet das meine Frage. Ich nahm an, dass es gesetzt werden könnte, weil die Eigenschaft 'matrixWorld' in den [Object3D docs] (http://threejs.org/docs/index.html#Reference/Core/Object3D) nicht als" readonly "gekennzeichnet ist (die Beschreibungen für andere schreibgeschützte Eigenschaften, z. B. "id", beginnen mit "readonly". –

+1

Es ist nicht schreibgeschützt. Der Renderer setzt es zurück. – WestLangley

Antwort

0

Bisher konnte ich das gewünschte Ergebnis erzielen, indem ich die Eigenschaft matrix des Objekts (die lokale Transformation relativ zum übergeordneten Objekt des Objekts) festlegte. Da der Eltern Objekt scene ist, Code wie folgt funktioniert:

scene.add(nameOfObject); 

// Using this transformation matrix (translation of two units along the x axis): 
// 1 0 0 2 
// 0 1 0 0 
// 0 0 1 0 
// 0 0 0 1 

// Column-major version of the transformation 
var tempArrayCM = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1]; 
// Per the docs, Matrix4.fromArray() uses column-major format 

// Row-major version of the transformation 
var matrixT = new THREE.Matrix4(); 
matrixT.set(1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); 
// Per the docs, Matrix4.set() uses row-major format 

nameOfObject.matrixAutoUpdate = false; 

nameOfObject.matrix.fromArray(tempArrayCM); // This works 

//nameOfObject.matrix.copy(matrixT); // This also works 

//nameOfObject.matrixWorld.fromArray(tempArrayCM); // No effect 

//nameOfObject.matrixWorld.copy(matrixT); // No effect 

Es matrixWorld Einstellung scheint funktioniert einfach nicht. Ich nehme an, das ist in Ordnung, wenn das fragliche Objekt ein Kind von scene ist, aber ich kann mir vorstellen, dass dies Probleme verursacht, wenn das Objekt ein Kind eines Kindes von ist und es seine Weltposition unabhängig von seinem Elternteil festlegen muss (): scheint es, dass die attach und detach Methoden von SceneUtils dies zulassen würden, wenn auch indirekt).

Ich werde dies nicht als Antwort markieren, da es sich wirklich nur um eine Problemumgehung handelt, die nur gilt, wenn das übergeordnete Objekt des Objekts scene ist.

Ein beiseite: Ich finde es ein wenig seltsam, dass Matrix4.set() Zeilenreihenfolge verwendet, aber Matrix4.fromArray() und Matrix4.elements Spaltenreihenfolge verwenden.

+0

Sie müssen .updateMatrix() in Ihrer Schleife haben, richtig? – dcromley

+0

Nein, aber seine Auslassung ist konsistent mit [was ich gelesen habe] (http://threejs.org/docs/#Manual/Introduction/Matrix_transformations) 'updateMatrix()' (nämlich dass es nicht aufgerufen werden sollte, wenn Setzen Sie 'matrix' manuell, da es die Transformation mit einer über die' position'- und 'rotation'-Eigenschaften berechneten transformiert. –

+1

'Matrix4.set()' verwendet Zeilenreihenfolge, so dass der Code lesbar ist, wenn er als Block in 4 Zeilen gedruckt wird. 'Matrix4.elements' verwendet die Spalten-Haupt-Reihenfolge, um webGL-kompatibel zu sein. 'Matrix4.fromArray()' verwendet die Spalten-Haupt-Reihenfolge, um mit 'Matrix4.elements' kompatibel zu sein. – WestLangley

Verwandte Themen