Vue.js import three.js, the screen is displayed, but the model and any errors do not appear

I want to inquire about vue.js import three.js. My family contains three.js. The screen is displayed, but the model and any errors do not appear. I don’t know why.

<template>
  <div id="scene-container">
    <header class="title-wrapper move-ctrl">
      <h1 class="title">Psychedelic</h1>
      <h1 class="title">paint</h1>
    </header>
    <div class="subitle move-ctrl">
      <h1 class="title">rhinoceros</h1>
    </div>
    <div class="rhinoceros-info move-ctrl">
      <ul class="info-title">
        <li>Artist: Henri-Alfred Jacquemart</li>
        <li>Period: 1878</li>
        <li>Material: Plaster</li>
        <li>Location: Dépôt des sculptures de la Ville de Paris</li>
      </ul>
    </div>
    <footer class="footer-wrapper move-ctrl">
      <div class="title">reflection out</div>
    </footer>
    <div class="footer-subitle move-ctrl">
      <h1 class="footrt-title footrt-title-size">2020</h1>
      <div class="footer-info">
        <h2>25-28 working</h2>
        <h2>Psychedelic + rhinoceros</h2>
      </div>
    </div>
    <div class="footer-cop move-ctrl">
      <h3>3d model design</h3>
      <h3>#Psychedelic-r2020</h3>
    </div>
  </div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { MTLLoader } from "three/examples/jsm/loaders/MTLLoader";
import * as Stats from "stats-js";
import { GUI } from "dat.gui";

export default {
  name: "three",
  data() {
    return {
      container: null,
      camera: null,
      renderer: null,
      controls: null,
      scene: null,
      mesh: null,
      stats: null
    };
  },
  methods: {
    init() {
      this.container = this.$el;

      this.scene = new THREE.Scene();

      // Background Color背景顏色
      this.scene.background = new THREE.Color(0x000000, 0);

      // function 函數整理
      this.createCamera();
      this.createControls();
      this.createLight();
      this.meangerProgress();
      this.loader();
      this.createRenderer();
      this.onWindowResize();
      this.createGui();
      this.regenerate();
    },

    // Create a Camera 建立相機
    createCamera() {
      this.camera = new THREE.PerspectiveCamera(
        75, //FOV
        window.innerWidth / window.innerHeight, //aspect
        0.1, //near
        1500 //far
      );
      this.camera.position.set(0, 0, 1000); // x,y,z
    },

    // Create a Controls 建立控制器
    createControls() {
      this.controls = new OrbitControls(this.camera, this.container);
      this.controls.enableDamping = true;
      this.controls.campingFactor = 0.25;
      this.controls.enableZoom = true;
    },

    // Create a Lights 建立光源組
    createLight() {
      this.ambient = new THREE.AmbientLight(0xffffff);

      this.keyLight = new THREE.DirectionalLight(
        new THREE.Color("hsl(313, 100%, 83%)"),
        3
      );
      this.keyLight.position.set(-100, 0, 200);

      this.fillLight = new THREE.DirectionalLight(
        new THREE.Color("hsl(181, 54%, 76%)"),
        1
      );
      this.fillLight.position.set(100, 100, -500);

      this.backLight = new THREE.DirectionalLight(0xffffff, 3.0);
      this.backLight.position.set(100, 150, -150).normalize();

      this.light1 = new THREE.PointLight(0xa2e2e3, 300, 1000);
      this.light1.position.set(100, 230, 200);

      this.light2 = new THREE.PointLight(0xa2e2e3, 200, 1000);
      this.light2.position.set(100, -100, -300);

      this.light3 = new THREE.PointLight(0xffffff, 100, 1000);
      this.light3.position.set(-60, -100, 50);

      this.light4 = new THREE.PointLight(0xfca4d3, 400, 1000);
      this.light4.position.set(0, 180, 50);

      this.light5 = new THREE.PointLight(0xa2e2e3, 400, 1000);
      this.light5.position.set(250, 200, -150);

      this.light6 = new THREE.PointLight(0xa2e2e3, 800, 1000);
      this.light6.position.set(-200, 250, -350);

      this.scene.add(
        this.ambient,
        this.light1,
        this.light2,
        this.light3,
        this.light4,
        this.light5,
        this.light6
      );

      // pointLightHelper 輔助
      this.sphereSize = 50;

      this.pointLightHelper = new THREE.PointLightHelper(
        this.light1,
        this.sphereSize
      );
      this.pointLightHelper2 = new THREE.PointLightHelper(
        this.light2,
        this.sphereSize
      );
      this.pointLightHelper3 = new THREE.PointLightHelper(
        this.light3,
        this.sphereSize
      );
      this.pointLightHelper4 = new THREE.PointLightHelper(
        this.light4,
        this.sphereSize
      );
      this.pointLightHelper5 = new THREE.PointLightHelper(
        this.light5,
        this.sphereSize
      );
      this.pointLightHelper6 = new THREE.PointLightHelper(
        this.light6,
        this.sphereSize
      );

      this.scene.add(
        this.pointLightHelper,
        this.pointLightHelper2,
        this.pointLightHelper3,
        this.pointLightHelper4,
        this.pointLightHelper5,
        this.pointLightHelper6
      );
    },
    meangerProgress() {
      this.onProgress = function(xhr) {
        if (xhr.lengthComputable) {
          this.percentComplete = (xhr.loaded / xhr.total) * 100;
          console.log(Math.round(this.percentComplete, 2) + "% downloaded");
        }
      };

      this.onError = function() {};

      this.manager = new THREE.LoadingManager();
    },

    loader() {
      this.mtlLoader = new MTLLoader(this.manager);
      this.mtlLoader.setResourcePath("../../public/models");
      this.mtlLoader.setPath("../../public/models");
      this.mtlLoader.load("rhinoceros-Psychedelic.mtl", function(materials) {
        this.materials.preload();

        this.objLoader = new OBJLoader(this.manager);
        this.objLoader.setMaterials(materials);
        this.objLoader.setPath("../../public/models");
        this.objLoader.load(
          "rhinoceros-Psychedelic.obj",
          function(object) {
            this.mesh = object;
            this.scene.add(this.mesh);
          },
          this.onProgress,
          this.onError
        );
      });
    },

    // Creat the Renderer 建立渲染器
    createRenderer() {
      this.renderer = new THREE.WebGLRenderer({ alpha: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);

      this.renderer.setPixelRatio(window.devicePixelRatio);

      this.renderer.gammaFactor = 2.2;
      // this.renderer.gammaOutput = true;

      this.renderer.physicallyCorrectLights = true;

      this.container.appendChild(this.renderer.domElement);

      this.stats = new Stats();
      this.container.appendChild(this.stats.dom);
    },

    // animate 動畫執行
    animate() {
      requestAnimationFrame(this.animate);

      this.render();
      this.stats.update();
    },

    // render 渲染
    render() {
      // 物體旋轉 model rotation
      if (this.mesh) {
        this.mesh.rotation.y += this.Data.speed;
      }
      this.renderer.render(this.scene, this.camera);
      window.addEventListener("resize", this.onWindowResize);
    },
    // RWD 螢幕偵測
    onWindowResize() {
      // console.log( '你調整瀏覽器大小了' );

      this.camera.aspect = window.innerWidth / window.innerHeight;

      // update the camera's frustum 相機錐角
      this.camera.updateProjectionMatrix();

      // update the size of the renderer AND the canvas
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    createGui() {
      // GUI Display
      this.gui = new GUI();

      // GUI Data 參數
      this.Data = {
        color: "#ffffff",
        speed: -0.01
      };

      this.Folder = this.gui.addFolder("Rhinoceros");

      // GUI Light
      this.Folder.addColor(this.Data, "color")
        .onChange(this.regenerate)
        .name("Color");
      this.Folder.add(this.Data, "speed", -0.01, -0.05).name("Speed");

      this.Folder.open();
    },
    regenerate() {
      this.keyLight = new THREE.DirectionalLight(this.Data.color, 1);
      this.scene.add(this.keyLight);
    }
  },
  mouted() {
    this.init();
    this.animate();
    this.loader();
  }
};
</script>

<style lang="scss" scoped>
#scene-container {
  box-sizing: border-box;
  position: relative;
  width: 100%;
  height: 100%;
  .title {
    font-size: 60px;
    color: #fff;
    font-family: "Bungee Outline", cursive;
  }
  .info-title {
    font-size: 20px;
    color: #fff;
  }
  .footrt-title-size {
    font-size: 90px;
    color: #fff;
    font-family: "Bungee Outline", cursive;
    letter-spacing: 20px;
  }
  .move-ctrl {
    position: absolute;
  }
  .title-wrapper {
    display: flex;
    justify-content: space-between;
    width: 97%;
    margin: 110px 25px;
    border-top: 1px solid #fff;
    border-bottom: 1px solid #fff;
  }
  .subitle {
    display: flex;
    justify-content: flex-end;
    width: 97%;
    margin: 110px 25px;
    top: 60px;
    border-bottom: 1px solid #fff;
    letter-spacing: 30px;
  }
  .rhinoceros-info {
    margin: 110px 25px;
    top: 150px;
    ul {
      li {
        margin-bottom: 1rem;
      }
    }
  }
  .footer-wrapper {
    display: flex;
    justify-content: flex-end;
    margin: 0 25px;
    bottom: 200px;
    width: 97%;
    border-top: 1px solid #fff;
    border-bottom: 1px solid #fff;
    letter-spacing: 10px;
  }
  .footer-subitle {
    margin: 0 25px;
    bottom: 110px;
    width: 97%;
    border-bottom: 1px solid #fff;
    display: flex;
    .footrt-title {
      display: flex;
      position: relative;
      &:after {
        content: "";
        position: absolute;
        top: 15px;
        left: 350px;
        width: 1px;
        height: 60px;
        background-color: #fff;
      }
    }
    .footer-info {
      display: flex;
      flex-direction: column;
      justify-content: center;
      font-size: 40px;
      color: #fff;
      margin-left: 50px;
      letter-spacing: 10px;
    }
  }
  .footer-cop {
    display: flex;
    justify-content: space-between;
    margin: 0 25px;
    bottom: 50px;
    width: 97%;
    font-size: 40px;
    color: #fff;
  }
}
</style>

There’s a typo, which could cause the whole thing not to work.

The function call mouted() should be mounted()

Change that and see how you get on :slight_smile:

Also, you call this.loader() in mounted, but you also call it inside of the init() function. Maybe remove the one from mounted, the double call could give you other issues.

Duplication of - https://stackoverflow.com/questions/60934977/vue-js-import-three-js-the-screen-is-displayed-but-the-model-and-any-errors-do

1 Like

Haha, thank you for reminding me, but I do n’t seem to know the material here :sweat_smile:

I think you’re getting mixed up with scoping there. It should be materials.preload() not this.materials.preload()

1 Like

thanks u, but console a warning appears
Cannot set property ‘objLoader’ of undefined

I can’t be sure, but I still think you’re running into scoping problems.

Try and declare this line this.objLoader = new OBJLoader(this.manager); outside the function it currently is in (above this.mtlLoader.load(...)

I would suggest making sure the OBJLoader is included correctly, referencing the example source code and debugging each part as you go - https://github.com/mrdoob/three.js/blob/7c1424c5819ab622a346dd630ee4e6431388021e/examples/webgl_loader_obj_mtl.html

1 Like

thank u , My problem has been solved :slightly_smiling_face:
path +/

can i see final code? now I have same problem.