Three.js 소스 코드 읽기 노트의 두 번째 글입니다. 바로 시작해 보겠습니다.
Core::Object3D
Object3D는 Three.js 프레임워크에서 가장 중요한 클래스인 것 같습니다. 장면 클래스, 기하학 클래스, 클래스, 조명 클래스 등: 모두 3D 공간의 개체이므로 Object3D 클래스라고 합니다. Object3D 생성자는 다음과 같습니다.
THREE. Object3D = function () {
THREE.Object3DLibrary.push( this );
this.id = THREE.Object3DIdCount;
this.name =
this.properties; 🎜>this.parent = 정의되지 않음;
this.children = [];
this.up = new THREE.Vector3( 0, 1, 0 )
this.position = new THREE.Vector3() ;
this .rotation = new THREE.Vector3();
this.eulerOrder = THREE.Object3D.defaultEulerOrder
this.scale = new THREE.Vector3( 1, 1, 1 ); this.renderDepth = null ;
this.rotationAutoUpdate = true;
this.matrix = new THREE.Matrix4();
this.matrixWorld = new THREE.Matrix4(); new THREE.Matrix4( );
this.matrixAutoUpdate = true;
this.quaternion = new THREE.Quaternion()
this.boundRadius = 0.0;
this.boundRadiusScale = 1.0;
this.castShadow = false;
this.frustumCulled = true;
this._Vector = new THREE.Vector3();
함수를 소개하기 전에 이 클래스의 몇 가지 중요한 속성을 소개해야 합니다.
상위 및 하위 속성에 대한 설명, 일반적으로 많은 Object3D 개체를 관리하려면 트리를 사용해야 합니다. 예를 들어, 움직이는 자동차는 Object3D 개체이고 자동차의 주행 경로를 제어하는 논리는 개체 내부에 구현됩니다. 자동차의 각 정점은 모델 매트릭스에 의해 처리된 후 올바른 위치에 위치합니다. 자동차는 자동차의 방향으로 움직일 뿐만 아니라 자동차를 기준으로 좌우로 흔들리기도 합니다. 이 스윙의 논리는 자동차의 객체 내부에서 구현될 수 없습니다. 해결책은 와이퍼를 자동차의 하위 위치에 설정하는 것이며, 와이퍼 내부의 로직은 자동차에 대한 와이퍼의 스윙만 담당합니다. 이 트리 구조에서 장면 장면은 실제로 최상위 Object3D이고 해당 모델 행렬은 뷰 행렬의 역행렬입니다(카메라에 따라 다름).
매트릭스와 매트릭스 월드 속성은 이해하기 쉽습니다. 매트릭스는 객체의 움직임만 나타내는 로컬 모델 매트릭스를 나타내는 반면, 매트릭스 월드는 순서대로 상위 노드까지 반복해야 합니다. 부모 개체의 로컬 값 모델 행렬(장면 개체까지) - 물론 실제로는 부모 개체의 전역 모델 행렬을 곱한 값입니다.
위치, 회전, 크기 조정 속성은 Matrix4 클래스에서 설명하는 모델 행렬의 세 가지 변환 부분을 나타냅니다. 회전과 eulerOrder는 함께 회전 상태를 설명하고 쿼터니언은 회전 상태를 설명할 수도 있습니다. 사용할 구체적인 방법은 useQuation의 부울 값에 따라 다릅니다.
Object3D 개체에 대한 가장 중요한 "변환 상태" 정보가 실제로 두 개의 "백업"에 저장되어 있음을 알 수 있습니다. 하나는 행렬 개체이고 다른 하나는 위치 및 기타 속성, 두 부분입니다. 일관성을 유지해야 하며, 한 백업이 어떤 방법으로 변경되면 다른 백업도 적시에 업데이트되어야 합니다. 그 의미를 문자 그대로나 유형별로 볼 수 있으며 별도로 나열되지 않은 몇 가지 다른 속성이 있습니다. 아래 함수에 대해 이야기해 보겠습니다.
applyMatrix(matrix) 함수는 왼쪽의 매개변수 행렬에 this.matrix를 곱합니다. 이는 실제로 Object3D 개체에 대해 특정 변환을 수행합니다(이 변환에는 몇 가지 기본 변환 단계가 필요할 수 있지만 매개변수 매트릭스에 저장되었습니다). this.matrix에 대해 왼쪽 곱셈을 수행한 후 위치와 같은 매개변수의 값이 즉시 업데이트된다는 점에 유의하세요. 다음 변환 함수와 비교하면 이 함수는 더 "고급"되어 개발자가 "x축 방향으로 5단위 전진"이라고 말하는 대신 변환 행렬을 자유롭게 지정할 수 있습니다.
코드 복사
코드는 다음과 같습니다.
translate(distance, axis) 함수는 객체가 축 축에서 지정한 방향으로 거리만큼 이동하도록 합니다. translateX(거리),translateY(거리),translateZ(거리)함수는 X, Y, Z축까지의 거리를 전진시킵니다. 이러한 함수는 위치 개체의 값만 변경하며 행렬의 값은 변경하지 않습니다.
번역: 함수( 거리, 축 ) {
this.matrix.rotateAxis( 축 );
this.position.addSelf( axis.multiplyScalar( 거리 ) )
},
translateX: function( 거리 ) {
this.translate ( distance, this._Vector.set( 1, 0, 0 ) );
},
localToWorld(벡터) 함수는 로컬 좌표를 월드 좌표로 변환하는 반면, worldToLocal 함수는 반대. 여기서 벡터의 로컬 좌표는 변환 전의 좌표, 즉 와이퍼 기본 위치의 정점 좌표를 의미합니다.
lookAt(eye,center,up) 함수는 일반적으로 카메라 객체에 사용되는 행렬 속성 객체(앞서 소개한 것처럼 Matrix4 객체에도 LookAt 함수가 있음)의 LookAt 함수를 실행합니다. 이 함수는 회전 상태만 변경하므로 행렬 속성 객체가 실행될 때 RotationAutoUpdate 속성이 true이면 회전 또는 쿼터니언 값이 업데이트되며 업데이트되는 값은 useQuation 속성에 따라 다릅니다.
add(객체) 함수와 제거(객체) 함수는 현재 Object3D 객체에서 하위 객체를 추가하거나 하위 객체를 삭제하는 기능입니다. 장면의 많은 Object3D 객체가 트리를 사용하여 관리된다는 것을 이해하기 쉽습니다. .
traverse(callback) 함수는 호출자와 호출자의 모든 하위 항목을 순회합니다. 콜백 매개변수는 호출 수신자와 각 하위 개체가 callback(this)을 호출하는 함수입니다.
traverse: function ( callback ) {
callback( this );
for ( var i = 0, l = this.children.length; i < l; i ) {
this.children[ i ].traverse( 콜백 ); }
},
getChildByName(name, recursive) 함수는 문자열을 통해 호출자의 하위 요소(recursive가 false) 또는 하위 요소(recursive가 true)와 일치하는 개체를 쿼리합니다. 속성 이름을 입력하고 이를 반환합니다.
getDescendants(array) 함수는 호출자의 모든 하위 개체를 배열 배열로 푸시합니다.
updateMatrix() 및 updateMatrixWorld(force) 함수는 위치, 회전 또는 쿼터니언, 배율 매개변수에 따라 행렬 및 MatrixWorld를 업데이트합니다. updateMatrixWorld는 force 값이 true이거나 호출자 자체의 MatrixWorldNeedsUpdate 값이 true인 경우 모든 하위 요소의 MatrixWorld도 업데이트합니다. applyMatrix(matrix) 함수에서는 행렬 값을 변경한 후 위치, 회전 등 기타 속성이 즉시 업데이트되지만,translate(거리,축) 함수에서는 위치 및 기타 변수가 변경되거나(또는 위치 및 기타 속성이 변경됨) 직접 변경) 즉시 업데이트되지 않습니다. 행렬 값을 업데이트하려면 updateMatrix()를 수동으로 호출해야 합니다. 이러한 세부 사항은 주목할 가치가 있습니다. 이벤트 리스너를 추가해야 한다고 생각할 수도 있습니다. 하나의 값이 변경되면 다른 모든 값이 즉시 업데이트되지만, 적절한 시기에 업데이트하면 효율성이 높아진다는 점을 고려한 것일 수도 있습니다. - 예를 들어 회전 값은 자주 변경될 수 있지만 행렬 속성은 사용하기 전에만 업데이트됩니다.
updateMatrix: function () {
this.matrix .setPosition( this.position );
if ( this.useQuaternion === false ) {
this.matrix.setRotationFromEuler( this.rotation, this.eulerOrder )
}; 🎜>this .matrix.setRotationFromQuaternion( this.quaternion );
}
if ( this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z ! == 1 ) {
this.matrix.scale( this.scale );
this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale. z ) ) ;
}
this.matrixWorldNeedsUpdate = true;
},
updateMatrixWorld: function ( force ) {
if ( this.matrixAutoUpdate === true ) this.updateMatrix() ;
if ( this.matrixWorldNeedsUpdate === true || force === true ) {
if ( this.parent === 정의되지 않음 ) {
this.matrixWorld.copy( this.matrix );
} else {
this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix )
}
this.matrixWorldNeedsUpdate = false;
force = true;
for ( var i = 0, l = this.children.length; i < l; i ) {
this.children[ i ].updateMatrixWorld( force )
}
},
dealcate 함수는 객체가 더 이상 필요하지 않을 때 호출자가 점유한 공간을 수동으로 해제합니다.
Core::Projectors
프로젝션 행렬을 관리하는 클래스입니다. 코드가 너무 복잡합니다. 적절한 시점에 살펴보겠습니다.
Core::UV 이 생성자는 재료 좌표 클래스(종종 래스터화 후 정점에 해당하는 재료 좌표)를 생성합니다. 그런 다음 "를 선택합니다. "색상"을 재료에서 추출하여 질감을 얻습니다.
THREE.UV = 함수( u, v ) {
this.u = u || 0;
this.v = v || 0
}
간단한 벡터2 클래스입니다. 속성 이름을 제외하고는 다릅니다.
Core::Ray Core::Rectangle Core:Spline 원점, 방향, 원거리 및 근거리 차단점이 있는 Ray 클래스입니다. 점광원에 적용이 있어야 합니다. 직사각형 및 곡선 유형은 상대적으로 단순하며 "핵심"이 아닙니다.
Core::Geometry Geometry 클래스도 꼭지점과 표면으로 구성된 기하학적 모양을 나타내는 매우 중요한 클래스입니다.
THREE.Geometry = function () {
THREE .GeometryLibrary.push( this );
this.id = THREE.GeometryIdCount;
this.name = ''; ];
this.normals = [];
this.faces = [];
this.faceUvs = [[]]
this.faceVertexUvs = [[]]; .morphTargets = [];
this.morphColors = [];
this.morphNormals = [];
this.skinWeights =
this.skinIndices = []; .lineDistances = [];
this.boundingBox = null;
this.hasTangents = false;
this.verticesNeedUpdate = false ;
this.elementsNeedUpdate = false;
this.normalsNeedUpdate = false;
this.colorsNeedUpdate = false; >this.buffersNeedUpdate = false;
};
다음 두 가지 속성 세트가 가장 중요합니다
:
속성 정점은 배열이며 각 요소는 꼭지점 좌표를 나타내는 벡터3 유형의 객체입니다. 색상 및 법선 속성은 정점에 해당하는 색상 값 및 검색 벡터를 나타냅니다. 대부분의 경우 정점의 색상 및 검색 벡터는 "표면"에 정의됩니다. 큐브의 측면 색상이 다르므로 각 꼭지점은 실제로 면마다 다른 색상입니다.
faces 속성은 배열이고, 각 요소는 Face4 또는 Face3 유형의 객체입니다. 이전에 Face3을 소개했을 때, Face는 정점의 인덱스 값만 저장하며, 인덱스 값은 다음과 같을 수 있다고 언급했습니다. 배열 정점에 사용됩니다. 정점의 좌표 값을 가져옵니다.
다음은
함수입니다.
applyMatrix(matrix) 함수는 기하학의 모든 정점 좌표와 표면의 법선 벡터를 업데이트합니다. 실제로 변환 행렬을 사용합니다. 기하학을 기하학에 적용하기 위한 행렬입니다. 모양은 공간 변환을 거칩니다. NormalMatrix는 매개변수 행렬의 왼쪽 상단에 있는 3×3 행렬의 역전치 행렬입니다. 이 행렬은 벡터(정점 좌표가 아닌 법선)를 회전하는 데 사용됩니다.
코드 복사
코드는 다음과 같습니다. applyMatrix: 함수( 매트릭스 ) {
varface = this.faces[ i ];
normalMatrix.multiplyVector3(face.normal).normalize()
for ( var j = 0, jl = face.vertexNormals.length ; j < ; jl; j ) {
normalMatrix.multiplyVector3( face.vertexNormals[ j ] ).normalize()
matrix.multiplyVector3(
}
},
ComputeCentroid() 함수는 기하학 자체의 무게 중심이 아닌 기하학에 있는 각 표면의 무게 중심을 계산합니다. 이 함수는 얼굴 클래스의 프로토타입에 배치하는 것이 더 좋을 것 같지만, 점의 좌표는 얼굴 클래스에서 내부적으로 얻을 수 없기 때문에(점 좌표 배열에 대한 참조가 매개변수로 생성자에 전달되지 않는 한, 이는 매우 비용이 많이 듭니다.) 이는 단지 Index 값이므로 기하학 클래스의 프로토타입에 정의되어야 합니다. 다음 함수들도 비슷한 상황이다. (사실 얼굴 클래스에는 멤버 함수가 거의 없다.)
createMorphNormal 함수는 각 모프에 대한 법선을 생성합니다. 고정된 연속 애니메이션의 변형 효과를 표시하려면 Morph를 사용해야 합니다.
mergeVertics 함수는 좌표 값이 동일한 점을 제거하고 얼굴 개체의 점 인덱스 값을 업데이트합니다.
Core::Quaternian
4차원 회전 클래스는 회전을 사용하는 것과 비교하여 회전 변환을 다른 방식으로 표현하므로 짐벌 교착 상태 문제를 피할 수 있습니다. THREE.Quaternion = function( x, y , z, w ) {
this.x = x || 0;
this.z = z || 0; w != = 정의되지 않음 ) ? w : 1;
};
함수에 대해 이야기하지 않는다면 Quaternian은 단순한 벡터4 유형 객체입니다.
setFromEuler(v,order) 함수는 오일러 회전을 통해 4차원 회전을 설정합니다.
setFromAxis(axis,angle) 함수는 임의의 축을 중심으로 회전하여 4차원 회전을 설정합니다.
setFromRotationMatrix(matrix) 함수는 회전 행렬을 통해 4차원 회전을 설정합니다.
Vector4 클래스와 동일하지만 여기에 나열되지 않은 일부 기능도 있습니다.