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());
}
}