| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- import { ref } from "vue";
- import {
- Scene,
- PerspectiveCamera,
- Clock,
- WebGLRenderer,
- AmbientLight,
- Color,
- PlaneGeometry,
- Mesh,
- HemisphereLight,
- Group,
- Raycaster,
- Vector2,
- // PointLight,
- // PointLightHelper,
- // FogExp2,
- // Vector2,
- } from "three";
- import { OrbitControls } from "three/addons/controls/OrbitControls.js";
- // import Stats from "three/addons/libs/stats.module.js";
- import { getImg } from "@/utils";
- import { Reflector } from "three/examples/jsm/objects/Reflector.js";
- import { getBottomMaterial } from "./material";
- import { modelGroup, initModels } from "./models";
- import { lineGroup, lineLabelGroup, initBuildGirdLines } from "./lines";
- import { vfxGroup } from "./vfx";
- import { CSS3DRenderer } from "three/examples/jsm/renderers/CSS3DRenderer.js";
- import { Easing, Tween, update } from "@tweenjs/tween.js";
- // import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
- // import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass.js";
- // import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
- // import { OutputPass } from "three/examples/jsm/postprocessing/OutputPass.js";
- export function useScene({ modelClick }: { modelClick: (model: any) => void }) {
- //@ts-ignore
- let stats: any, clock: any, controls: any;
- let camera: any,
- scene: any,
- renderer: any,
- mixer: any,
- verticalMirror: any,
- geometry: any,
- css3Renderer: any;
- // bloomComposer: any,
- // finalComposer: any;
- const containerRef = ref<HTMLElement | null>(null);
- const raycaster = new Raycaster();
- const mouse = new Vector2();
- // const params = {
- // threshold: 0,
- // strength: 1,
- // radius: 0.5,
- // exposure: 1,
- // };
- function init() {
- // console.log([containerRef.value], containerRef.value!.clientWidth,containerRef.value!.clientHeight);
- camera = new PerspectiveCamera(
- 25,
- containerRef.value!.clientWidth / containerRef.value!.clientHeight,
- 1,
- 1000
- );
- camera.position.set(
- 18.416546632171155,
- 12.90089079540779,
- -16.681357401983476
- );
- scene = new Scene();
- // @ts-ignore
- window.scene = scene;
- // scene.background = new Color(0xefd1b5);
- clock = new Clock();
- const group = new Group();
- group.name = "智慧能源";
- //雾-指数
- // scene.fog = new FogExp2(0xcccccc, 0.002);
- //加载模型
- initModels();
- //线
- initBuildGirdLines();
- group.add(modelGroup, lineGroup, lineLabelGroup, vfxGroup);
- scene.add(group);
- //环境光
- const ambientLight = new AmbientLight(0xffffff, 0.6);
- scene.add(ambientLight);
- //半球光
- const directionalLight = new HemisphereLight(0xffffff, 0x080820, 1);
- directionalLight.position.set(0, 1000, 0);
- scene.add(directionalLight);
- //底部平面
- geometry = new PlaneGeometry(1, 1);
- // 创建材质,可以设置贴图
- let material = getBottomMaterial(
- "#ffffff", // 设置模型的颜色
- getImg("models/bg.png"),
- 1,
- 5
- );
- // 创建平面网格
- let plane = new Mesh(geometry, material);
- plane.scale.set(192, 108, 108);
- plane.position.y = 0.01;
- plane.rotateX(-Math.PI / 2);
- let plane2 = plane.clone();
- plane2.material = getBottomMaterial(
- "#ffffff", // 设置模型的颜色
- getImg("models/bg.png"),
- 2,
- 5
- );
- scene.add(plane2);
- scene.add(plane);
- //镜面
- verticalMirror = new Reflector(geometry, {
- clipBias: 0.003,
- textureWidth:
- containerRef.value!.clientWidth * window.devicePixelRatio * 0.5,
- textureHeight:
- containerRef.value!.clientHeight * window.devicePixelRatio * 0.5,
- color: new Color("#326973"),
- });
- verticalMirror.scale.set(100, 100, 100);
- verticalMirror.position.y = 0;
- verticalMirror.position.z = 0;
- verticalMirror.rotateX(-Math.PI / 2);
- scene.add(verticalMirror);
- //渲染器
- renderer = new WebGLRenderer({ antialias: true });
- renderer.setPixelRatio(window.devicePixelRatio);
- renderer.setSize(
- containerRef.value!.clientWidth,
- containerRef.value!.clientHeight
- );
- containerRef.value!.appendChild(renderer.domElement);
- //控制器
- controls = new OrbitControls(camera, renderer.domElement);
- controls.screenSpacePanning = false;
- controls.maxPolarAngle = Math.PI / 2.1;
- controls.minDistance = 5;
- controls.maxDistance = 40;
- setControlsVeiw(
- {
- x: -4.92927755506738,
- y: 1.9591040557652486e-19,
- z: -3.0835424654787844,
- },
- {
- x: 21.791887493897622,
- y: 15.919334531990208,
- z: -21.407410138122152,
- }
- );
- // controls.target.set(-4.7582917376881415, 0, -2.9423607740176285);
- // controls.update();
- // const renderScene = new RenderPass(scene, camera);
- // const bloomPass = new UnrealBloomPass(
- // new Vector2(window.innerWidth, window.innerHeight),
- // 1.5,
- // 0.4,
- // 0.85
- // );
- // bloomPass.threshold = params.threshold;
- // bloomPass.strength = params.strength;
- // bloomPass.radius = params.radius;
- // bloomComposer = new EffectComposer(renderer);
- // bloomComposer.renderToScreen = false;
- // bloomComposer.addPass(renderScene);
- // bloomComposer.addPass(bloomPass);
- // const outputPass = new OutputPass();
- // finalComposer = new EffectComposer(renderer);
- // finalComposer.addPass(renderScene);
- // finalComposer.addPass(outputPass);
- // @ts-ignore
- // window.camera = camera;
- // // @ts-ignore
- // window.controls = controls;
- window.getCamera = () => {
- return [controls.target, controls.object.position];
- };
- //性能监控
- // stats = new Stats();
- // stats.dom.style.position = "absolute";
- // stats.dom.style.top = "10%";
- // stats.dom.style.left = "25%";
- // containerRef.value!.appendChild(stats.dom);
- // 创建一个CSS3渲染器CSS3DRenderer
- css3Renderer = new CSS3DRenderer();
- css3Renderer.setSize(
- containerRef.value!.clientWidth,
- containerRef.value!.clientHeight
- );
- // HTML标签<div id="tag"></div>外面父元素叠加到canvas画布上且重合
- css3Renderer.domElement.style.position = "absolute";
- css3Renderer.domElement.style.top = "0px";
- //设置.pointerEvents=none,解决HTML元素标签对threejs canvas画布鼠标事件的遮挡
- css3Renderer.domElement.style.pointerEvents = "none";
- css3Renderer.domElement.style.className = "css3Renderer";
- containerRef.value!.appendChild(css3Renderer.domElement);
- //监听窗口变化
- window.addEventListener("resize", onWindowResize);
- window.addEventListener("click", onMouseClick);
- }
- function onMouseClick(event: any) {
- // calculate mouse position in normalized device coordinates
- // (-1 to +1) for both components
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
- // 通过鼠标点的位置和当前相机的矩阵计算出raycaster
- raycaster.setFromCamera(mouse, camera);
- // 获取raycaster直线和所有模型相交的数组集合
- let intersects = raycaster.intersectObjects(modelGroup.children);
- // console.log(intersects);
- //将所有的相交的模型的颜色设置为红色
- // for (let i = 0; i < intersects.length; i++) {
- // //@ts-ignore
- // intersects[i].object.material.color.set(0xff0000);
- // }
- if (intersects.length > 0) modelClick(intersects[0].object);
- }
- function flyTo(target: any) {
- new Tween(controls.object.position)
- .to(target.position, target.time || 500) // Move to (300, 200) in 1 second.
- .easing(Easing.Quadratic.InOut) // Use an easing function to make the animation smooth.
- .onUpdate(() => {})
- .start(); // Start the tween immediately.;
- new Tween(controls.target)
- .to(target.targetContent, target.time || 500) // Move to (300, 200) in 1 second.
- .easing(Easing.Quadratic.InOut) // Use an easing function to make the animation smooth.
- .onUpdate(() => {})
- .start(); // Start the tween immediately.;;
- }
- function onWindowResize() {
- camera.aspect =
- containerRef.value!.clientWidth / containerRef.value!.clientHeight;
- camera.updateProjectionMatrix();
- css3Renderer.setSize(
- containerRef.value!.clientWidth,
- containerRef.value!.clientHeight
- );
- renderer.setSize(
- containerRef.value!.clientWidth,
- containerRef.value!.clientHeight
- );
- verticalMirror
- .getRenderTarget()
- .setSize(
- containerRef.value!.clientWidth * window.devicePixelRatio,
- containerRef.value!.clientHeight * window.devicePixelRatio
- );
- }
- function animate() {
- update();
- controls.update();
- requestAnimationFrame(animate);
- render();
- // stats.update();
- }
- function render() {
- const delta = clock.getDelta();
- if (mixer !== undefined) {
- mixer.update(delta);
- }
- // bloomComposer.render();
- // finalComposer.render();
- css3Renderer.render(scene, camera);
- renderer.render(scene, camera);
- }
- function setControlsVeiw(targetContent: any, position: any) {
- flyTo({ targetContent, position });
- // controls.target.set(targetContent.x, targetContent.y, targetContent.z);
- // controls.object.position.set(position.x, position.y, position.z);
- // controls.update();
- }
- return {
- containerRef,
- init,
- animate,
- setControlsVeiw,
- };
- }
|