API documentation: https://threejs.org/docs/index.html
The following source code comes from: three js v0. one hundred and thirty-five
How to view the source code
Create a blank npm project. After npm install three is executed in the project, select the node in the project_ Three is in the modules / three directory JS code.
build directory: packaged three JS code. Of which:
- three.js: three. JS script version of JS
- three.module.js: three. ES Module version of JS
src Directory: three JS source code
It is recommended to be familiar with the basic functions and usage of the class through the API document, and then read the source code of the class.
Basic tools
Vector2
Two dimensional vector. It can be used to express many things, such as:
- A point on a plane: (x,y)
- Direction and length of a in the plane: from (0,0) to (x,y)
Basic usage:
const a = new THREE.Vector2( 0, 1 ); const b = new THREE.Vector2( );//no arguments; will be initialised to (0, 0) const d = a.distanceTo( b );
Source code overview:
class Vector2 { constructor(x = 0, y = 0) { this.x = x; this.y = y; } // ... }
Vector3
Three dimensional vector. It can be used to express many things, such as:
- A point in space: (x,y,z)
- A direction and length in space: from (0,0,0) to (x,y,z)
Basic usage:
const a = new THREE.Vector3( 0, 1, 0 ); const b = new THREE.Vector3( );//no arguments; will be initialised to (0, 0, 0) const d = a.distanceTo( b );
Vector4
Four dimensional vector. It is often used to represent homogeneous coordinates.
Source code overview:
class Vector4 { constructor( x = 0, y = 0, z = 0, w = 1 ) { this.x = x; this.y = y; this.z = z; this.w = w; } // ... }
Quaternion
Quaternion, in three JS is used to represent rotation.
Basic usage:
const quaternion = new THREE.Quaternion(); // setFromAxisAngle(axis, angle) quaternion.setFromAxisAngle( new THREE.Vector3( 0, 1, 0 ), Math.PI / 2 ); const vector = new THREE.Vector3( 1, 0, 0 ); vector.applyQuaternion( quaternion );
Matrix3
Three dimensional matrix.
Basic usage:
const m = new Matrix3(); // Create an identity matrix
Source code overview:
class Matrix3 { constructor() { this.elements = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; } // Current matrix = current matrix multiplied by matrix multiply(matrix) {...} // Current matrix = matrix times current matrix premultiply(matrix) {...} // Current matrix = inverse of current matrix invert(){...} // Current matrix = inverse transpose matrix of 3rd order matrix in the upper left corner of 4-dimensional matrix matrix4 getNormalMatrix(matrix4){} // Current matrix = identity matrix of current matrix identity(){...} // Current matrix = transpose matrix of current matrix transpose(){...} }
Note the order of row priority and column priority:
The set() method parameters adopt row major, and they are internally stored in the array in column major order, which means:
m.set( 11, 12, 13, 21, 22, 23, 31, 32, 33 );
The element array elements will be stored as:
m.elements = [ 11, 21, 31, 12, 22, 32, 13, 23, 33 ];
Internally, all calculations are performed using column precedence.
Matrix4
4-dimensional matrix. The most common use of a 4x4 matrix is as a transformation matrix.
Any 3D object has three associated matrices:
-
Object3D.matrix: local transformation matrix of the object (also known as local transformation matrix. Transformation matrix, that is, model matrix). This is the transformation matrix of the object relative to its parent object.
-
Object3D.matrixWorld: the global transformation matrix (or world transformation matrix) of the object. If the object has no parent object, it is the same as its local transformation matrix. (personal understanding: for example, there is an object B in object A, and object A has no parent object. The matrix of object A is translated to the left by 30m, while the matrix of object B is translated to the left by 10m. Then the matrixWorld of object A is translated to the left by 30m, and the matrixWorld of object B is translated to the left by 40m)
-
Object3D.modelViewMatrix: represents the transformation matrix of the object relative to the camera coordinate system (in other words, through this matrix, the object can be transformed into the camera coordinate system, which is the same as the definition of modelViewMatrix in WebGL). The modelViewMatrix of an object is equal to the inverse matrix of the camera's world transformation matrix multiplied by the object's world transformation matrix. (personal understanding: because of the relative relationship between the object and the camera, the inverse matrix of the matrixWorld of the camera should be equivalent to the viewMatrix of the object, and the matrixWorld of the object is actually the modelMatrix of the object, so the modelViewMatrix of the object is equal to the multiplication of the two)
Camera camera is a subclass of Object3D. In addition to the above matrices, it has several additional four-dimensional matrices:
- Camera.projectionMatrix: projection matrix.
- Camera. matrixWorld inverse: view matrix, which is the inverse matrix of matrixWorld of Camara.
Review the three matrices of the Web GL system: the matrixWorld of the object is modelMatrix, camera Matrixworldinverse is the viewMatrix, and camera The projectionMatrix is the projectionMatrix.
There are several options for extracting position (translation), rotation, and scaling from Matrix4.
- Vector3.setFromMatrixPosition: extract position related components.
- Vector3.setFromMatrixScale: extract scaling related components.
- Quaternion.setFromRotationMatrix,Euler. Set from rotation matrix or extractRotation: extract rotation related components from a pure (non scaled) matrix.
- decompose: can be used to extract position, rotation and scaling components at one time.
Object3D class
Object3D
This is three The base class of most objects in JS provides a series of attributes and methods to manipulate objects in three-dimensional space.
Source code overview:
let _object3DId = 0; class Object3D extends EventDispatcher { constructor() { super(); Object.defineProperty(this, 'id', { value: _object3DId++ }); this.type = 'Object3D'; this.parent = null; this.children = []; // One Object3D can contain multiple sub Object3D Object.defineProperties(this, { // Local position (translation. Initial position: (0,0,0)) position: { configurable: true, enumerable: true, value: new Vector3() }, // Local rotation // Quaternions are used in three.js to represent rotations quaternion: { configurable: true, enumerable: true, value: new Quaternion() }, // Local scaling scale: { configurable: true, enumerable: true, value: new Vector3(1, 1, 1) }, // modelViewMatrix // It is equal to the inverse matrix of the world model matrix of the camera multiplied by the world model matrix of the object. See the explanation in Matrix4 for details modelViewMatrix: { value: new Matrix4() }, // "Magic matrix" for transforming vertex normal vector, inverse transpose matrix of modelViewMatrix. Refer to "WebGL programming guide abstract. md" normalMatrix: { value: new Matrix3() } }); // Local model matrix // Contains this position, this. quaternion, this. Scale information, i.e. position (translation), rotation and zoom this.matrix = new Matrix4(); // World model matrix this.matrixWorld = new Matrix4(); // ... } // According to this position, this. quaternion, this. Scale update this matrix updateMatrix() { // By this position, this. quaternion, this. Scale generates this matrix this.matrix.compose(this.position, this.quaternion, this.scale); this.matrixWorldNeedsUpdate = true; } // According to this Matrix update this matrixWorld and update matrixWorld for all child ren updateMatrixWorld(force) { } // Local rotation rotateOnAxis(axis, angle) { } // Local Translation translateOnAxis(axis, distance) { } // Local rotation, local translation and local scaling are carried out through a matrix applyMatrix4(matrix) { this.matrix.premultiply(matrix); // Put this This is extracted from the position, rotation and scaling components in the matrix position, this. quaternion, this. In scale this.matrix.decompose(this.position, this.quaternion, this.scale); } // Add / delete sub Object3D add(object) { } remove(object) { } // ... }
The translation, rotation and scaling methods of Object3D do not modify the position coordinates of vertices (Object3D and its subclasses do not store the position coordinates of vertices), but indirectly modify the local model matrix to realize translation, rotation and scaling.
Comparison: BufferGeometry and its subclasses store the position coordinates of each vertex. Their translation, rotation and scaling are realized by modifying the position coordinates of vertices.
Scene
Scene. This is where you place objects, lights and cameras.
Source code overview:
class Scene extends Object3D { constructor() { super(); this.type = 'Scene'; this.background = null; this.environment = null; this.fog = null; } // ... }
Camera & PerspectiveCamera
Camera
Source code overview:
class Camera extends Object3D { constructor() { super(); this.type = 'Camera'; // The inverse matrix of the camera's world model matrix, that is, the view matrix, is explained in Matrix4 above this.matrixWorldInverse = new Matrix4(); // Projection matrix this.projectionMatrix = new Matrix4(); } // ... }
PerspectiveCamera
Source code overview:
class PerspectiveCamera extends Camera { constructor(fov = 50, aspect = 1, near = 0.1, far = 2000) { super(); this.type = 'PerspectiveCamera'; this.fov = fov; this.aspect = aspect; this.near = near; this.far = far; // Update the projection matrix according to the above parameters this.updateProjectionMatrix(); } // ... }
Mesh
Represents an object based on a triangular mesh.
Source code overview:
class Mesh extends Object3D { constructor(geometry = new BufferGeometry(), material = new MeshBasicMaterial()) { super(); this.type = 'Mesh'; this.geometry = geometry; this.material = material; // ... } // ... }
Geometric class
BufferGeometry
Store the vertex information constituting a geometry, including vertex coordinates, vertex normal vector, vertex texture coordinates, vertex index, etc.
Basic usage:
const geometry = new THREE.BufferGeometry(); // Create a simple rectangle It consists of two triangles const vertices = new Float32Array( [ -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0 ] ); geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); const material = new THREE.MeshBasicMaterial( { color: 0xff0000 } ); const mesh = new THREE.Mesh( geometry, material );
Source code overview:
let _id = 0; class BufferGeometry extends EventDispatcher { constructor() { super(); Object.defineProperty(this, 'id', { value: _id++ }); this.type = 'BufferGeometry'; // Vertex attributes, including vertex coordinates, vertex normal vector, vertex texture coordinates, vertex index, etc this.attributes = {}; } // Apply matrix to vertex attributes such as vertex coordinates and vertex normal vector. The effects are rotation, translation and scaling applyMatrix4(matrix) { } // Rotate, translate and zoom. It is implemented internally by calling applyMatrix4 rotateX(angle) { } rotateY(angle) { } rotateZ(angle) { } translate(x, y, z) { } scale(x, y, z) { } // Set vertex attributes (this.attributes[name]) setAttribute( name, attribute ) { this.attributes[ name ] = attribute; return this; } // Set vertex coordinates (this.attributes['position ']) setFromPoints(points) { const position = []; for ( let i = 0, l = points.length; i < l; i++ ) { const point = points[ i ]; position.push( point.x, point.y, point.z || 0 ); } this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); } // ... }
BoxGeometry
The specific geometry represented by BoxGeometry is a simple encapsulation of the basic geometry BufferGeometry.
BufferGeometry requires us to manually input various vertex attributes, while BoxGeometry and other specific geometry can automatically calculate various vertex attributes according to the parameters of the constructor.
Source code overview:
// Cube class BoxGeometry extends BufferGeometry { // Parameters: width, height, depth, width split segment, height split segment, depth split segment constructor(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) { super(); this.type = 'BoxGeometry'; const indices = []; // Vertex Index const vertices = []; // Vertex coordinates const normals = []; // Vertex normal vector const uvs = []; // Vertex texture coordinates // According to the constructor parameters, calculate the vertex coordinates, vertex normal vector, vertex texture coordinates and vertex index of each face of the cube // build each side of the box geometry buildPlane('z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0); // px buildPlane('z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1); // nx buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2); // py buildPlane('x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3); // ny buildPlane('x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4); // pz buildPlane('x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5); // nz // Store vertex coordinates, vertex normal vector, vertex texture coordinates and vertex index this.setIndex(indices); this.setAttribute('position', new Float32BufferAttribute(vertices, 3)); this.setAttribute('normal', new Float32BufferAttribute(normals, 3)); this.setAttribute('uv', new Float32BufferAttribute(uvs, 2)); function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) { } } // ... }
Material class
Material
Base class of various materials.
Source code overview:
let materialId = 0; class Material extends EventDispatcher { constructor() { super(); Object.defineProperty(this, 'id', { value: materialId++ }); this.type = 'Material'; this.vertexColors = false; // Use vertex color this.format = RGBAFormat; this.opacity = 1; // transparency this.transparent = false; // Do you want to use transparency // blend this.blending = NormalBlending; this.blendSrc = SrcAlphaFactor; this.blendDst = OneMinusSrcAlphaFactor; // Depth detection this.depthFunc = LessEqualDepth; this.depthTest = true; // polygon offset this.polygonOffset = false; this.polygonOffsetFactor = 0; this.polygonOffsetUnits = 0; // ... } // ... }
MeshBasicMaterial
Base mesh material.
Source code overview:
/** * parameters = { * color: <hex>, * opacity: <float>, * map: new THREE.Texture( <Image> ), * * lightMap: new THREE.Texture( <Image> ), * lightMapIntensity: <float> * * aoMap: new THREE.Texture( <Image> ), * aoMapIntensity: <float> * * specularMap: new THREE.Texture( <Image> ), * * alphaMap: new THREE.Texture( <Image> ), * * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), * combine: THREE.Multiply, * reflectivity: <float>, * refractionRatio: <float>, * * depthTest: <bool>, * depthWrite: <bool>, * * wireframe: <boolean>, * wireframeLinewidth: <float>, * } */ class MeshBasicMaterial extends Material { constructor(parameters) { super(); this.type = 'MeshBasicMaterial'; // ... } // ... }
Renderer
WebGLRenderer
Source code overview:
function WebGLRenderer(parameters = {}) { // Canvas dom and canvas size this.domElement = _canvas; let _width = _canvas.width; let _height = _canvas.height; _canvas.addEventListener('webglcontextlost', onContextLost, false); _canvas.addEventListener('webglcontextrestored', onContextRestore, false); // The internal code of render function is very complex. You can see it later if necessary this.render = function (scene, camera) { // ... } // ... }