After multiple clicks, stop turning, the model will disappear, what's the matter?

Problem recurrence 23s The problem arises。 https://playground.babylonjs.com/#609BJS#2

import {
  Engine,
  Texture,
  Tools,
  StandardMaterial,
  ShadowDepthWrapper,
  CubicEase,
  EasingFunction,
  CubeTexture,
  Light,
  FreeCamera,
  Scene,
  PBRMetallicRoughnessMaterial,
  SceneLoader,
  Color4,
  ShadowGenerator,
  AssetsManager,
  Color3,
  ArcRotateCamera,
  Vector3,
  DirectionalLight,
  HemisphericLight,
  Mesh,
  Animation,
  DefaultLoadingScreen,
} from "@babylonjs/core";
import "@babylonjs/materials";
import "@babylonjs/loaders";
import { AdvancedDynamicTexture, Button } from "@babylonjs/gui";
import { runScene } from "./scenes/scene";
import { ShadowOnlyMaterial } from "@babylonjs/materials";
let qs = require("querystring");

type Data = {
  [key: string]: any;
};
export class Game {
  public engine: Engine;

  public scene: Scene;

  public materialList: string[];

  public camera: ArcRotateCamera;

  public light: DirectionalLight;

  public light2: HemisphericLight;

  public shadowGenerator: ShadowGenerator;

