Three. js Source Code Reading Notes (how objects are organized) _ basic knowledge

Source: Internet
Author: User
Tags linecap
This article will mainly discuss Three. how objects in js are organized: that is, how to combine vertices, surfaces, and materials into a specific object. For details, refer to Three. js Source Code Reading Notes article 3. The previous two articles mainly focus on core objects. These core objects focus on vector vector3 objects and matrix matrix4 objects, focusing on the positions and changes of individual vertices in the space. This article will mainly discuss how Three. js organizes objects: how to combine vertices, surfaces, and materials into a specific object.
Object: Mesh
This constructor constructs an object in a space. The reason is "Grid" is that, in fact, objects with volumes are basically modeled as "grids.

The Code is as follows:


THREE. Mesh = function (geometry, material ){
THREE. Object3D. call (this );
This. geometry = geometry;
This. material = (material! = Undefined )? Material: new THREE. MeshBasicMaterial ({color: Math. random () * 0 xffffff, wireframe: true });
/* Some other content irrelevant to this section */
}


In fact, the Mesh class has only two attributes, indicating the RY ry object of the ry and the material object of the material. The geometry object has been introduced in the previous blog, and some Derived classes will be introduced in this blog (through the construction process of these derived classes, you can better understand the working principle of the Mesh object ); the matrial object and its derived classes will also be introduced in this note. These two attributes of the Mesh object are closely related. In the face array of the geometry object, the materialIndex of each face object is used to match the material attribute object, the vertexUVs array of the face object is used to match the values of each vertex on the array in sequence. It is worth noting that the Mesh can only have one material object (I do not know what the design intent is). If you need to use multiple materials, the material should be initialized in the materials attribute of geometry in the order of materialIndex.
Geometry: CubeGeometry
This constructor creates a cube object.

The Code is as follows:


THREE. CubeGeometry = function (width, height, depth, widthSegments, heightSegments, depthSegments ){
THREE. Geometry. call (this );
Var scope = this;
This. width = width;
This. height = height;
This. depth = depth;
Var width_half = this. width/2;
Var height_half = this. height/2;
Var depth_half = this. depth/2;
/* Skip */
BuildPlane ('Z', 'y',-1,-1, this. depth, this. height, width_half, 0); // px
/* Skip */
Function buildPlane (u, v, udir, vdir, width, height, depth, materialIndex ){
/* Skip */
}
This. computeCentroids ();
This. mergeVertices ();
};


The most important thing the constructor does is buildPlane. The most important thing about this function is to operate the scope (in the code block above, scope is this), including calling scope. vertices. push (vector) adds vertices to the geometry object and calls scope. faces. push (face) adds the surface to the geometry object and calls scope. faceVertexUvs [I]. the push (uv) method adds the material coordinates corresponding to the vertex to the geometry object. Most of the Code is about the logic for generating cubes. These logics are easy to understand and can be easily extended to other types of geometry objects.

Parameters of the constructor include the number of segments in the following directions: length, width, height, and height. The so-called segmentation means that if three parameters, such as widthSeqments, are set to 2, each surface is expressed as 2 × 2 = 4 faces, and the whole cube is composed of 24 surfaces, just like the grid.

The Code is as follows:


Function buildPlane (u, v, udir, vdir, width, height, depth, materialIndex ){
Var w, ix, iy,
GridX = scope. widthSegments,
GridY = scope. heightSegments,
Width_half = width/2,
Height_half = height/2,
Offset = scope. vertices. length;
If (u = 'X' & v = 'y ') | (u = 'y' & v = 'X') {w = 'Z ';}
Else if (u = 'X' & v = 'Z ') | (u = 'Z' & v = 'X') {w = 'y'; gridY = scope. depthSegments;} else if (u = 'Z' & v = 'y ') | (u = 'y' & v = 'Z') {w = 'X'; gridX = scope. depthSegments ;}
Var gridX1 = gridX + 1,
GridY1 = gridY + 1,
Segment_width = width/gridX,
Segment_height = height/gridY,
Normal = new THREE. Vector3 ();
Normal [w] = depth> 0? 1:-1;
For (iy = 0; iy <gridY1; iy ++ ){
For (ix = 0; ix <gridX1; ix ++ ){
Var vector = new THREE. Vector3 ();
Vector [u] = (ix * segment_width-width_half) * udir;
Vector [v] = (iy * segment_height-height_half) * vdir;
Vector [w] = depth;
Scope. vertices. push (vector );
}
}
For (iy = 0; iy <gridY; iy ++ ){
For (ix = 0; ix <gridX; ix ++ ){
Var a = ix + gridX1 * iy;
Var B = ix + gridX1 * (iy + 1 );
Var c = (ix + 1) + gridX1 * (iy + 1 );
Var d = (ix + 1) + gridX1 * iy;
Var face = new THREE. Face4 (a + offset, B + offset, c + offset, d + offset );
Face. normal. copy (normal );
Face. vertexNormals. push (normal. clone (), normal. clone ());
Face. materialIndex = materialIndex;
Scope. faces. push (face );
Scope. faceVertexUvs [0]. push ([
New THREE. UV (ix/gridX, 1-iy/gridY ),
New THREE. UV (ix/gridX, 1-(iy + 1)/gridY ),
New THREE. UV (ix + 1)/gridX, 1-(iy + 1)/gridY ),
New THREE. UV (ix + 1)/gridX, 1-iy/gridY)
]);
}
}
}


