This is an introductory tutorial on building a web-three-dimensional view that Webgl+threejs to create simple three-dimensional graphics using Threejs and control the movement of graphics.
First, create the scene
The views we see are created by two parts, scene and camera.
First, define a scene:
var scene = new THREE. Scene ();
Then define a camera:
var camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
And so on, define the width of the window that the camera needs. Now I want my drawing to appear in one area (<div>) tab of the page. Let's Select this element to get its long width.
var container = document.getElementById (' Canvasdiv ');
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
This, along with the preceding line of code, completes the definition of the camera. Then set the camera position on the z axis for easy observation.
Camera.position.set (0,0,10)
Now we need a renderer to render the defined scene.
var renderer = new THREE. Webglrenderer ();
Give this shader the right size.
Renderer.setsize (width, height);
It is then added to the DOM.
Canvasdiv.appendchild (renderer.domelement);
(after running, it turns out that this is actually a canvas element.) In fact, we can also create canvas elements in HTML and then bind renderer to it. var renderer = new THREE. Webglrenderer ({canvas:document.getElementById (' Maincanvas ')})
The final rendering.
Renderer.render (Scene,camera);
In this way, a simple 3d scene is established.
Second, draw graphics
I interpret the objects in the Threejs as models + materials. Take a cuboid as an example.
To create a model:
var geometry = new THREE. Boxgeometry (1,2,1);
Definition Material:
var material = new THREE. Meshbasicmaterial ({COLOR:0X645D50});
With both, we can build a cuboid box.
var cube = new THREE. Mesh (geometry, material);
We add it to the scene to display it.
Scene.add (Cube);
In this way, a three-dimensional cuboid is drawn and completed.
For other shapes, Zhang Wenli's Threejs Introductory Guide is very detailed, not much to repeat.
The complete code for this section is as follows:
<! DOCTYPE html>
<meta charset= "UTF-8" >
<title>Document</title>
<style type= "Text/css" >
#canvasdiv {
width:600px;
height:600px;
}
</style>
<script src= "Js/three.min.js" ></script>
<body>
<div id= "Canvasdiv" >
</div>
<script type= "Text/javascript" >
var container = document.getElementById (' Canvasdiv ')
var scene = new THREE. Scene ();
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
var camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
Camera.position.set (0,0,10);
var renderer = new THREE. Webglrenderer ();
Renderer.setsize (width, height);
Canvasdiv.appendchild (renderer.domelement);
var geometry = new THREE. Boxgeometry (2,1,1);
var material = new THREE. Meshbasicmaterial ({COLOR:0X645D50});
var cube = new THREE. Mesh (geometry, material);
Scene.add (Cube);
Renderer.render (Scene,camera);
</script>
</body>
It looks like it's just a rectangle, but it's really a stereo shape, and you can change the position of the camera to see.
Camera.position.set (5,3,10);
OK, so it looks like a three-dimensional cuboid.
Third, create 3d objects
Most of the time, we need to talk about drawing the graphics together to control. At this point, we need a 3d object.
Put another ball on top of the cuboid drawn above.
var geometry = new THREE. Spheregeometry (0.5,100,100);
var material = new THREE. Meshbasicmaterial ({color:0xb9c16c});
var ball = new THREE. Mesh (geometry,material);
Ball.position.set (0,0,1);
Scene.add (ball);
In other words, the default placement of mesh is (0,0,0), and change the camera position, we can use the Ball.position.set method to change the position of the graphic or object. So the animation also uses this method to implement.
Then you want to integrate them into one object.
First we create an object.
var myobj = new THREE. Object3d ();
And then add the graphic we're drawing to the object, OK.
Myobj.add (Cube);
Myobj.add (ball);
At this point we have a 3d object that contains the rectangle and the ball that we have just drawn. So there is no need to put the graphics one by one into the scene, just put the object just created into the scene.
Scene.add (myobj);
The complete code is as follows:
<! DOCTYPE html>
<meta charset= "UTF-8" >
<title>Document</title>
<style type= "Text/css" >
#canvasdiv {
width:600px;
height:600px;
}
</style>
<script src= "Js/three.min.js" ></script>
<body>
<div id= "Canvasdiv" >
</div>
<script type= "Text/javascript" >
var container = document.getElementById (' Canvasdiv ')
var scene = new THREE. Scene ();
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
var camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
Camera.position.set (0,0,10)
var renderer = new THREE. Webglrenderer ();
Renderer.setsize (width, height);
Canvasdiv.appendchild (renderer.domelement);
var geometry = new THREE. Boxgeometry (2,1,1);
var material = new THREE. Meshbasicmaterial ({COLOR:0X645D50});
var cube = new THREE. Mesh (geometry, material);
Scene.add (Cube);
var geometry = new THREE. Spheregeometry (0.5,100,100);
var material = new THREE. Meshbasicmaterial ({color:0xb9c16c});
var ball = new THREE. Mesh (geometry,material);
Ball.position.set (0,0,1);
Scene.add (ball);
var myobj = new THREE. Object3d ();
Myobj.add (Cube);
Myobj.add (ball);
Scene.add (myobj);
Renderer.render (Scene,camera);
</script>
</body>
Display effect:
Threejs supports importing. obj files from the outside, and it is said that the files are drawn in 3DsMax and can be edited with PS. We need to introduce Objmtlloader.js,mtlloader.js file, there is also a objloader.js, but the use of this library can only import models and can not import the rendering of obj added material, personal feeling is not very practical, do not introduce. At this point, we need to put the files on a server, or there will be a cross-domain problem.
To make the image more visible, we add some light.
Scene.add (New THREE. Ambientlight (0XFFFFFF));
Here, we set the texture of this object by importing a picture.
var texture = new THREE. Texture ();
var loader = new THREE. Imageloader ();
Loader.load (' tank.jpg ', function (image) {
Texture.image = image;
Texture.needsupdate = true;
} );
Start importing our 3D objects!
var loader = new THREE. Objmtlloader ();
Loader.load (' tank.obj ', ' TANK.MTL ', function (object) {
Tank = object;
Object.traverse (function (child) {
if (Child instanceof THREE. Mesh) {
Assign the texture to the material
Child.material.map = texture;
Child.material.transparent = true;
}
});
Object.position.set (0,0,0);
Scene.add (object);
Camera.lookat (object.position);
Renderer.render (Scene,camera);
});
The model has been imported, but it still looks strange, so we need to add some other light to render it. Here we add parallel light.
var directionallight = new THREE. DirectionalLight (0XFFFFFF, 1.5);
DirectionalLight.position.set (1, 1, 1);
Scene.add (DirectionalLight);
Become much more shiny.
Import the complete code for obj from the outside:
<! DOCTYPE html>
<meta charset= "UTF-8" >
<title>Document</title>
<style type= "Text/css" >
#canvasdiv {
width:1200px;
height:800px;
}
</style>
<script src= "Js/three.min.js" ></script>
<script src= "Js/mtlloader.js" ></script>
<script src= "Js/objmtlloader.js" ></script>
<body>
<div id= "Canvasdiv" >
</div>
<script type= "Text/javascript" >
var container = document.getElementById (' Canvasdiv ')
var scene = new THREE. Scene ();
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
var camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
Camera.position.set ( -10,10,10);
var renderer = new THREE. Webglrenderer ();
Renderer.setsize (width, height);
Canvasdiv.appendchild (renderer.domelement);
var texture = new THREE. Texture ();
var loader = new THREE. Imageloader ();
Loader.load (' tank.jpg ', function (image) {
Texture.image = image;
Texture.needsupdate = true;
} );
var loader = new THREE. Objmtlloader ();
Loader.load (' tank.obj ', ' TANK.MTL ', function (object) {
Tank = object;
Object.traverse (function (child) {
if (Child instanceof THREE. Mesh) {
Assign the texture to the material
Child.material.map = texture;
Focus, no such sentence will cause PNG to not display the transparency effect correctly
Child.material.transparent = true;
}
});
Object.position.set (0,0,0);
Scene.add (object);
Camera.lookat (object.position);
Renderer.render (Scene,camera);
});
Scene.add (New THREE. Ambientlight (0XFFFFFF));
var directionallight = new THREE. DirectionalLight (0XFFFFFF, 1.5);
DirectionalLight.position.set (1, 1, 1)
Scene.add (DirectionalLight);
Renderer.render (Scene,camera);
</script>
</body>
Four, animation
Now we find a way to get these graphs moving.
The most used animation in Threejs is the Requestanimationframe () method. You can also use the traditional setinterval () to do it, but use this to drop frames.
Here we do a render function to render and animate the call. This is based on the code previously added to the MyObj object.
Now to constantly change the angle of the object to facilitate the observation.
<! DOCTYPE html>
<meta charset= "UTF-8" >
<title>Document</title>
<style type= "Text/css" >
#canvasdiv {
width:600px;
height:600px;
}
</style>
<script src= "Js/three.min.js" ></script>
<body>
<div id= "Canvasdiv" >
</div>
<script type= "Text/javascript" >
var container,camera,scene,renderer,myobj;
var init = function () {
container = document.getElementById (' Canvasdiv ')
Scene = new THREE. Scene ();
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
Camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
Camera.position.set (0,0,10)
renderer = new THREE. Webglrenderer ();
Renderer.setsize (width, height);
Canvasdiv.appendchild (renderer.domelement);
var geometry = new THREE. Boxgeometry (2,1,1);
var material = new THREE. Meshbasicmaterial ({COLOR:0X645D50});
var cube = new THREE. Mesh (geometry, material);
Scene.add (Cube);
var geometry = new THREE. Spheregeometry (0.5,100,100);
var material = new THREE. Meshbasicmaterial ({color:0xb9c16c});
var ball = new THREE. Mesh (geometry,material);
Ball.position.set (0,0,1);
Scene.add (ball);
myobj = new THREE. Object3d ();
Myobj.add (Cube);
Myobj.add (ball);
Scene.add (myobj);
}
var render = function () {
Requestanimationframe (render);
myobj.rotation.x+=0.01;
myobj.rotation.y+=0.01;
Renderer.render (Scene,camera);
}
Init ()
Render ()
</script>
</body>
Then let's control the animation.
In my project, it is through the WebSocket connection background incoming parameters to control the movement of objects, here to introduce the use of parameter control bar.
The problem here is that the function of the requestanimationframe callback cannot have arguments, otherwise there will be strange bugs. So I chose to use a global object for control.
var control={
s:0,
p:0,
q:0,
j:0,
}
Here S is the velocity of motion, and the p,q,j is the x,y,z coordinate of the position where myobj will move to. Let's write a function that controls how it moves on the x axis:
var run = function () {
if (MYOBJ.POSITION.X<CONTROL.P) {
Myobj.position.x + = Control.s;
Requestanimationframe (run);
Renderer.render (Scene,camera)
};
if (MYOBJ.POSITION.X>CONTROL.P) {
Myobj.position.x-= CONTROL.S;
Requestanimationframe (run);
Renderer.render (Scene,camera)
};
}
Then add the call to run Requestanimationframe (run) in the render function. This allows you to change the value of the object control in the command line to implement the motion controlling myobj. But after the campaign stopped my browser became very card, and the speed of movement back to change. I don't know why yet. I don't know if there are any friends and I have the same problem. So I split the function into two, so the browser is performing better.
var run = function () {
if (MYOBJ.POSITION.X<CONTROL.P) {
Myobj.position.x + = Control.s;
Requestanimationframe (run);
};
Renderer.render (Scene,camera)
}
var runx = function () {
if (MYOBJ.POSITION.X>CONTROL.P) {
Myobj.position.x-= CONTROL.S;
Requestanimationframe (RUNX);
};
Renderer.render (Scene,camera)
}
Similarly, you can write a function that moves on the y,z axis.
Complete code to move on the x-axis:
<! DOCTYPE html>
<meta charset= "UTF-8" >
<title>Document</title>
<style type= "Text/css" >
#canvasdiv {
width:600px;
height:600px;
}
</style>
<script src= "Js/three.min.js" ></script>
<body>
<div id= "Canvasdiv" >
</div>
<script type= "Text/javascript" >
var container,camera,scene,renderer,myobj;
var init = function () {
container = document.getElementById (' Canvasdiv ')
Scene = new THREE. Scene ();
var width = canvasdiv.clientwidth;
var height = canvasdiv.clientheight;
Camera = new THREE. Perspectivecamera (Width/height, 0.1, 1000);
Camera.position.set (0,0,10)
renderer = new THREE. Webglrenderer ();
Renderer.setsize (width, height);
Canvasdiv.appendchild (renderer.domelement);
var geometry = new THREE. Boxgeometry (2,1,1);
var material = new THREE. Meshbasicmaterial ({COLOR:0X645D50});
var cube = new THREE. Mesh (geometry, material);
Scene.add (Cube);
var geometry = new THREE. Spheregeometry (0.5,100,100);
var material = new THREE. Meshbasicmaterial ({color:0xb9c16c});
var ball = new THREE. Mesh (geometry,material);
Ball.position.set (0,0,1);
Scene.add (ball);
myobj = new THREE. Object3d ();
Myobj.add (Cube);
Myobj.add (ball);
Scene.add (myobj);
}
var control={
s:0,
p:0,
q:0,
j:0,
}
var run = function () {
if (MYOBJ.POSITION.X<CONTROL.P) {
Myobj.position.x + = Control.s;
Requestanimationframe (run);
};
Renderer.render (Scene,camera)
}
var runx = function () {
if (MYOBJ.POSITION.X>CONTROL.P) {
Myobj.position.x-= CONTROL.S;
Requestanimationframe (RUNX);
};
Renderer.render (Scene,camera)
}
var render = function () {
Requestanimationframe (run);
Requestanimationframe (RUNX);
Renderer.render (Scene,camera);
}
Init ()
Render ()
</script>
</body>
By this point, our introductory tutorial will be over.