目标:
写一个3D铁塔,随意切换角度观察
背景:
vue3+ts,使用贴图的方式
准备工作:
创建一个文件夹,我这里是叫tbTieta,里面创建一个文件夹(mx2)和一个文件(index.vue)
在你的文件夹mx2中复制粘贴进你的scene.bin文件和scene.gltf文件(scene.bin和scene.gilt文件均来自于此文件)
同时在public中也引入
OK,准备工作咱们已经做好了
代码:
在tbtieta中的index.vue 中写代码:
<template>
<div class="about">
<div id="container"></div>
</div>
</template>
<script lang="ts" setup>
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { ref, shallowRef, onMounted } from 'vue';
let logosrc = ref('')
let objContainer = shallowRef(); // 箱子
let objScence = shallowRef(); // 场景
let objCamera = shallowRef(); // 相机(透视相机)
let objRenderer = shallowRef(); // 渲染器
let objLight = shallowRef(); // 光源
let objPointLight = shallowRef(); // 点光源
let objpxLight = shallowRef(); // 平行光
let objGeometry = shallowRef(); // 物体
let objMaterial = shallowRef(); // 纹理
let objCube = shallowRef(); // 物体对象
let objGeometry2 = shallowRef(); // 物体
let objMaterial2 = shallowRef(); // 纹理
let objCube2 = shallowRef(); // 物体对象
let objZb = shallowRef(); // 坐标轴
let objControl = shallowRef(); // 控制器
const props = defineProps({
x: {
type: String,
default: ''
},
y: {
type: String,
default: ''
},
z: {
type: String,
default: ''
}
});
console.log(props.x, props.y, props.z, 555666);
onMounted(() => {
objContainer.value = document.getElementById("container");
funInit();
})
const funInit = () => {
// nextTick(() => {
objScence.value = new THREE.Scene(); // 场景
objCamera.value = new THREE.PerspectiveCamera(75, objContainer.value.clientWidth / objContainer.value.clientHeight, 0.1, 1000); // 相机(透视相机)
objCamera.value.position.z = 5;
objCamera.value.position.y = 0.5;
objRenderer.value = new THREE.WebGLRenderer({ antialias: true }); // 渲染器
objRenderer.value.setSize(objContainer.value.clientWidth, objContainer.value.clientHeight);
objRenderer.value.setClearColor("#222222", 0);
objContainer.value.appendChild(objRenderer.value.domElement);
objZb.value = new THREE.AxesHelper(160); // 坐标轴
// objScence.value.add(objZb.value);
objGeometry.value = new THREE.BoxGeometry(1, 1, 1); // 物体\纹理\物体对象
objMaterial.value = new THREE.MeshStandardMaterial({
color: 0xff0051,
flatShading: true,
metalness: 0,
roughness: 1,
});
objCube.value = new THREE.Mesh(objGeometry.value, objMaterial.value);
objLight.value = new THREE.AmbientLight(0xffffff, 0.2); // 环境光源
objScence.value.add(objLight.value);
objPointLight.value = new THREE.PointLight(0xffffff, 2); // 点光源
objPointLight.value.position.set(1, 0, 1);
objScence.value.add(objPointLight.value);
objpxLight.value = new THREE.DirectionalLight(0xffffff, 1);
objpxLight.value.position.set(80, 100, 50);
objpxLight.value.target = objCube.value;
objScence.value.add(objpxLight.value);
objControl.value = new OrbitControls(objCamera.value, objRenderer.value.domElement);
// 创建GLTF加载器对象
const gltfloaderA = new GLTFLoader();
// 创建插入模型
const modelA = new THREE.Group();
//加载模型文件,返回gltf对象
gltfloaderA.load(
'./mx2/scene.gltf',
// 添加模型
function (gltf: any) {
gltf.scene.scale.set(0.05, 0.05, 0.05);
modelA.add(gltf.scene);
objScence.value.add(modelA);
// 设置中心点的颜色
const centerPointGeometry = new THREE.SphereGeometry(0.05); // 创建一个小球体代表中心点
const centerPointMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 }); // 设置中心点颜色
const centerPoint = new THREE.Mesh(centerPointGeometry, centerPointMaterial);
// 将中心点放置在铁塔模型的中心
centerPoint.position.copy(modelA.position);
// 添加中心点到场景
objScence.value.add(centerPoint);
},
// // 加载模型进度
// function (xhr) {
// console.log(`已加载:${(xhr.loaded / xhr.total) * 100}%`);
// },
// // 回调函数
// function (error) {
// console.log(error, "错误显示");
// }
)
// 底座部分
// 创建底座
const baseGeometry = new THREE.CircleGeometry(1, 50);
const baseMaterial = new THREE.MeshBasicMaterial({
color: 0x654321,
side: THREE.DoubleSide
});
const baseMesh = new THREE.Mesh(baseGeometry, baseMaterial);
baseMesh.rotation.x = -Math.PI / 2.0;
baseMesh.position.set(0, 0, 0);
objScence.value.add(baseMesh);
// resize 事件
// window.addEventListener("resize", () => {
// let width = window.innerWidth;
// let height = window.innerHeight;
// renderer.setSize(width, height);
// camera.aspect = width / height;
// camera.updateProjectionMatrix();
// });
funAnimate();
// })
}
const funAnimate = () => {
requestAnimationFrame(funAnimate);
objCube.value.rotation.x = objCube.value.rotation.x + 0.04;
objCube.value.rotation.y = objCube.value.rotation.y + 0.04;
// objCube2.value.rotation.x = objCube2.value.rotation.x - 0.01;
// objCube2.value.rotation.y = objCube2.value.rotation.y - 0.01;
objRenderer.value.render(objScence.value, objCamera.value);
// objControl.value.update();
}
</script>
<style lang="less" scoped>
.about {
display: flex;
align-items: center;
justify-content: center;
#container {
width: 100%;
height: 700px;
overflow: hidden;
}
}
</style>
这个运行出来是这样的: