three.js基础之加载外部模型、纹理贴图、投射阴影、几何体颜色属性、面模型属性

初始化共用方法

<canvas id="model"></canvas>
<canvas id="texture"></canvas>
<canvas id="shadow"></canvas>
<canvas id="color"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addPlane, addBox, addSphere } from "./init.js";

  // gltf文件就是通过JSON的键值对方式来表示模型信息
  // glb就是gltf格式的二进制文件,glb文件相对gltf文件体积更小

  function init(domId, callback) {
    const width = 300;
    const height = 200;
    const renderer = initRenderer(domId, width, height);

    const scene = new THREE.Scene();

    const camera = initPerspectiveCamera({ aspect: width / height });
    scene.add(camera);

    const ambientLight = initAmbientLight();
    scene.add(ambientLight);

    const spotLight = initSpotLight();
    scene.add(spotLight);

    const axesHelper = new THREE.AxesHelper(150);
    scene.add(axesHelper);

    callback(scene);

    function animate() {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
    }
    animate();
  }
</script>

 外部模型

 init("model", (scene) => {
    // 加载模型
    const loader = new GLTFLoader();
    loader.load(
      "./models/Flower.glb",
      function (gltf) {
        console.log("gltf文件返回的对象结构", gltf);
        console.log("gltf对象场景", gltf.scene);
        gltf.scene.position.set(0, 0, 0);
        gltf.scene.scale.set(50, 50, 50);
        scene.add(gltf.scene);

        //查看模型尺寸
        const box = new THREE.Box3().setFromObject(gltf.scene);
        const size = box.getSize(new THREE.Vector3());
        console.log(size);
      },
      function (xhr) {
        const percent = xhr.loaded / xhr.total;
        console.log("加载进度" + percent);
      }
    );
  });

纹理贴图

init("texture", (scene) => {
    //纹理贴图加载器
    const texLoader = new THREE.TextureLoader();
    //纹理贴图
    texLoader.load("./images/FloorsCheckerboard_S_Diffuse.jpg", (texture) => {
      //设置为SRGB颜色空间
      texture.colorSpace = THREE.SRGBColorSpace;
      const material = new THREE.MeshBasicMaterial({
        map: texture, //材质的颜色贴图属性
        side: THREE.DoubleSide,
      });
      const geometry = new THREE.PlaneGeometry(30, 20);
      const mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
    });
  });

投射阴影

  init("shadow", (scene) => {
    const plane = addPlane({ width: 50, height: 20 });
    scene.add(plane);

    const cube = addBox({ color: 0xff0000 });
    cube.position.set(-5, 5, 0);
    scene.add(cube);

    const sphere = addSphere({ color: 0x7777ff });
    sphere.position.set(10, 5, 0);
    scene.add(sphere);
  });

几何体颜色属性


  init("color", (scene) => {
    const geometry = new THREE.BufferGeometry();
    const vertices = new Float32Array([0, 0, 0, 5, 0, 0, 0, 5, 0]);
    geometry.attributes.position = new THREE.BufferAttribute(vertices, 3);
    const colors = new Float32Array([1, 0, 0, 0, 0, 1, 0, 1, 0]);
    // 设置几何体attributes属性的颜色color属性,3个为一组,表示一个顶点的颜色数据RGB
    geometry.attributes.color = new THREE.BufferAttribute(colors, 3);
    const material = new THREE.MeshBasicMaterial({
      vertexColors: true, //默认false,设置为true表示使用顶点颜色渲染
      side: THREE.DoubleSide,
    });
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    const geometry2 = new THREE.BufferGeometry();
    const curve2 = new THREE.CatmullRomCurve3([new THREE.Vector3(-5, 2, 9), new THREE.Vector3(-1, 4, 4), new THREE.Vector3(0, 0, 0), new THREE.Vector3(6, -6, 0), new THREE.Vector3(7, 0, 8)]);
    const pointsArr2 = curve2.getSpacedPoints(100);
    geometry2.setFromPoints(pointsArr2);
    const pos = geometry2.attributes.position;
    const count = pos.count;
    // 计算每个顶点的颜色值
    const colorsArr = [];
    for (let i = 0; i < count; i++) {
      const percent = i / count;
      colorsArr.push(percent, 0, 1 - percent); //蓝色到红色渐变色
    }
    const colors2 = new Float32Array(colorsArr);
    geometry2.attributes.color = new THREE.BufferAttribute(colors2, 3);
    const material2 = new THREE.LineBasicMaterial({
      vertexColors: true, //使用顶点颜色渲染
    });
    const line = new THREE.Line(geometry2, material2);
    scene.add(line);

    const colorsArr3 = [];
    // 根据顶点距离起点远近进行颜色插值计算
    const c1 = new THREE.Color(0x00ffff); //曲线起点颜色
    const c2 = new THREE.Color(0xffff00); //曲线结束点颜色
    for (let i = 0; i < count; i++) {
      const percent = i / count;
      const c = c1.clone().lerp(c2, percent); //颜色插值计算
      colorsArr3.push(c.r, c.g, c.b);
    }
    const colors3 = new Float32Array(colorsArr3); //类型数组创建顶点颜色color数据
    const geometry3 = geometry2.clone();
    geometry3.attributes.color = new THREE.BufferAttribute(colors3, 3);
    geometry3.translate(5, 2, 1);
    const line3 = new THREE.Line(geometry3, material2);
    scene.add(line3);
  });

