乐趣区

关于html:threeblenderreact实现一些简单功能|大帅老猿threejs特训

前言

📃前几天加入了原宇宙我的项目的学习,奈何是 blender 老手,工作工夫不能学习,只能忙里偷闲,先先做一个记录,我的项目用到的和没用到的文件都在 src 目录下的 resources 文件夹外面。想着做不同的,那么就用框架不一样吧,利用 vite 搭建的 react 我的项目,下载 threeJs 安装包书写。

筹备工作

1,工具

应用的是 blender

  • 因为 blender 对于 mac 和 windows 都是能够应用的,3dMax 只实用于 windows 零碎(不过因为我之前学过 3dMax 的,所以,尽管我是 mac,然而也装置了一个 windows 的虚拟机,3dMax 跑起来还是能够应用的。)

2,网址

  • blender 下载地址:https://www.blender.org/thanks/
  • 下载贴图或者材质的:https://www.textures.com/library
  • 一些根本模型:https://sketchfab.com/ (在 sketchfab 上能够拿模型,实现模型的小局部自在)(qq 邮箱,google 邮箱能够,163 邮箱注册如同不行)
  • 用于模型绑定骨骼:https://www.mixamo.com/(无动画的角色,演示的时候用的 glb 不反对,没提醒。用 fbx 格局的能够)

    3,blender 中的一些快捷键

    在 blender 中应用的的右手坐标系

性能 快捷键
全选: A 勾销全选: AA 复制物体: Shift+D
挪动: G 缩放: S 挪动视角: 鼠标滚轮键
旋转: R 搜寻: F3 删除: X
填充面: F 合并顶点: M 编辑模式: Tab
前视图: 1 右视图: 3 顶视图: 7
切换视图: Alt+ 鼠标中键 透视显示模式: Alt+Z 拆散: P
属性栏: N 左侧工具栏: T 环选: Alt+A
反选: Ctrl+I 暗藏物体: H 勾销暗藏: Alt+H
查看全副: Shift+C 父子链接: Ctrl+P 相机视图: 0
着色模式: Z 弹出上次的渲染窗口: F11 创立汇合: M
设置游标: Shift+S 最大化以后窗口: Ctrl+ 空格 物体交互模式设置: Ctrl+Tab
进入 / 退出三视图: Ctrl+Alt+Q 挤出: F9 游标回到原点: Shift+C
开启 / 敞开吸附性能: Shift+Tab 抉择相连元素: L 一般复制: Shift+D
去除父子关系: Alt+P 创立父子关系: Ctrl+P 挪动物体: M
连贯节点: F 断开节点: Ctrl+ 鼠标左键 增加转换点: Shift+ 鼠标左键
暂停 / 播放: Alt+A 上一帧 / 下一帧: 左右箭头 删除关键帧: Alt+I
切换点线面: Ctrl+Tab 撕开后填充: Alt+V 倒角工具: Ctrl+B
切割工具: K 挤出工具: E 细分物体: 按住 S + 鼠标中键
渲染: F12 保留用户设置: Ctrl+U

有些快捷键我没有试过,能够本人入手尝试做一下