  public constructor() {
    this.engine = new Engine(
      document.getElementById("renderCanvas") as HTMLCanvasElement,
      true,
      { preserveDrawingBuffer: true, stencil: true }
    );
    this.createLoading();
    console.log("开始loading");
    this.engine.displayLoadingUI();
    this.scene = new Scene(this.engine);
    var color = Color3.FromHexString("#dadee1");
    this.scene.clearColor = Color4.FromColor3(color, 1);
    this.scene.environmentIntensity = 1;
    // this.scene.fogMode = Scene.FOGMODE_EXP;
    // this.scene.fogDensity = 0.002;
    this._init();
    this._bindEvents();
    this.effect();
    // this._load();
  }
  // 副作用
  private effect(): void {
    // this.scene.onBeforeRenderObservable.add(() => {});
    this.scene.registerBeforeRender(() => {
      if (this.scene.isReady() && this.isReadyAll()) {
        setTimeout(() => {
          this.engine.hideLoadingUI();
        }, 1000);
      } else {
        this.engine.displayLoadingUI();
      }
    });
  }
  // 创建相机
  private createCamera(): void {
    this.camera = new ArcRotateCamera(
      "camera",
      0,
      0,
      0,
      new Vector3(0, 0, 0),
      this.scene
    );
    this.camera.position = new Vector3(1, 500, 300);
    // Y轴的限制
    // this.camera.lowerBetaLimit = 0.95;
    // Y轴的限制
    // this.camera.upperBetaLimit = 1.45;
    this.camera.upperRadiusLimit = 600;
    //回弹效果
    this.camera.useBouncingBehavior = true;
    // camera.upperRadiusLimit = 30;
    // 相机与目标的距离
    this.camera.radius = 600;
    // 相机超过目标局部坐标中心点的高度

    this.camera.useFramingBehavior = true;
    //缩放速度
    // this.camera.pinchPrecision = 2;

    //将相机与画布关联;
    // camera.attachControl(canvas, true);
    this.scene.activeCamera = this.camera;
    this.camera.useAutoRotationBehavior = true;

    this.camera.autoRotationBehavior.idleRotationSpeed = 1; //自动旋转速度
    this.camera.autoRotationBehavior.idleRotationWaitTime = 1000; //用户交互后多少时间开启自动旋转(毫秒)
    this.camera.autoRotationBehavior.idleRotationSpinupTime = 0; //从开始自动旋转到设置的旋转速度所需要的时间(毫秒)
    this.camera.autoRotationBehavior.zoomStopsAnimation = true; //设置缩放是否会停止自动旋转
    this.camera.attachControl(
      document.getElementById("renderCanvas") as HTMLCanvasElement,
      true
    );
  }
  private createSkyBox(): void {
    var skybox = Mesh.CreateBox("skyBox", 800.0, this.scene);
    var skyboxMaterial = new StandardMaterial("skyBox", this.scene);
    skyboxMaterial.backFaceCulling = false;
    var skyURL = "https://www.babylonjs-playground.com/textures/skybox2";
    skyboxMaterial.reflectionTexture = new CubeTexture(skyURL, this.scene);
    skyboxMaterial.reflectionTexture.coordinatesMode = Texture.SKYBOX_MODE;
    skyboxMaterial.diffuseColor = new Color3(0, 0, 0);
    skyboxMaterial.specularColor = new Color3(0, 0, 0);
    skyboxMaterial.disableLighting = true;
    skybox.material = skyboxMaterial;
  }
  // 创建灯光
  private createLight(): void {
    // this.light = new DirectionalLight(
    //   "dir01",
    //   new Vector3(0, 500, 0),
    //   this.scene
    // );
    // this.light.position = new Vector3(0, 1, 0);
    // this.light.intensity = 1;
    // // this.light.shadowMaxZ = 3000;
    // // this.light.shadowMinZ = 100;
    // this.light.lightmapMode = Light.LIGHTMAP_DEFAULT;
    // // this.light.range = 500;

    this.light2 = new HemisphericLight(
      "HemiLight",
      new Vector3(1, 1, 0),
      this.scene
    );

    // var light2 = new HemisphericLight("h", new Vector3(0, 800, 0), this.scene);
    //灯光强度
    this.light2.intensity = 0.95;
    // light2.range = 0.6
  }
  // 创建阴影
  private createShadow(): void {
    //  this.shadowGenerator = new ShadowGenerator(4096, this.light);
    //  this.shadowGenerator.bias = 0.001;
    //  this.shadowGenerator.normalBias = 0.02;
    //  this.shadowGenerator.useContactHardeningShadow = true;
    //  this.shadowGenerator.contactHardeningLightSizeUVRatio = 0.05;
    //  this.shadowGenerator.useExponentialShadowMap = true;
    //  this.shadowGenerator.usePoissonSampling = true;
    //  this.shadowGenerator.setDarkness(0.1);
    this.shadowGenerator = new ShadowGenerator(512, this.light);
    this.shadowGenerator.useBlurExponentialShadowMap = true;
    this.shadowGenerator.blurScale = 4;
    this.shadowGenerator.blurBoxOffset = 8;

    this.shadowGenerator.enableSoftTransparentShadow = true;
    this.shadowGenerator.setDarkness(0.25);
    //泊松采样
    // this.shadowGenerator.usePoissonSampling = true
    // 内模糊
    this.shadowGenerator.blurKernel = 1; // 默认1 1是外模糊
    // this.shadowGenerator.usePercentageCloserFiltering = true
  }
  private downloadFile(fileName, content) {
    let aLink = document.createElement("a");
    let blob = this.base64ToBlob(content); //new Blob([content]);

    let evt = document.createEvent("HTMLEvents");
    evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错  事件类型,是否冒泡,是否阻止浏览器的默认行为
    aLink.download = fileName;
    aLink.href = URL.createObjectURL(blob);

    // aLink.dispatchEvent(evt);
    aLink.click();
  }
  //base64转blob
  private base64ToBlob(code) {
    let parts = code.split(";base64,");
    let contentType = parts[0].split(":")[1];
    let raw = window.atob(parts[1]);
    let rawLength = raw.length;

    let uInt8Array = new Uint8Array(rawLength);

    for (let i = 0; i < rawLength; ++i) {
      uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
  }
  private screenShot(): void {
    var gui = AdvancedDynamicTexture.CreateFullscreenUI("UI");
    var btnScreenshot = Button.CreateSimpleButton("but1", "截图");
    console.log(btnScreenshot);
    btnScreenshot.top = "0px";
    btnScreenshot.background = "red";
    btnScreenshot.width = "150px";
    btnScreenshot.height = "60px";
    btnScreenshot.color = "white";
    btnScreenshot.fontSize = "30px";
    btnScreenshot.verticalAlignment = 1;
    btnScreenshot.horizontalAlignment = 1;
    btnScreenshot.onPointerUpObservable.add(() => {
      Tools.CreateScreenshotUsingRenderTarget(
        this.engine,
        this.camera,
        {
          width: 240,
          height: 400,
          precision: 5.5,
        },
        (data) => {
          this.downloadFile(String(new Date().getTime()) + ".png", data);

          console.log(data);
        }
      );
    });
    gui.addControl(btnScreenshot);
  }
  // 创建地面
  private createGround(): void {
    // var ground = Mesh.CreateGround("ground", 8000, 8000, 10, this.scene);
    // (ground.position = new Vector3(0, -2, 0)), (ground.checkCollisions = true);
    // ground.receiveShadows = true;

    var ground = Mesh.CreatePlane("ground", 1000, this.scene);
    ground.rotation.x = Math.PI / 2;
    ground.material = new ShadowOnlyMaterial("mat", this.scene);
    ground.receiveShadows = true;
    ground.position.y = -100;
    ground.material.shadowDepthWrapper = new ShadowDepthWrapper(
      ground.material,
      this.scene
    );
  }
  private createScreenshotBtn(): void {}
  //创建摄像头动画
  private cameraAnimation(): void {
    var frameRate = 20;

    var movein = new Animation(
      "movein",
      "position",
      frameRate,
      Animation.ANIMATIONTYPE_VECTOR3,
      Animation.ANIMATIONLOOPMODE_CONSTANT
    );

    var movein_keys = [];

    // movein_keys.push({
    //   frame: 0,
    //   value: new Vector3(1, 500, -300),
    // });

    // movein_keys.push({
    //   frame: 3 * frameRate,
    //   value: new Vector3(6000, 8000, 0),
    // });

    // movein_keys.push({
    //   frame: 5 * frameRate,
    //   value: new Vector3(6000, 8000, 0),
    // });
    // movein_keys.push({
    //   frame: 8 * frameRate,
    //   value: new Vector3(6000, 8000, 0),
    // });
    // movein.setKeys(movein_keys);

    this.scene.beginDirectAnimation(
      this.camera,
      [movein],
      25,
      100 * frameRate,
      false,
      4,
      () => {
        // this.animateCameraTargetToPosition(this.camera, 45, 200, new Vector3(0, 0, 0));
        // this.animateCameraToPosition(this.camera, 45, 200, new  Vector3(-45, 55, -45));
        this.camera.useAutoRotationBehavior = true;

        this.camera.autoRotationBehavior.idleRotationSpeed = 1; //自动旋转速度
        // camera.autoRotationBehavior.idleRotationWaitTime = 1000; //用户交互后多少时间开启自动旋转(毫秒)
        this.camera.autoRotationBehavior.idleRotationSpinupTime = 0; //从开始自动旋转到设置的旋转速度所需要的时间(毫秒)
        this.camera.autoRotationBehavior.zoomStopsAnimation = true; //设置缩放是否会停止自动旋转
        this.camera.attachControl(
          document.getElementById("renderCanvas") as HTMLCanvasElement,
          true
        );
      }
    );
  }
  animateCameraTargetToPosition(cam, speed, frameCount, newPos): void {
    var ease = new CubicEase();
    ease.setEasingMode(EasingFunction.EASINGMODE_EASEINOUT);
    Animation.CreateAndStartAnimation(
      "at5",
      cam,
      "target",
      speed,
      frameCount,
      cam.target,
      newPos,
      0,
      ease
    );
  }

  animateCameraToPosition(cam, speed, frameCount, newPos): void {
    var ease = new CubicEase();
    ease.setEasingMode(EasingFunction.EASINGMODE_EASEINOUT);
    Animation.CreateAndStartAnimation(
      "at4",
      cam,
      "position",
      speed,
      frameCount,
      cam.position,
      newPos,
      0,
      ease
    );
  }

  get(url) {
    return new Promise((resolve, reject) => {
      let xhr = new XMLHttpRequest();
      xhr.open("get", url, true);
      xhr.onload = function () {
        if (xhr.status == 200) {
          resolve(JSON.parse(xhr.responseText));
        } else {
          reject(null);
        }
      };
      xhr.onerror = function () {
        reject(null);
      };
      xhr.send(null);
    });
  }
  createLoading() {
    DefaultLoadingScreen.prototype.displayLoadingUI = function () {
      if (document.getElementById("customLoadingScreenDiv")) {
        // document.getElementById("customLoadingScreenDiv").style.display =
        //   "flex";
        // Do not add a loading screen if there is already one
        return;
      }

      this._loadingDiv = document.createElement("div");
      this._loadingDiv.id = "customLoadingScreenDiv";
      this._loadingDiv.innerHTML =
        "<img src='https://cms-oss-sh-dev.oss-cn-shanghai.aliyuncs.com/jpc/2021-03-10/Loadingsome.gif' />";
      var customLoadingScreenCss = document.createElement("style");
      customLoadingScreenCss.type = "text/css";
      customLoadingScreenCss.innerHTML = `
      #customLoadingScreenDiv{
          background-color: #FFFFFFcc;
          color: white;
          font-size:50px;
          text-align:center;
          justify-content: center;
          display: flex;
          align-items: center;
      }
      `;
      document
        .getElementsByTagName("head")[0]
        .appendChild(customLoadingScreenCss);
      this._resizeLoadingUI();
      window.addEventListener("resize", this._resizeLoadingUI);
      document.body.appendChild(this._loadingDiv);
    };
    DefaultLoadingScreen.prototype.hideLoadingUI = function () {
      document.getElementById("customLoadingScreenDiv").style.display = "none";
      console.log("scene is now loaded");
    };
  }
  customLoadingScreen() {
    console.log("customLoadingScreen creation");
  }
  isReadyAll() {
    let flag = this.scene.meshes?.every(
      (mesh) => mesh.material && mesh.material.isReady(mesh)
    );
    return flag;
  }

  private async _init(): Promise<void> {
    // this.createLoading();
    this.createCamera();
    // this.createSkyBox();
    // this.cameraAnimation();
    this.createLight();
    // this.createShadow();
    // this.createGround();
    // this.screenShot();
    let queryString = window.location.search.split("?")[1];
    let query = qs.parse(queryString);
    this.engine.runRenderLoop(() => this.scene.render());
    let data = (await this.get(
      "https://cms-oss-sh-dev.oss-cn-shanghai.aliyuncs.com/jpc/2021-03-10/data/data1.json"
    )) as Data;

    let list = data.data.reduce((result, current) => {
      if (current.id == query.id) {
        result.push(...current.list);
      }
      return result;
    }, []);

    let materialList = list;
    // this.engine.loadingScreen.displayLoadingUI();
    SceneLoader.LoadAssetContainer(
      "https://cms-oss-sh-dev.oss-cn-shanghai.aliyuncs.com/jpc/2021-03-10/3D_Model/",
      "115.obj",
      this.scene,
      (container) => {
        this.scene.executeWhenReady(() => {
          if (!this.scene.activeCamera) {
            throw new Error(
              "No camera defined in the scene. Please add at least one camera in the project or create one yourself in the code."
            );
          }
          container.meshes.forEach((mesh: any) => {
            mesh.material = new PBRMetallicRoughnessMaterial("pbr", this.scene);
            // mesh.position = new Vector3(0, -800, 0);
            mesh.material.metallic = 0.0;
            mesh.material.roughness = 1;
            mesh.material.alpha = 1;
            mesh.material.metallicF0Factor = 0;

            mesh.material.useRoughnessFromMetallicTextureAlpha = false;
            mesh.material.useRoughnessFromMetallicTextureGreen = true;
            mesh.material.useMetallnessFromMetallicTextureBlue = true;
            //截图是模型保持中心
            mesh.material.useAmbientInGrayScale = true;

            mesh.scaling.z = 4;
            mesh.scaling.y = 4;
            mesh.scaling.x = 4;
            mesh.alwaysSelectAsActiveMesh = true;

            let uScale = 8;
            let vScale = 8;
            //颜色

            mesh.material.baseTexture = new Texture(
              materialList[0],
              this.scene
            );
            mesh.material.baseTexture.uScale = uScale;
            mesh.material.baseTexture.vScale = vScale;

            mesh.material.normalTexture = new Texture(
              materialList[1],
              this.scene
            );
            mesh.material.normalTexture.uScale = uScale;
            mesh.material.normalTexture.vScale = vScale;

            mesh.material.useParallax = true;
            mesh.material.useParallaxOcclusion = true;
            mesh.material.parallaxScaleBias = 11;
            mesh.material.specularPower = 1000.0;

            // 金属/粗糙
            mesh.material.metallicRoughnessTexture = new Texture(
              materialList[2],
              this.scene
            );
            mesh.material.metallicRoughnessTexture.uScale = uScale;
            mesh.material.metallicRoughnessTexture.vScale = vScale;
            mesh.material.invertNormalMapX = true;
            mesh.material.invertNormalMapY = true;
            mesh.isReady((val) => {
              console.log(val);
            });
            // this.shadowGenerator.getShadowMap().renderList.push(mesh);
          });
          container.addAllToScene();
        });
      },
      null,
      function (err) {
        console.log("err", err);
      }
    );
  }

  /**
   * Binds the required events for a full experience.
   */
  private _bindEvents(): void {
    window.addEventListener("resize", () => this.engine.resize());
  }
}

I think you will need to provide a repro in the Playground if you want people to help you.

playground can use typescript?

Yes, click on TS:
image

And there is no highlight :joy:

What to do now? :joy:

Try to clear the cache of the browser / hit CTRL+F5. It does work for me (Chrome and Firefox):

1 Like

https://playground.babylonjs.com/#609BJS#1

This is playground , has same problem, can you help me? thank you.

sometimes only once click will arise this
problem :grinning: :sob:

This is the standard behaviour of the auto rotation feature: when you click with the mouse or the keyboard keys, the rotation stops for some time, then automatically restarts if no new user interaction occurred.

You can decrease the value of idleRotationWaitTime if you want to stop for a shorter time. Or don’t use the auto rotation feature (useAutoRotationBehavior = false) and rotate the camera yourself:

https://playground.babylonjs.com/#609BJS#3

2 Likes

thank you , this advice resolve my problem. very nice :grinning: