首页 > 其他分享 >three.js之加载模型

three.js之加载模型

时间:2024-05-23 16:51:16浏览次数:20  
标签:function const three controls js add new scene 加载

加载各种模型

<canvas id="mainCanvas"></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 { TrackballControls } from "three/addons/controls/TrackballControls.js";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight } from "./init.js";
  import { OBJLoader } from "three/addons/loaders/OBJLoader.js";
  import { MTLLoader } from "three/addons/loaders/MTLLoader.js";
  import { ColladaLoader } from "three/addons/loaders/ColladaLoader.js";
  import { STLLoader } from "three/addons/loaders/STLLoader.js";
  import { VTKLoader } from "three/addons/loaders/VTKLoader.js";
  import { PDBLoader } from "three/addons/loaders/PDBLoader.js";
  import { PLYLoader } from "three/addons/loaders/PLYLoader.js";
  import { VRMLLoader } from "three/addons/loaders/VRMLLoader.js";
  import { TDSLoader } from "three/addons/loaders/TDSLoader.js";
  import { ThreeMFLoader } from "three/addons/loaders/3MFLoader.js";
  import { AMFLoader } from "three/addons/loaders/AMFLoader.js";
  import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
  import { GCodeLoader } from "three/addons/loaders/GCodeLoader.js";
  import { SVGLoader } from "three/addons/loaders/SVGLoader.js";

  function init() {
    const gui = new GUI();

    const renderer = initRenderer("mainCanvas");

    let scene = new THREE.Scene();

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

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

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

    let knot = createMesh(new THREE.TorusKnotGeometry(10, 1, 64, 8, 2, 3));
    scene.add(knot);

    const controls = setupControls();
    let step = 0;
    let loadedMesh;

    render();

    function render() {
      knot.rotation.y = step += 0.01;

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

    function setupControls() {
      const controls = new (function () {
        this.radius = knot.geometry.parameters.radius;
        this.tube = 0.3;
        this.radialSegments = knot.geometry.parameters.radialSegments;
        this.tubularSegments = knot.geometry.parameters.tubularSegments;
        this.p = knot.geometry.parameters.p;
        this.q = knot.geometry.parameters.q;

        this.redraw = function () {
          scene.remove(knot);
          knot = createMesh(
            new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q))
          );
          scene.add(knot);
        };

        this.saveMesh = function () {
          const result = knot.toJSON();
          sessionStorage.setItem("mesh", JSON.stringify(result));
          console.log(sessionStorage.getItem("mesh"));
        };

        this.loadMesh = function () {
          scene.remove(loadedMesh);

          const json = sessionStorage.getItem("mesh");
          if (json) {
            const loadedGeometry = JSON.parse(json);
            const loader = new THREE.ObjectLoader();
            loadedMesh = loader.parse(loadedGeometry);
            loadedMesh.position.x -= 40;
            scene.add(loadedMesh);
          }
        };

        this.exportScene = function () {
          sessionStorage.setItem("scene", JSON.stringify(scene.toJSON()));
          console.log(sessionStorage.getItem("scene"));
        };

        this.clearScene = function () {
          scene = new THREE.Scene();

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

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

        this.importScene = function () {
          const json = sessionStorage.getItem("scene");

          if (json) {
            const loadedSceneAsJson = JSON.parse(json);
            const loader = new THREE.ObjectLoader();
            scene = loader.parse(loadedSceneAsJson);
          }
        };

        this.loadFromJson = function () {
          const loader = new THREE.ObjectLoader();
          loader.load("./models/lightmap/lightmap.json", function (obj) {
            computeSize(obj);
            console.log("obj scale", obj.scale);
            computeSize(scene);

            obj.scale.set(5, 5, 5);
            scene.add(obj);
          });
        };

        this.loadFromObj = function () {
          // OBJ加载器 用于加载 .obj 资源的加载器。
          // OBJ 文件格式是一种简单的数据格式, 这种格式以人类可读的形式来表示3D几何体,即每个顶点的位置、每个纹理坐标顶点的UV位置、顶点法线、 将使每个多边形定义为顶点列表的面以及纹理顶点。
          const loader = new OBJLoader();
          loader.load("./models/tree.obj", function (obj) {
            computeSize(obj);
            console.log("obj scale", obj.scale);
            computeSize(scene);

            obj.scale.set(20, 20, 20);
            scene.add(obj);
          });
        };

        this.loadFromObjMtl = function () {
          const mtlLoader = new MTLLoader();
          mtlLoader.load("./models/walt/WaltHead.mtl", function (materials) {
            materials.preload();

            const loader = new OBJLoader();
            loader.load("./models/walt/WaltHead.obj", function (obj) {
              computeSize(obj);
              console.log("obj scale", obj.scale);
              computeSize(scene);

              obj.scale.set(0.2, 0.2, 0.2);
              scene.add(obj);
            });
          });
        };

        this.loadFromCollada = function () {
          const loader = new ColladaLoader();
          loader.load("./models/pump/pump.dae", function (res) {
            const sceneGroup = res.scene;
            sceneGroup.children.forEach(function (child) {
              if (child instanceof THREE.Mesh) {
                child.receiveShadow = true;
                child.castShadow = true;
              } else {
                sceneGroup.remove(child);
              }
            });
            sceneGroup.rotation.z = 0.5 * Math.PI;
            sceneGroup.scale.set(8, 8, 8);
            scene = sceneGroup;
          });
        };

        this.loadFromStl = function () {
          const loader = new STLLoader();
          loader.load("./models/stl/ascii/slotted_disk.stl", function (geometry) {
            const mat = new THREE.MeshStandardMaterial({
              color: 0xffffff,
              metalness: 1,
              roughness: 0.5,
            });
            const mesh = new THREE.Mesh(geometry, mat);
            mesh.rotation.x = -0.5 * Math.PI;
            mesh.scale.set(20, 20, 20);

            computeSize(mesh);
            computeSize(scene);

            scene.add(mesh);
          });
        };

        this.loadFromVtk = function () {
          const loader = new VTKLoader();
          loader.load("./models/vtk/liver.vtk", function (geometry) {
            const mat = new THREE.MeshNormalMaterial();

            geometry.center();
            geometry.computeVertexNormals();

            const mesh = new THREE.Mesh(geometry, mat);
            mesh.scale.set(0.3, 0.3, 0.3);

            computeSize(mesh);
            computeSize(scene);

            scene.add(mesh);
          });
        };

        this.loadFromPdb = function () {
          const loader = new PDBLoader();
          loader.load("./models/diamond.pdb", function (geometries) {
            const group = new THREE.Object3D();
            const geometryAtoms = geometries.geometryAtoms;

            for (let i = 0; i < geometryAtoms.attributes.position.count; i++) {
              const startPosition = new THREE.Vector3();
              startPosition.x = geometryAtoms.attributes.position.getX(i);
              startPosition.y = geometryAtoms.attributes.position.getY(i);
              startPosition.z = geometryAtoms.attributes.position.getZ(i);

              const color = new THREE.Color();
              color.r = geometryAtoms.attributes.color.getX(i);
              color.g = geometryAtoms.attributes.color.getY(i);
              color.b = geometryAtoms.attributes.color.getZ(i);

              const material = new THREE.MeshPhongMaterial({
                color: color,
              });

              const sphere = new THREE.SphereGeometry(0.2);
              const mesh = new THREE.Mesh(sphere, material);
              mesh.position.copy(startPosition);
              group.add(mesh);
            }

            const geometryBonds = geometries.geometryBonds;

            for (let j = 0; j < geometryBonds.attributes.position.count; j += 2) {
              const startPosition = new THREE.Vector3();
              startPosition.x = geometryBonds.attributes.position.getX(j);
              startPosition.y = geometryBonds.attributes.position.getY(j);
              startPosition.z = geometryBonds.attributes.position.getZ(j);

              const endPosition = new THREE.Vector3();
              endPosition.x = geometryBonds.attributes.position.getX(j + 1);
              endPosition.y = geometryBonds.attributes.position.getY(j + 1);
              endPosition.z = geometryBonds.attributes.position.getZ(j + 1);

              const path = new THREE.CatmullRomCurve3([startPosition, endPosition]);
              const tube = new THREE.TubeGeometry(path, 1, 0.04);
              const material = new THREE.MeshPhongMaterial({
                color: 0xcccccc,
              });
              const mesh = new THREE.Mesh(tube, material);
              group.add(mesh);
            }

            computeSize(scene);
            computeSize(group);
            group.scale.set(2, 2, 2);
            scene.add(group);
          });
        };

        this.loadFromPly = function () {
          const loader = new PLYLoader();
          loader.load("./models/ply/ascii/dolphins.ply", function (geometry) {
            const material = new THREE.PointsMaterial({
              color: 0xffffff,
              size: 1,
              opacity: 0.6,
              transparent: true,
              blending: THREE.AdditiveBlending,
              depthWrite: false,
              map: generateSprite(),
            });

            const group = new THREE.Points(geometry, material);
            group.scale.set(0.05, 0.05, 0.05);
            computeSize(scene);
            computeSize(group);
            scene.add(group);
          });
        };

        this.loadFromVrml = function () {
          const loader = new VRMLLoader();
          loader.load("./models/house.wrl", function (model) {
            computeSize(model);
            computeSize(scene);
            console.log("model scale", model.scale, model);
            console.log("scene", scene);
            model.scale.set(0.05, 0.05, 0.05);
            // model.scale.set(25, 25, 25);
            // scene.add(model);
            scene = model;
            // renderer.render(model, camera);
          });
        };

        this.loadFromTds = function () {
          const loader = new TDSLoader();
          loader.load("./models/3ds/portalgun/portalgun.3ds", function (group) {
            computeSize(group);
            group.scale.set(20, 20, 20);
            scene.add(group);
          });
        };

        this.loadFrom3mf = function () {
          const loader = new ThreeMFLoader();
          loader.load("./models/truck.3mf", function (group) {
            computeSize(group);
            scene.add(group);
          });
        };

        this.loadFromAmf = function () {
          const loader = new AMFLoader();
          loader.load("./models/rook.amf", function (group) {
            computeSize(group);
            group.scale.set(5, 5, 5);
            scene.add(group);
          });
        };

        this.loadFromDrc = function () {
          // DRACOLoader 一个用于加载经过Draco压缩的图形库。
          // Draco是一个开源的库,主要用于压缩和解压缩三维模型及点云。 以客户端上解压缩为代价,显著减少压缩的图形。
          // 独立的Draco文件后缀为.drc,其中包含顶点坐标,法线,颜色和其他的属性,不包含材质,纹理,动画和节点结构。
          const loader = new DRACOLoader();
          loader.setDecoderPath("./js/jsm/libs/draco/");
          loader.setDecoderConfig({ type: "js" });
          loader.preload();

          loader.load("./models/bunny.drc", function (geometry) {
            geometry.computeVertexNormals();
            geometry.computeBoundingSphere();
            geometry.computeBoundingBox();

            const mesh = new THREE.Mesh(geometry, new THREE.MeshNormalMaterial());
            computeSize(mesh);
            mesh.scale.set(100, 100, 100);
            scene.add(mesh);
          });
        };

        this.loadFromGcode = function () {
          const loader = new GCodeLoader();
          loader.load("./models/benchy.gcode", function (obj) {
            computeSize(obj);
            obj.scale.set(0.1, 0.1, 0.1);
            scene.add(obj);
          });
        };

        this.loadFromSvg = function () {
          // SVGLoader 用于加载.svg资源的加载器
          // 可伸缩向量图形是XML形式的矢量图形格式,用来描述二维矢量图形并支持交互和动画。
          const loader = new SVGLoader();

          loader.load("./models/tiger.svg", function (data) {
            const paths = data.paths;
            const group = new THREE.Group();
            group.scale.multiplyScalar(0.1);
            group.scale.y *= -1;
            for (let i = 0; i < paths.length; i++) {
              const path = paths[i];
              const material = new THREE.MeshBasicMaterial({
                color: path.color,
                side: THREE.DoubleSide,
                depthWrite: false,
              });
              const shapes = path.toShapes(true);
              for (let j = 0; j < shapes.length; j++) {
                const shape = shapes[j];
                const geometry = new THREE.ShapeGeometry(shape);
                const mesh = new THREE.Mesh(geometry, material);
                group.add(mesh);
              }
            }

            computeSize(group);
            scene.add(group);
          });
        };
      })();

      const ioGui = gui.addFolder("Save & Load");
      ioGui.add(controls, "exportScene");
      ioGui.add(controls, "clearScene");
      ioGui.add(controls, "importScene");
      ioGui.add(controls, "saveMesh").onChange(controls.saveMesh);
      ioGui.add(controls, "loadMesh").onChange(controls.loadMesh);
      ioGui.add(controls, "loadFromJson").onChange(controls.loadFromJson);
      ioGui.add(controls, "loadFromObj").onChange(controls.loadFromObj);
      ioGui.add(controls, "loadFromObjMtl").onChange(controls.loadFromObjMtl);
      ioGui.add(controls, "loadFromCollada").onChange(controls.loadFromCollada);
      ioGui.add(controls, "loadFromStl").onChange(controls.loadFromStl);
      ioGui.add(controls, "loadFromVtk").onChange(controls.loadFromVtk);
      ioGui.add(controls, "loadFromPdb").onChange(controls.loadFromPdb);
      ioGui.add(controls, "loadFromPly").onChange(controls.loadFromPly);
      ioGui.add(controls, "loadFromVrml").onChange(controls.loadFromVrml);
      ioGui.add(controls, "loadFromTds").onChange(controls.loadFromTds);
      ioGui.add(controls, "loadFrom3mf").onChange(controls.loadFrom3mf);
      ioGui.add(controls, "loadFromAmf").onChange(controls.loadFromAmf);
      ioGui.add(controls, "loadFromDrc").onChange(controls.loadFromDrc);
      ioGui.add(controls, "loadFromGcode").onChange(controls.loadFromGcode);
      ioGui.add(controls, "loadFromSvg").onChange(controls.loadFromSvg);

      const meshGui = gui.addFolder("mesh");
      meshGui.add(controls, "radius", 0, 40).onChange(controls.redraw);
      meshGui.add(controls, "tube", 0, 40).onChange(controls.redraw);
      meshGui.add(controls, "radialSegments", 1, 400).step(1).onChange(controls.redraw);
      meshGui.add(controls, "tubularSegments", 1, 20).step(1).onChange(controls.redraw);
      meshGui.add(controls, "p", 1, 10).step(1).onChange(controls.redraw);
      meshGui.add(controls, "q", 1, 15).step(1).onChange(controls.redraw);

      return controls;
    }
  }

  init();

  function createMesh(geom) {
    const meshMaterial = new THREE.MeshBasicMaterial({
      vertexColors: false,
      wireframe: true,
      wireframeLinewidth: 2,
      color: 0xaaaaaa,
    });
    meshMaterial.side = THREE.DoubleSide;

    const mesh = new THREE.Mesh(geom, meshMaterial);
    mesh.position.set(20, 0, 0);
    return mesh;
  }

  function computeSize(obj) {
    const cbox = new THREE.Box3().setFromObject(obj);
    const size = cbox.getSize(new THREE.Vector3());

    if (obj instanceof THREE.Scene) {
      console.log("scene size", size);
    } else {
      console.log("obj size", size);
    }
  }

  function generateSprite() {
    const canvas = document.createElement("canvas");
    canvas.width = 16;
    canvas.height = 16;
    const context = canvas.getContext("2d");

    const gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
    gradient.addColorStop(0, "rgba(255,255,255,1)");
    gradient.addColorStop(0.2, "rgba(0,255,255,1)");
    gradient.addColorStop(0.4, "rgba(0,0,64,1)");
    gradient.addColorStop(1, "rgba(0,0,0,1)");
    context.fillStyle = gradient;
    context.fillRect(0, 0, canvas.width, canvas.height);

    const texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;
    return texture;
  }