Except for the clone () method that most objects have, there are no other methods for CubeGeometry, and other XXXGeometry objects. There is no way to indicate that the object is responsible for organizing and storing data, and how to use the data to generate 3D scenes and animations is defined in another object.
Geometry: CylinderGeometry
As the name suggests, this constructor creates a cylindrical (or circular) object.

The Code is as follows:


THREE. CylinderGeometry = function (radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded ){
/* Omitted */
}


With the basis of the CubeGeometry constructor, we should also be able to implement CylinderGeometry. We only need to pay attention to the significance of the parameters of the constructor. RadiusTop and radiusBottom indicate the radius of the top and bottom, and height indicates the height. RadiusSegments defines how many parts of the circumference (the larger the number is, the more cylinder is), heightSegments defines how many parts of the whole height should be divided, and openEnded specifies whether to generate the top surface and the bottom surface.

There are two points worth noting in the source code: the local origin of the model is the midpoint of the central axis, rather than the center of gravity, that is, the height of the upper circular surface (Y axis value) is height/2, the lower circular area is-height/2, which is no difference for the cylinder, but there is a difference for the circle bodies with different upper and lower radius; in addition, the top surface and the ground of the model adopt face3 type surface, while the side adopt face4 type surface.
Geometry: SphereGeometry
This constructor creates a sphere.

The Code is as follows:


THREE. SphereGeometry = function (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ){
/* Omitted */
}


Meaning of each parameter: radius specifies the radius. widthSegments indicates the number of longitude bands and heightSegments indicates the number of latitude bands. The following four parameters are optional, indicating the start value of the longitude and the start value of the latitude. Familiar with polar coordinates, usually using the Greek letter phi (phi) to represent the latitude angle (longitude), and using θ (theta) to represent the latitude angle (latitude ). The default values of these four numbers are 0, 2 π, 0, and π. By changing their values, you can create incomplete spherical surfaces (but the edges must be neat ).

In the source code, except for the polar circle of the Arctic and Antarctic, face3 is used, and face4 is used for other parts. The local origin is the ball center.
Geometry: PlaneGeometry
This constructor creates a plane.

The Code is as follows:


THREE. PlaneGeometry = function (width, height, widthSegments, heightSegments ){
/* Omitted */
}


Each parameter indicates the number of segments in width, height, width, and height. Readers should be familiar with this method of constructing a "Grid.
Some other information is obtained in the source code: the plane is constructed on the x-y plane, and the origin is the center point of the rectangle.
Geometry: ExtrudeGeometry
This object is now a method to construct a general ry, but we usually store the modeled object in a certain format file and load it through loader, therefore, it seems that there are few opportunities to directly use this function. In addition, this function looks like a semi-finished product. Many of them set up a brain heap in the options object, and I have not studied it carefully.
Material: Material
A Material object is a prototype object of all other types of Material.

The Code is as follows:


THREE. Material = function (){
THREE. MaterialLibrary. push (this );
This. id = THREE. MaterialIdCount ++;
This. name = '';
This. side = THREE. FrontSide;
This. opacity = 1;
This. transparent = false;
This. blending = THREE. NormalBlending;
This. blendSrc = THREE. SrcAlphaFactor;
This. blendDst = THREE. OneMinusSrcAlphaFactor;
This. blendEquation = THREE. AddEquation;
This. depthTest = true;
This. depthWrite = true;
This. polygonOffset = false;
This. polygonOffsetFactor = 0;
This. polygonOffsetUnits = 0;
This. alphaTest = 0;
This. overdraw = false; // Boolean for fixing antialiasing gaps in CanvasRenderer
This. visible = true;
This. needsUpdate = true;
};