面模型属性

<canvas id="mesh-properties"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, addPlane, addBox } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mesh-properties");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambientLight = initAmbientLight();
  scene.add(ambientLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  const plane = addPlane();
  scene.add(plane);

  const cube = addBox({ color: 0x44ff44 });
  cube.position.set(0, 4, 0);
  scene.add(cube);

  const controls = setupControls();

  render();

  function render() {
    cube.visible = controls.visible;

    cube.rotation.x = controls.rotationX;
    cube.rotation.y = controls.rotationY;
    cube.rotation.z = controls.rotationZ;

    cube.position.x = controls.translateX;
    cube.position.y = controls.translateY;
    cube.position.z = controls.translateZ;

    cube.scale.set(controls.scaleX, controls.scaleY, controls.scaleZ);

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = new (function () {
      this.scaleX = 1;
      this.scaleY = 1;
      this.scaleZ = 1;

      this.positionX = 0;
      this.positionY = 4;
      this.positionZ = 0;

      this.rotationX = 0;
      this.rotationY = 0;
      this.rotationZ = 0;
      this.scale = 1;

      this.translateX = 0;
      this.translateY = 0;
      this.translateZ = 0;

      this.visible = true;

      this.translate = function () {
        cube.translateX(controls.translateX);
        cube.translateY(controls.translateY);
        cube.translateZ(controls.translateZ);

        controls.positionX = cube.position.x;
        controls.positionY = cube.position.y;
        controls.positionZ = cube.position.z;
      };
    })();

    const guiScale = gui.addFolder("scale");
    guiScale.add(controls, "scaleX", 0, 5);
    guiScale.add(controls, "scaleY", 0, 5);
    guiScale.add(controls, "scaleZ", 0, 5);

    const guiPosition = gui.addFolder("position");
    const contX = guiPosition.add(controls, "positionX", -10, 10);
    const contY = guiPosition.add(controls, "positionY", -4, 20);
    const contZ = guiPosition.add(controls, "positionZ", -10, 10);

    contX.listen();
    contX.onChange(function (value) {
      cube.position.x = controls.positionX;
    });

    contY.listen();
    contY.onChange(function (value) {
      cube.position.y = controls.positionY;
    });

    contZ.listen();
    contZ.onChange(function (value) {
      cube.position.z = controls.positionZ;
    });

    const guiRotation = gui.addFolder("rotation");
    guiRotation.add(controls, "rotationX", -4, 4);
    guiRotation.add(controls, "rotationY", -4, 4);
    guiRotation.add(controls, "rotationZ", -4, 4);

    const guiTranslate = gui.addFolder("translate");
    guiTranslate.add(controls, "translateX", -10, 10);
    guiTranslate.add(controls, "translateY", -10, 10);
    guiTranslate.add(controls, "translateZ", -10, 10);

    gui.add(controls, "visible");

    return controls;
  }
</script>

 

posted @ 2024-04-05 17:14  carol2014  阅读(164)  评论(0编辑  收藏  举报