I am participating in the Mid-Autumn Festival Creative Submission contest, please see: Mid-Autumn Festival Creative Submission Contest for details

preface

This paper takes the realization of a 3D moon as an example to get started with three.js. There have been many articles describing how to realize a 3D moon in digging gold, but they have not introduced in detail the methods used in the realization of a 3D moon and the role and influence of its parameters. This paper will introduce them in detail.

The introduction of three. Js

Run the NPM install three –save command. After the installation is successful, run the NPM install three –save command.

Import {//… } from “three” to introduce the required method from three.js.

import {
  Scene,
  WebGLRenderer,
} from "three";
Copy the code

Create a scene

Simply create a container in which objects are displayed, using the Scene class.

this.scene = new Scene();
Copy the code

Scene provides an instance method add to add content to the Scene.

this.scene.add()
Copy the code

This is because Scene inherits Object3D. Add is an instance method of Object3D. You can find add in the introduction of Object3D.

Create a renderer

The renderer is used to render the content added to the scene, using the WebGLRenderer class.

this.renderer = new WebGLRenderer();
document.querySelector("#planet").appendChild(this.renderer.domElement);
Copy the code

The constructor of the WebGLRenderer class receives a configuration object, which may or may not be passed, and will be configured with the most reasonable value. The renderer outputs a canvas, which can be set to the length and width using the setSize instance method.

this.renderer.setSize(innerWidth, innerHeight);
Copy the code

The renderer key creation is complete. We need to obtain the renderer generated Canvas DOM object through the domElement property, and then add it to the Document.

document.querySelector("#planet").appendChild(this.renderer.domElement);
Copy the code

Create a camera

The camera is a key element in Three.js, and different cameras produce different 3D effects. There are two types of cameras in Three. One is the orthogonal camera and the perspective camera. In an orthogonal camera, the size of the object presented to the user’s eye remains constant regardless of whether the object is far or close to the camera. In perspective camera, it is in line with the characteristics of our eyes to observe things, near big and far small.

To achieve a 3D moon, we chose the perspective camera, the moon is actually large, the earth is away from the moon, the moon looks very small, which fits the perspective camera effect.

Perspective cameras are created using the PerspectiveCamera class. The Constructor of the PerspectiveCamera class accepts parameters that control how the object is presented.

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

  • fov– The vertical field of view of the camera cone is also called the visual Angle
  • aspect– Length to width ratio of the camera cone
  • near– Distance between the camera and the near end of the viewing cone
  • far– Distance between the camera and the distal end of the viewing cone

Before we understand these parameters, we need to understand the concept of the camera’s visual cone, using a diagram to illustrate the concept of the following terms in the visual cone.

  • The vertical field of view of the camera cone is alpha in the figure.
  • The near end face of the camera’s viewing cone is the near plane in the figure.
  • The far end face of the camera’s viewing cone is the far plane in the figure.
  • The aspect ratio of the camera’s viewing cone indicates the ratio of the width to the height of the output image.

The meanings of FOV, aspect, NEAR and FAR parameters are illustrated in the two figures.

Only when the distance from the camera is greater than near value, less than FAR value, and within foV of the camera’s visual Angle, can the camera take photos. This region is called the view body. Just as in the perspective view, the gray part is the view body, which is the area where the object that may be rendered is located.

Fov is the Angle of the view vertically (in angles rather than radians), as shown in the side view.

Aspect is equal to width/height, which is the ratio of the camera’s horizontal and vertical lengths, usually set as the horizontal and vertical ratio of canvas.

Near and FAR are the nearest and furthest distances from the camera to the viewing body respectively, both of which are positive values, and FAR should be greater than NEAR.

Under the premise that aspect, near and far remain unchanged, the larger FOV is, the smaller the object in the view will be. This is why the size of the object relative to the whole view becomes smaller, and the object appears smaller. The actual size of the object doesn’t change.

On the premise that the position of the camera remains unchanged, the larger the NEAR is, the smaller the object in the view will be, which conforms to the feature of perspective camera of “larger near and smaller far”.

Use the PerspectiveCamera class to create a PerspectiveCamera.

this.camera = new PerspectiveCamera(75, innerWidth / innerHeight, 1, 1000);
Copy the code

The innerWidth and innerHeight are the width and height of the browser’s view window, indicating that the image viewed through the camera is spread across the browser page.

Once the camera is created, it is also positioned via the Position property of the PerspectiveCamera instantiation object, which inherits the Object3D base class and is an instantiation object of Vector3 with a set instance method that sets the coordinates of x, y, and z. The right-handed coordinate system is used in three.js.

// this.camera.position.set(x, y, z);
this.camera.position.set(0, 0, 100);
Copy the code

To position the camera is to make the object appear in the view the camera produces. In order to keep the object from deforming, we usually just adjust the z coordinate. The z value can only be between near and far, and the smaller the z value, the larger the object.

Once you’ve positioned your camera, there’s one more important thing to do: always point the camera toward the scene.

this.camera.lookAt(this.scene.position);
Copy the code

Create a sphere

With the basic setup set up above, let’s create a sphere as the moon. Before creating it, let’s put the code together.

this.scene = new Scene();
this.renderer = new WebGLRenderer();
this.renderer.setSize(innerWidth, innerHeight);
document.querySelector("#planet").appendChild(this.renderer.domElement);
this.camera = new PerspectiveCamera(75, innerWidth / innerHeight, 1, 1000);
this.camera.position.set(0, 0, 100);
this.camera.lookAt(this.scene.position);
Copy the code

A sphere is a type of geometry. Three. js provides a list of classes for creating geometry. You can use the SphereGeometry class to create a sphere.

SphereGeometry(radius : Float, widthSegments : Integer, heightSegments : Integer, phiStart : Float, phiLength : Float, thetaStart : Float, thetaLength : Float

  • Radius – The radius of the sphere. The default is 1.
  • WidthSegments – Number of horizontal segments (along the longitude) with a minimum of 3 and a default of 8.
  • HeightSegments – The number of vertical segments (along the latitude), with a minimum value of 2 and a default value of 6.
  • PhiStart – Specifies the starting Angle of the horizontal (warp). Default is 0.
  • PhiLength – Specifies the size of the horizontal (warp) scan Angle. The default is math.pi * 2.
  • ThetaStart – Specifies the vertical (latitude) start Angle. Default is 0.
  • ThetaLength – Specifies the vertical (latitude) scan Angle. Default is math.pi.

The meanings of widthSegments and heightSegments are shown in the following figure. The larger the value is, the rounder the sphere is created. This is because in the underlying graphics implementation, there is no concept of curves, curves are approximated by multiple broken lines. For a sphere, when these two values are large, the polyhedron formed can be approximated as a sphere.

PhiStart, phiLength, thetaStart, and thetaLength are in degrees (degrees) and are usually assigned by math. PI. Math.PI is 180 degrees, so 90 degrees is math. PI/2.

For example, create a left hemisphere new SphereGeometry(6,32,32, math.pi, math.pi).

For example, create a right hemisphere new SphereGeometry(6,32,32,0, math.pi).

For example, create a new SphereGeometry(6,32,32,0, math.pi *2,0, math.pi /2) on the upper hemisphere.

However, write down

Const geometry = new SphereGeometry(30,32,32); this.scene.add(geometry);Copy the code

You’ll find that the expected sphere doesn’t appear. This is because we haven’t painted the sphere yet, so of course we can’t see it.

Add color to the sphere

To color geometry in three.js with materials, start by using the MeshBasicMaterial class to create a material that is not affected by light. In other words, it is always on.

const material = new MeshBasicMaterial({ color: 0xffff00});
Copy the code

Once you’ve created the material (color), how do you color the sphere? You use the Mesh, which is basically a Mesh to attach the colored materials to the sphere.

Mesh( geometry : Geometry, material : Material )

  • Geometry of Geometry

  • Material Material

this.moon = new Mesh(geometry, material);
Copy the code

Once the sphere is painted, add the sphere to the scene.

this.scene.add(moon);
Copy the code

When it runs, it’s awkward, and the expected moon still doesn’t appear on the screen. This is because the camera hasn’t rendered the sphere into the scene yet, so the following code is executed.

this.renderer.render(this.scene, this.camera);
Copy the code

After rendering a scene with the camera, the moon appears on the screen.

Let the moon move

Use the OrbitControls class to create a controller to do this

OrbitControls( object : Camera, domElement : HTMLDOMElement )

  • Camera Camera

  • The DOM object that domElement controls is typically a renderer generated DOM object

new OrbitControls(this.camera, this.renderer.domElement);
Copy the code

With the controller, getting the moon moving also involves using a timer to allow the camera to render the moon into the scene. The timer selected here is requestAnimationFrame, which uses system time intervals to maintain optimal drawing efficiency.

loop() {
    requestAnimationFrame(this.loop);
    this.renderer.render(this.scene, this.camera);
    this.camera.lookAt(this.scene.position);
},
Copy the code

At this point you can use the mouse to control the moon rotation. How does that make the moon spin?

Let the moon spin

The three. Js base class Object3D has a property rotation to control the Angle of rotation. The Mesh class also inherits Object3D.

Rotation Is an Euler class with properties X, y, and z to control how an object rotates around the X, y, and Z axes.

Let’s move the moon around the Y-axis by adding a little code to the loop function.

Loop () {this.moon.rotation. Y += 0.01; requestAnimationFrame(this.loop); this.renderer.render(this.scene, this.camera); this.camera.lookAt(this.scene.position); },Copy the code

The last

Here is using Vue2.0 development, first to tidy up the previous code.

<template> <div id="planet"></div> </template> <script> import { Scene, WebGLRenderer, PerspectiveCamera, SphereGeometry, MeshBasicMaterial, Mesh, } from "three"; export default { data() { return { scene: null, renderer: null, camera: null, }; }, mounted() { this.scene = new Scene(); this.renderer = new WebGLRenderer(); this.renderer.setSize(innerWidth, innerHeight); document.querySelector("#planet").appendChild(this.renderer.domElement); this.camera = new PerspectiveCamera(75, innerWidth / innerHeight, 1, 1000); this.camera.position.set(0, 0, 100); this.camera.lookAt(this.scene.position); const geometry = new SphereGeometry(30, 32, 32); const material = new MeshBasicMaterial({ color: 0xe4ff03 }); this.moon = new Mesh(geometry, material); this.scene.add(moon); new OrbitControls(this.camera, this.renderer.domElement); this.loop(); }, methods:{loop() {this.moon.rotation. requestAnimationFrame(this.loop); this.renderer.render(this.scene, this.camera); this.camera.lookAt(this.scene.position); }}}; </script>Copy the code