当前位置:网站首页>Threejs loads the city obj model, loads the character gltf model, and tweetjs realizes the movement of characters according to the planned route

Threejs loads the city obj model, loads the character gltf model, and tweetjs realizes the movement of characters according to the planned route

2022-07-05 04:00:00 Zuo Ben

1, Introduce :

This example uses r95 edition Three.js library . In the last case ( The front page of the article can be found ) Add a city model (obj Format ), Add persona (gltf Format ), Initialize the movement route , It's used here Tween.js Implemented animation , The character model moves according to the route . Add axis . The renderings are as follows :

 

2, Main description

Three.js Load model file , And import geometry from it .Three.js Supported model file formats :json、obj/mtl、dae、ply、gltf、glb、svg、pbd..., All the extensions mentioned here , There are many kinds that are not listed here . If you want to load bim Model such as :ifc and rvt Format , It needs to be converted into Three Supported formats , have access to blender Software conversion , Specific course Baidu .

Add city model obj/mtl Format ,obj/mtl It is a combination of two formats , Often used together .obj File definition geometry , and mtl The file defines the material used .obj and mtl They are all text-based formats . The code is as follows :

//  Add model 
function initModel() {
	var mtlLoader = new THREE.MTLLoader();
	mtlLoader.setPath("assets/models/obj_mtl/")
	mtlLoader.load('city.mtl', function(materials) {
		materials.preload();

		var objLoader = new THREE.OBJLoader();
		objLoader.setMaterials(materials);
		objLoader.load('assets/models/obj_mtl/city.obj', function(object) {
			mesh = object;
			mesh.scale.set(3, 3, 3);
			mesh.position.set(18, 0, 18);
			scene.add(mesh);
		});
	});
}

  Add persona gltf Format , This format is dedicated to storage 3D Scenarios and models , Its advantage is that it can minimize the file size , And the model can be loaded efficiently . The code is as follows :

//  Add persona 
function initPeople() {
	var loader = new THREE.GLTFLoader();
	loader.load('assets/models/CesiumMan/CesiumMan.gltf', function(result) {
		result.scene.scale.set(1, 1, 1);
		result.scene.translateY(0);
		aaa = result.scene;
		scene.add(result.scene);

		tweenComplete();

		mixer = new THREE.AnimationMixer(result.scene);
		animationClip = result.animations[0];
		clipAction = mixer.clipAction(animationClip).play();
		animationClip = clipAction.getClip();
	});
}

Use Tween.js The animation effect , adopt Tween.js It is easy to realize the transition between two values of a certain attribute , And all intermediate values between the start value and the end value will be automatically calculated , This process is called tweening( Mend the space ).


function tweenComplete() {
	if (i < points.length) {
		switch (i) {
			case 0:
				pobj.rotateY(Math.PI);
				break;
			case 1:
			case 5:
			case 8:
			case 9:
				pobj.rotateY(-0.5 * Math.PI);
				break;
			case 2:
			case 3:
			case 4:
			case 6:
			case 7:
				pobj.rotateY(0.5 * Math.PI);
				break;
			case 10:
				mixer.stopAllAction();
				break;

		}
		tween = new TWEEN.Tween(points[i])
			.to(points[i + 1], 3000)
			.easing(TWEEN.Easing.Linear.None)
			.onUpdate(function() {
				pobj.position.set(this.x, this.y, this.z);
			})
			.onComplete(tweenComplete)
			.start();
		i++;
	}
}

 3, Source code is as follows :