4,代码实现时可能遇到的几个坑

  • 动画为什么不动,
    须要在动画中设置帧的播放程序
  • 为什么依照操作,整个画面是黑的,
    因为相机在外部,须要将相机的地位进行设置
  • 为什么底部的材质是黑的,
    能够用一个环境光,将四周的亮度调亮

    5,代码

    1,应用 vite 搭建我的项目

    这里抉择的是 react 版本

    npm create vite@latest

    2, 下载 three.js 安装包

    下载后查看文档对应下载的版本进行查看,因为不同的版本相应的文件可能存在的文件夹不一样,这里我用的是 0.145.0

    npm install three@0.145.0 

    3, 具体代码

  • 1,引入相干文件

    import {useState, useEffect, useRef} from 'react'
    import * as THREE from 'three';
    // 引入 three.js 其余扩大库,对应版本查看文档,最新扩大库在 addons 文件夹下,eg:'three/addons/controls/OrbitControls.js';
    // OrbitControls 控件反对鼠标左中右键操作和键盘方向键操作
    import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
    import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
    import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader';
  • 2, 设置盒子宽高

     function App() {const [width, setWidth] = useState(window.innerWidth)
    const [height, setHeight] = useState(window.innerHeight)
    return (<div id="container" style={{ width: width, height: height}}></div>
    )
    }
    
    export default App
  • 3,若窗口扭转,则对窗口进行重置

    const resizeUpdate = (e) => {
      // 通过事件对象获取浏览器窗口的高度
      let h = e.target.innerHeight;
      let w = e.target.innerWidth;
      // 对利用大小进行重置
      renderer.setSize(w, h);
      setHeight(h);
      setWidth(w)
    };
    // 重置窗口大小
    useEffect(() => {
      // 页面刚加载实现后获取浏览器窗口的大小
      let h = window.innerHeight;
      setHeight(h)
      let w = window.innerWidth;
      setWidth(w)
      // 页面变动时获取浏览器窗口的大小 
      window.addEventListener('resize', resizeUpdate);
      return () => {
        // 组件销毁时移除监听事件
        window.removeEventListener('resize', resizeUpdate);
      }
    }, [])
  • 4, 对相应的变量进行命名

    let scene, camera, renderer, controls // 场景,相机,渲染器,控制器
    let donuts; // 前面甜甜圈旋转时的变量
    let mixer; // 甜甜圈播放动画是的变量
  • 5,初始化 / 销毁 利用

    useEffect(() => {
      // 创立场景
      scene = new THREE.Scene();
      // // 创立相机
      camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10);
      renderer = new THREE.WebGLRenderer({antialias: true});
      renderer.setSize(width, height); // 设置渲染器尺寸
      document.getElementById('container').appendChild(renderer.domElement);
    
      camera.position.set(0.3, 0.3, 0.5); // 设置相机地位
    
      controls = new OrbitControls(camera, renderer.domElement);
      const directionLight = new THREE.DirectionalLight(0xffffff, 0.4); // 增加平行光
      scene.add(directionLight);
    
      gltfLoader() // 场景增加 glb 文件
      rgbeLoader() // 增加背景天空
      animate() // 动画循环
    
      // 组件销毁时移除 app 利用
      return () => {document.getElementById('container').removeChild(renderer.domElement);
      }
    }, [])
  • 6,三个分离出来的办法

    // 场景增加 glb 文件
    const gltfLoader = () => {new GLTFLoader().load('../src/resources/models/donuts.glb', (gltf) => {scene.add(gltf.scene);
        donuts = gltf.scene;
    
        mixer = new THREE.AnimationMixer(gltf.scene);
        const clips = gltf.animations; // 播放所有动画
        clips.forEach((clip) => {const action = mixer.clipAction(clip);
          action.loop = THREE.LoopOnce;
          // 停在最初一帧
          action.clampWhenFinished = true;
          action.play();});
      })
    }
    // 增加背景天空
    const rgbeLoader = () => {new RGBELoader()
        .load('../src/resources/sky2.hdr', function (texture) {
          scene.background = texture;
          texture.mapping = THREE.EquirectangularReflectionMapping;
          scene.environment = texture;
          renderer.outputEncoding = THREE.sRGBEncoding;
          renderer.render(scene, camera);
        });
    }
    // 动画循环
    const animate = () => {requestAnimationFrame(animate);
      renderer.render(scene, camera);
      controls.update();
      if (donuts) {donuts.rotation.y += 0.01;}
      if (mixer) {mixer.update(0.02);
      }
    }

    6,代码地址

    代码在以后 github 地址,点击可进入查看

    7,总结

    不论做什么还是要保持,保持才会迎来胜利。
    如果你有趣味的话,也能够 退出猿创营 (v:dashuailaoyuan),一起交流学习

退出移动版