<template>
<!-- vue3 -->
<view class="">
<view id="threeView">456</view>
<view class="">
22222
</view>
</view>
</template>
<script module="three" lang="renderjs" setup>
import * as THREE from 'three'
//引入轨道控制器(用来通过鼠标事件控制模型旋转、缩放、移动)
import {
OrbitControls
} from '../../static/threeTwo/examples/jsm/controls/OrbitControls.js'
import {
GLTFLoader
} from '../../static/threeTwo/examples/jsm/loaders/GLTFLoader.js'
import {
FBXLoader
} from '../../static/threeTwo/examples/jsm/loaders/FBXLoader.js'
import {
computed,
onMounted,
ref,
watch
} from 'vue'
// 如果模型没有显示出来, 可能是cameraZ的值不够, 请注意
let scene = '',
camera = '',
renderer = '',
cube = '',
sphere = '',
step = '',
stats = '',
group = '',
cameraZ = 500,
url = '../../static/texst.glb',
width = 800,
height = 560,
orbitcontrols = '';
const init = () => {
console.log(cameraZ, 'cameraZ');
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
camera.position.set(0, 0, cameraZ);
renderer = new THREE.WebGLRenderer({
antialias: true
});
renderer.setClearColor(0xffffff, 0);
renderer.setSize(width / 1.2, height / 1.2);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMapEnabled = true;
document.getElementById("threeView").appendChild(renderer.domElement);
orbitcontrols = new OrbitControls(camera, renderer.domElement); //移动控件
orbitcontrols.enabled = true;
orbitcontrols.enableRotate = true;
orbitcontrols.enableZoom = false;
orbitcontrols.autoRotate = true;
orbitcontrols.minPolarAngle = Math.PI / 4;
orbitcontrols.maxPolarAngle = 3 - (Math.PI / 4);
console.log('78', url.endsWith('gltf'), url.endsWith('glb'))
console.log(url)
if (url.endsWith('gltf') || url.endsWith('glb')) {
//设置了六个平行光 有些材质不接受环境光会很暗
const directionLight1 = new THREE.DirectionalLight(0xffffff, 1);
directionLight1.position.set(-300, 0, 0)
scene.add(directionLight1);
const directionLight2 = new THREE.DirectionalLight(0xffffff, 1);
directionLight2.position.set(300, 0, 0)
scene.add(directionLight2);
const directionLight3 = new THREE.DirectionalLight(0xffffff, 1);
directionLight3.position.set(0, 300, 0)
scene.add(directionLight3);
const directionLight4 = new THREE.DirectionalLight(0xffffff, 1);
directionLight4.position.set(0, 300, 0)
scene.add(directionLight4);
const directionLight5 = new THREE.DirectionalLight(0xffffff, 1);
directionLight5.position.set(0, 0, -300)
scene.add(directionLight5);
const directionLight6 = new THREE.DirectionalLight(0xffffff, 1);
directionLight6.position.set(0, 0, 300)
scene.add(directionLight6);
}
let Sun = new THREE.DirectionalLight(0xffffff, 1);
Sun.position.set(0, 300, 0);
Sun.castShadow = true;
let Ambient = new THREE.AmbientLight(0xffffff, 1);
scene.add(Ambient);
scene.add(Sun);
}
const loadModel = () => {
let loader1 = new GLTFLoader();
let FBXloader = new FBXLoader();
let rotateObj = [];
const loadLoader = url.endsWith('fbx') ? FBXloader : loader1;
loadLoader.load(url, function(gltf) {
const loadscene = gltf.scene || gltf;
loadscene.scale.set(1, 1, 1);
let group = new THREE.Group();
group.add(loadscene);
let bbox = new THREE.Box3().setFromObject(group);
// console.log(bbox,'bbox---');
let mdlen = bbox.max.x - bbox.min.x; //边界的最小坐标值 边界的最大坐标值
let mdhei = bbox.max.y - bbox.min.y;
let mdwid = bbox.max.z - bbox.min.z;
group.position.set(0, 0, 0);
// console.log(camera,'相机的信息',group,'组的信息');
let dist = Math.abs(camera.position.z - group.position.z - (mdwid / 2));
//console.log('dist值为:' + dist );
let vFov = camera.fov * Math.PI / 180; //弧度=角度*Math.PI/180
//console.log('vFov值为:' + vFov );
let vheight = 2 * Math.tan(vFov * 0.5) * dist;
//console.log('vheight值为:' + vheight );
let fraction = mdhei / vheight;
// console.log('fraction值为:' + fraction );
let finalHeight = height * fraction;
//console.log('finalHeight值为:' + finalHeight);
let finalWidth = (finalHeight * mdlen) / mdhei;
//console.log('finalWidth值为:' + finalWidth );
let value1 = width / finalWidth;
// console.log('value1缩放比例值为:' + value1);
let value2 = height / finalHeight;
// console.log('value2缩放比例值为:' + value2);
if (value1 >= value2) {
group.scale.set(value2, value2, value2);
} else {
group.scale.set(value1 / 2, value1 / 2, value1 / 2);
// group.scale.set(value1,value1,value1);
}
let bbox2 = new THREE.Box3().setFromObject(group)
// console.log(bbox2,'bbox2');
let mdlen2 = bbox2.max.x - bbox2.min.x;
let mdhei2 = bbox2.max.y - bbox2.min.y;
let mdwid2 = bbox2.max.z - bbox2.min.z;
group.position.set(-(bbox2.max.x + bbox2.min.x) / 2,
-(bbox2.max.y + bbox2.min.y) / 2,
-(bbox2.max.z + bbox2.min.z) / 2);
document.getElementById("threeView").click(); //去掉加载效果
scene.add(group);
// let boxhelper = new THREE.BoxHelper(group,0xbe1915); //辅助线外面红色框
// scene.add(boxhelper);
})
}
const animate = () => {
requestAnimationFrame(animate);
orbitcontrols.update(); //自动旋转
renderer.render(scene, camera);
}
setTimeout(() => {
init();
animate();
loadModel();
}, 100)
</script>
<template>
<!-- vue2 -->
<div id="threeView" ref="threeView" class="threeView" :prop="opt" :change:prop="three.updatethree"
style="width:100%; height:500rpx"></div>
</template>
<script>
export default {
props: {
},
data() {
return {
loading:false,
opt:{}
}
},
methods: {
start(url,mtl) {
this.loading = true
this.opt = {
url,
mtl,
}
},
}
}
</script>
<script module="three" lang="renderjs">
// const THREE = require('static/threeTwo/build/three.min.js')//vue2
import * as THREE from 'three' //vue3
import {
OrbitControls
} from '@/static/threeTwo/examples/jsm/controls/OrbitControls.js'
import {
GLTFLoader
} from '@/static/threeTwo/examples/jsm/loaders/GLTFLoader.js'
import {
RGBELoader
} from '@/static/threeTwo/examples/jsm/loaders/RGBELoader.js';
import {
OBJLoader
} from '@/static/threeTwo/examples/jsm/loaders/OBJLoader.js'
import {
MTLLoader
} from '@/static/threeTwo/examples/jsm/loaders/MTLLoader.js'
// const ThreeBSP = require('static/three/build/ThreeBSP.js')(THREE)
var renderer;
var scene, GLTFloader;
var camera;
var controls;
let pmremGenerator, envMap;
let renderEnabled = false;
let timeOut = null;
export default {
mounted() {
// this.initThree();
},
methods: {
updatethree(val) {
if (val) {
this.initThree(val)
}
},
initThree({url,mtl}) {
let that = this
/* 创建场景对象Scene */
scene = new THREE.Scene();
/*
相机设置
*/
const element = document.getElementById('threeView')
// const width = window.innerWidth; // 窗口宽度
// const height = window.innerHeight; // 高度
const width = element.clientWidth; // 窗口宽度
const height = element.clientHeight; // 窗口高度
console.log(width, 'width');
console.log(height, 'height');
// const width = 100; // 窗口宽度
// const height = 100; // 窗口高度
camera = new THREE.PerspectiveCamera(20, width / height, 0.1, 1000);
camera.position.set(0, 30, 100);
scene.add(camera);
/*
创建渲染器对象
*/
renderer = new THREE.WebGLRenderer({
antialias: true,
alpha: true
});
console.log(window.innerWidth, window.innerHeight,'window.innerWidth, window.innerHeight')
renderer.physicallyCorrectLights = true;
renderer.outputEncoding = THREE.sRGBEncoding;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(element.clientWidth, element.clientHeight);
pmremGenerator = new THREE.PMREMGenerator(renderer);
pmremGenerator.compileEquirectangularShader();
console.log(renderer.domElement, 'renderer.domElement')
element.appendChild(renderer.domElement); // body元素中插入canvas对象
/*
光源设置
*/
// 半球光
const hemiLight = new THREE.HemisphereLight();
hemiLight.intensity = 0.3
scene.add(hemiLight);
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 1);
scene.add(ambientLight);
//平行光
const light = new THREE.DirectionalLight(0xffffff, 0.3);
light.position.set(-10, -1, 100);
scene.add(light);
/*
控制器
*/
controls = new OrbitControls(camera, renderer.domElement);
controls.enablePan = false; //滑动
controls.enableDamping = true;
controls.dampingFactor = 0.05;
controls.screenSpacePanning = false;
controls.autoRotate = true; //场景自动旋转
controls.autoRotateSpeed = 4; //旋转的速度
// controls.minDistance = 60;
// controls.maxDistance = 100;
// controls.maxPolarAngle = Math.PI /2;//2.8 1.8 Math.PI / 1
// controls.minPolarAngle = Math.PI /2;//相同的角度禁止垂直旋转
controls.addEventListener('change', function() {
that.timeRender();
});
//设置鼠标,触摸的操作方式
// controls.mouseButtons = {
// LEFT: THREE.MOUSE.PAN,
// MIDDLE: THREE.MOUSE.DOLLY,
// RIGHT: THREE.MOUSE.ROTATE
// }
// controls.touches = {
// ONE: THREE.TOUCH.PAN,
// TWO: THREE.TOUCH.DOLLY_ROTATE
// }
/*
环境纹理
*/
// new RGBELoader()
// .setDataType( THREE.UnsignedByteType )
// .load( 'http://qiniu.3fwallet.com/venice_sunset_1k.hdr', ( texture ) => {
// envMap = pmremGenerator.fromEquirectangular( texture ).texture;
// pmremGenerator.dispose();
// scene.environment = envMap;
// // scene.background = envMap;
// }, );
that.animate();
const objLoader = new OBJLoader()
let MTLLoader1 = new MTLLoader()
// let obj = 'static/3mode/LUZI1.obj'
// let mtl = 'static/3mode/LUZI1.mtl'
MTLLoader1.load(mtl, (object) => {
object.preload();
objLoader.setMaterials(object)
objLoader.load(url, (root) => {
const model1 = root;
console.log(model1, 'model1')
model1.position.set(0, 0, 0);
// model1.name = 'model1';
scene.add(model1);
that.timeRender();
})
}, null, (error) => {
});
renderer.render(scene, camera);
},
animate() {
if (renderEnabled) {
controls.update();
this.render();
}
requestAnimationFrame(() => {
this.animate()
});
},
// 动画
render() {
renderer.render(scene, camera); //执行渲染操作
},
/*
渲染判断
在没有动画的情况下,可以在有需要的时候渲染,提高性能
*/
timeRender() {
//设置为可渲染状态
renderEnabled = true;
//清除上次的延迟器
if (timeOut) {
clearTimeout(timeOut);
}
//开启动画时需要一直渲染,不能暂停渲染操作
// timeOut = setTimeout(function () {
// renderEnabled = false;
// }, 3000);
},
}
}
</script>
<style>
.content {
margin: 0;
overflow: hidden;
}
.three {
width: 100%;
}
#threeView {
width: 100%;
}
</style>