<!DOCTYPE html>
<html>
	<head>
		<title>Threejs Load city obj Model , Load characters gltf Model , The character moves according to the planned route </title>
		<script type="text/javascript" src="libs/three.js"></script>
		<script type="text/javascript" src="libs/OrbitControls.js"></script>
		<script type="text/javascript" charset="UTF-8" src="libs/other/Tween.min.js"></script>
		<script type="text/javascript" charset="UTF-8" src="libs/three/loaders/GLTFLoader.js"></script>

		<script type="text/javascript" src="libs/OBJLoader.js"></script>
		<script type="text/javascript" src="libs/MTLLoader.js"></script>
		<style>
			body {
				margin: 0;
				overflow: hidden;
			}
		</style>
	</head>
	<body>
		<div id="dom"></div>
		<script type="text/javascript">
			var camera;
			var renderer;
			var clock = new THREE.Clock();
			var mixer = new THREE.AnimationMixer();
			var clipAction
			var animationClip
			var pobj

			function init() {
				//  Create a scene , It will contain all our elements , Like an object , Cameras and lights .
				var scene = new THREE.Scene();

				var urls = [
					'assets/textures/cubemap/flowers/posx.jpg',
					'assets/textures/cubemap/flowers/negx.jpg',
					'assets/textures/cubemap/flowers/posy.jpg',
					'assets/textures/cubemap/flowers/negy.jpg',
					'assets/textures/cubemap/flowers/posz.jpg',
					'assets/textures/cubemap/flowers/negz.jpg'
				];

				var cubeLoader = new THREE.CubeTextureLoader();
				scene.background = cubeLoader.load(urls);

				//  Create a camera , It defines where we are looking 
				camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 1000);
				//  Aim the camera at the center of the scene 
				camera.position.x = 20;
				camera.position.y = 15;
				camera.position.z = 35;
				camera.lookAt(scene.position);
				var orbit = new THREE.OrbitControls(camera);

				//  Create a renderer and set the size ,WebGLRenderer The computer graphics card will be used to render the scene 
				// initialize basic renderer
				renderer = new THREE.WebGLRenderer();
				renderer.setSize(window.innerWidth, window.innerHeight);

				//  Add planes to the scene 
				var plane = createPlaneGeometryBasicMaterial();
				scene.add(plane);

				//  Display the coordinate axis on the screen 
				var axes = new THREE.AxesHelper(100);
				scene.add(axes);

				// var trackballControls = initTrackballControls(camera, renderer);

				//  Add ambient light 
				scene.add(new THREE.AmbientLight(0x666666));
				scene.add(new THREE.AmbientLight("#ffffff", 1));
				//  Add the output of the renderer to HTML Elements 
				document.getElementById("dom").appendChild(renderer.domElement);

				var points = initLine();
				//  Add a sphere to the scene 

				initModel();
				initPeople();

				//  Start animation 
				renderScene();

				var i = 0;

				function tweenComplete() {
					if (i < points.length) {
						switch (i) {
							case 0:
								pobj.rotateY(Math.PI);
								break;
							case 1:
							case 5:
							case 8:
							case 9:
								pobj.rotateY(-0.5 * Math.PI);
								break;
							case 2:
							case 3:
							case 4:
							case 6:
							case 7:
								pobj.rotateY(0.5 * Math.PI);
								break;
							case 10:
								mixer.stopAllAction();
								break;

						}
						tween = new TWEEN.Tween(points[i])
							.to(points[i + 1], 3000)
							.easing(TWEEN.Easing.Linear.None)
							.onUpdate(function() {
								pobj.position.set(this.x, this.y, this.z);
							})
							.onComplete(tweenComplete)
							.start();
						i++;
					}
				}

				//  Add model 
				function initModel() {
					var mtlLoader = new THREE.MTLLoader();
					mtlLoader.setPath("assets/models/obj_mtl/")
					mtlLoader.load('city.mtl', function(materials) {
						materials.preload();

						var objLoader = new THREE.OBJLoader();
						objLoader.setMaterials(materials);
						objLoader.load('assets/models/obj_mtl/city.obj', function(object) {
							mesh = object;
							mesh.scale.set(3, 3, 3);
							mesh.position.y = -5;
							scene.add(mesh);
						});
					});
				}

				//  Add persona 
				function initPeople() {
					var loader = new THREE.GLTFLoader();
					loader.load('assets/models/CesiumMan/CesiumMan.gltf', function(result) {
						result.scene.scale.set(1, 1, 1);
						result.scene.translateY(0);
						pobj = result.scene;
						scene.add(result.scene);

						tweenComplete();

						mixer = new THREE.AnimationMixer(result.scene);
						animationClip = result.animations[0];
						clipAction = mixer.clipAction(animationClip).play();
						animationClip = clipAction.getClip();
					});
				}

				//  Create a plane 
				function createPlaneGeometryBasicMaterial() {
					var textureLoader = new THREE.TextureLoader();
					var cubeMaterial = new THREE.MeshStandardMaterial({
						map: textureLoader.load("assets/textures/stone/cd.jpg"),
					});
					cubeMaterial.map.wrapS = THREE.RepeatWrapping;
					cubeMaterial.map.wrapT = THREE.RepeatWrapping;
					cubeMaterial.map.repeat.set(18, 18)
					//  Create the ground plane and set the size 
					var planeGeometry = new THREE.PlaneGeometry(500, 500);
					var plane = new THREE.Mesh(planeGeometry, cubeMaterial);

					//  Set the plane position and rotate 
					plane.rotation.x = -0.5 * Math.PI;
					plane.position.x = 0;
					plane.position.y = -5;
					plane.position.z = 0;
					return plane;
				}

				//  Initialize the line 
				function initLine() {
					var pArr = [{
						x: 5 * 3,
						y: -3.8,
						z: -0.7 * 3
					}, {
						x: -0.6 * 3,
						y: -3.8,
						z: -0.7 * 3
					}, {
						x: -0.6 * 3,
						y: -3.8,
						z: -1.8 * 3
					}, {
						x: -4 * 3,
						y: -3.8,
						z: -1.8 * 3
					}, {
						x: -4 * 3,
						y: -3.8,
						z: 2.8 * 3
					}, {
						x: -1.2 * 3,
						y: -3.8,
						z: 2.8 * 3
					}, {
						x: -1.2 * 3,
						y: -3.8,
						z: 4.3 * 3
					}, {
						x: 1.7 * 3,
						y: -3.8,
						z: 4.3 * 3
					}, {
						x: 1.7 * 3,
						y: -3.8,
						z: -0.4 * 3
					}, {
						x: 4.4 * 3,
						y: -3.8,
						z: -0.4 * 3
					}, {
						x: 4.4 * 3,
						y: -3.8,
						z: 5 * 3
					}];
					var points = [];
					var geometry = new THREE.Geometry();
					for (var i = 0; i < pArr.length; i++) {
						var randomX = pArr[i].x;
						var randomY = pArr[i].y;
						var randomZ = pArr[i].z;
						var vector = new THREE.Vector3(randomX, randomY, randomZ);
						geometry.vertices.push(vector);
						points.push(vector);
					}
					var material = new THREE.LineBasicMaterial({
						color: 0xff0000
					});
					var line = new THREE.Line(geometry, material);
					scene.add(line);
					return points;
				}

				//  Animation rendering 
				var step = 5;

				function renderScene() {
					TWEEN.update();
					orbit.update();
					var delta = clock.getDelta();
					mixer.update(delta);
					//  Use requestAnimationFrame Function to render 
					requestAnimationFrame(renderScene);
					renderer.render(scene, camera);
				}

				//  Rendered scenes 
				renderer.render(scene, camera);


				document.addEventListener('mousedown', onDocumentMouseDown, false);

				function onDocumentMouseDown(event) {
					//  Click on the screen to create a vector 
					var vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window
						.innerHeight) * 2 + 1, 0.5);
					vector = vector.unproject(camera); //  Convert the coordinates of the screen into coordinates in the 3D scene 
					var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
					var intersects = raycaster.intersectObjects(mesh.children, true);
					console.log(intersects)
					if (intersects.length > 0) {
						// intersects[0].object.material.color.set("#ffffff");
					}
				}

				//  Create a spherical geometry 
				function createSphereGeometryLambertMaterial(point) {
					//  Create a sphere 
					var sphereGeometry = new THREE.SphereGeometry(0.2, 20, 20);
					var sphereMaterial = new THREE.MeshBasicMaterial({
						color: 0x7777ff,
						wireframe: true
					});
					var sphereMaterial = new THREE.MeshLambertMaterial({
						color: 0xff0000
					});
					var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
					//  Set the object to cast shadows 
					sphere.castShadow = true;

					//  Location range 
					sphere.position.x = point.x;
					sphere.position.y = point.y;
					sphere.position.z = point.z;
					return sphere;
				}
			}
			window.onload = init;

			function onResize() {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize(window.innerWidth, window.innerHeight);
			}
			//  Listen for resizing events 
			window.addEventListener('resize', onResize, false);
		</script>
	</body>
</html>

If you need a complete code, please leave a message or contact me on wechat :1171053128

原网站

版权声明
本文为[Zuo Ben]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202140717141203.html