</script>

 

标签:function,const,three,controls,js,add,new,scene,加载
From: https://www.cnblogs.com/caroline2016/p/18208927

相关文章

  • three.js之Group
    Group<canvasid="mainCanvas"></canvas><scripttype="importmap">{"imports":{"three":"./js/build/three.module.js","three/addons/":"./js/jsm/"......
  • NodeJS-高性能编程-全-
    NodeJS高性能编程(全)原文:zh.annas-archive.org/md5/DF276329F6BD35B176ABE023A386AF47译者:飞龙协议:CCBY-NC-SA4.0前言在像Node.js这样的平台上实现高性能意味着要了解如何充分利用硬件的各个方面,并帮助内存管理发挥最佳作用,并正确决定如何设计复杂的应用程序。如果您的......
  • nodejs + express + mysql + redis 基础功能实现
    nodejs+express+mysql+redis基础功能实现yeyue  9人赞同了该文章本文大体介绍了nodejs项目的创建、express框架的使用、mysql数据库的连接、以及redis的数据交互等方法,并举例了些简单的例子进行说明,代码都是亲自重头跑了一遍的,拿来可用。 一、......
  • Meteor-JS-框架入门指南-全-
    MeteorJS框架入门指南(全)原文:zh.annas-archive.org/md5/A6A998711E02B953FECB90E097CD1168译者:飞龙协议:CCBY-NC-SA4.0序言我们生活在一个惊人的时代。医学、通信、物理以及所有其他科学领域的进步为我们提供了创建一些在短短一段时间前简直是无法创造的事物的机会。然......
  • IDocList/IDocDict JSON for Delphi and FPC
    IDocList/IDocDictJSONforDelphiandFPC【英文原文】多年来,我们的开源mORMot框架提供了多种方式,以处理在运行时定义的任何数组/对象文档组合,例如通过JSON,它具备许多功能,并且非常高的性能。我们的TDocVariant自定义变体类型是处理这类无模式数据的一种强大方式,但一些用户......
  • FullCalendar插件js原生用法
    1.先看下要实现的效果图,左侧栏为当日时间,顶部为部门所有人员,表格内容是人员事件,要求数据多的时候,左侧栏和顶部固定,支持横竖滚动条,如图:  2.这里用的js原生写法:<html><head><title>工作记录详情</title><metaname="decorator"content="default"/><s......
  • JSP九大内置对象详解
    *JSP九大内置对象详解*JSP内置对象(9个内置对象):1.PageContextjavax.servlet.jsp.PageContextJSP的页面容器2.requestjavax.servlet.http.HttpServletrequest获取用户的请求信息3.responsejavax.servlet.http.HttpServletResponse服务器向客户端的回应信息4.sessionj......
  • JSP九大内置对象
    JSP九大内置对象JSP提供了由容器实现和管理的内置对象,也可以称之为隐含对象,由于JSP使用Java作为脚本语言,所以JSP将具有强大的对象处理能力,并且可以动态创建Web页面内容。但Java语法在使用一个对象前,需要先实例化这个对象,这其实是一件比较烦琐的事情。JSP为了简化开发,提供了一些内......
  • Nodejs Playwright 2Captcha 验证码识别实现自动登陆
    NodejsPlaywright2Captcha验证码识别实现自动登陆需求日常工作当中,为了提高工作效率,我们可能会写脚本来自动执行任务。有些网站因为需要用户登陆,所以脚本的自动登陆功能必不可少。不过我们在登陆网站的时候经常会出现验证码,验证码的目的就是为了防止机器登陆、自动化脚本操......
  • uniapp中使用mqtt.js的踩坑记录
    最近在uniapp的vue3.0版本中使用mqtt.js库时遇到了一些坑,经过亲身踩坑,现在把实际能够实现在uniapp的app端能够使用mqtt.js的方法步骤记录如下:一、安装首先安装mqtt.js,建议使用较为稳定的3.0.0版本:[email protected]二、引入mqtt.jsimportmqttfrom'mqtt/dist/mqtt.......