Let's take a look at some important attributes:
The opacity attribute is a value in the 0-1 interval, indicating transparency. The property transparent specifies whether to use transparency. Only when this value is true will it be mixed (when transparency is the rendering of pixels, the value to be rendered and the existing value work together to calculate the pixel value after rendering to achieve the mixed effect ).

The blending, blendSrc, blendDst, and blendEquation attributes specify the hybrid mode and the existing image element value Dst weights of the source Src and pixel. By default (such as the default value in the constructor), The New Image Element value equals to the new value x alpha + old value x (1-alpha ).

I used to wonder why the Material class does not have the most important object that represents the attributes of the texture image. Later, I understood that there are still differences between materials and textures. I can only say that some materials have textures, but some materials do not have textures. The material affects the rendering effect of the entire body. For example, the description of "rendering a line with 5px width, square points at both ends, and opaque red" can be considered as a material, it does not involve any textures.

Like many Geometry objects, Material objects have no other methods except General clone (), dellocate (), and setValues () methods. The following are two basic material objects.
Material: LineBasicMaterial
This constructor creates a material used to render a linear shape.

The Code is as follows:


THREE. LineBasicMaterial = function (parameters ){
THREE. Material. call (this );
This. color = new THREE. Color (0 xffffff );
This. linewidth = 1;
This. linecap = 'round ';
This. linejoin = 'round ';
This. vertexColors = false;
This. fog = true;
This. setValues (parameters );
};


Attribute color and linewidth, as the name implies, refer to the color of the line and the width of the line (the line has no width, and the width here is used for rendering ).
The linecap and linejoin attributes specify the style of the line endpoint and connection point.
The fog attribute specifies whether the material is affected by fog.
Material: MeshBasicMaterial
This constructor creates a material used to render the Mesh surface.

The Code is as follows:


THREE. MeshBasicMaterial = function (parameters ){
THREE. Material. call (this );
This. color = new THREE. Color (0 xffffff); // emissive
This. map = null;
This. lightMap = null;
This. specularMap = null;
This. envMap = null;
This. combine = THREE. MultiplyOperation;
This. reflectivity = 1;
This. refractionRatio = 0.98;
This. fog = true;
This. shading = THREE. SmoothShading;
This. wireframe = false;
This. wireframeLinewidth = 1;
This. wireframeLinecap = 'round ';
This. wireframeLinejoin = 'round ';
This. vertexColors = THREE. NoColors;
This. skinning = false;
This. morphTargets = false;
This. setValues (parameters );
};


Here we see the most important texture attributes, including map, lightMap, and specularMap. They are texture objects.
The property wireframe specifies whether the surface boundary is rendered. If rendered, several attributes starting with wireframe indicate how the boundary will be rendered.
Texture: Texture
This constructor is used to create a texture object.

The Code is as follows:


THREE. Texture = function (image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ){
THREE. TextureLibrary. push (this );
This. id = THREE. TextureIdCount ++;
This. name = '';
This. image = image;
This. mapping = mapping! = Undefined? Mapping: new THREE. UVMapping ();
This. wrapS = wrapS! = Undefined? WrapS: THREE. ClampToEdgeWrapping;
This. wrapT = wrapT! = Undefined? WrapT: THREE. ClampToEdgeWrapping;
This. magFilter = magFilter! = Undefined? MagFilter: THREE. LinearFilter;
This. minFilter = minFilter! = Undefined? MinFilter: THREE. LinearMipMapLinearFilter;
This. anisotropy = anisotropy! = Undefined? Anisotropy: 1;
This. format = format! = Undefined? Format: THREE. RGBAFormat;
This. type = type! = Undefined? Type: THREE. UnsignedByteType;
This. offset = new THREE. Vector2 (0, 0 );
This. repeat = new THREE. Vector2 (1, 1 );
This. generateMipmaps = true;
This. premultiplyAlpha = false;
This. flipY = true;
This. needsUpdate = false;
This. onUpdate = null;
};


The most important attribute is image, which is a JavaScript Image type object. The first parameter passed in is the object. How to create the object is described later.

The following objects are optional. If the default value is used, the default value is filled, and the default value is often filled.
Attribute magFileter and minFileter specify the filtering method for the texture to zoom in or out: newest vertex, bilinear interpolation, and so on.
Generate a texture from the url and call Three. ImageUtils. loadTexture (paras). This function returns a texture type object. Inside the function, the THREE. ImageLoader. load (paras) function is called again, and the THREE. Texture () constructor is called internally to generate a Texture.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.