849 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
			
		
		
	
	
			849 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			JavaScript
		
	
	
/**
 | 
						||
 * @Documents
 | 
						||
 * 
 | 
						||
 * 配置3D时选择模型文件后使用 MDCThreeD.readCabinetList 读取模型文件中的柜子列表,返回所有柜子的编号
 | 
						||
 * MDCThreeD.readCabinetList('./img/3d/molds/mdc.fbx').then(indexs => {
 | 
						||
 *   console.log(indexs);
 | 
						||
 * });
 | 
						||
 */
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 3D页面
 | 
						||
 * @param {*} options 初始化选项
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
function MDCThreeD(options) {
 | 
						||
    this.options = options;
 | 
						||
    this.container = options.container;
 | 
						||
    this.touchHandle = this.onTouch.bind(this);
 | 
						||
    this.touchendHandle = this.onTouchEnd.bind(this);
 | 
						||
    this.touchMoveHandle = this.onTouchMove.bind(this);
 | 
						||
    this.mousemoveHandle = this.onMouseMove.bind(this);
 | 
						||
    this.mouseleaveHandle = this.onMouseLeave.bind(this);
 | 
						||
    this.scope = options.scope;
 | 
						||
    this.exitFlag = false;
 | 
						||
    if (this.options.buttons) {
 | 
						||
        for (var i = 0; i < this.options.buttons.length; i++) {
 | 
						||
            var self = this;
 | 
						||
            this.options.buttons[i].index = i;
 | 
						||
            this.options.buttons[i].onclick = function (arg) {
 | 
						||
                var index = arg[0];
 | 
						||
                var position = self.originPosition;
 | 
						||
                if (index === 0) {
 | 
						||
                    if (self.camera.position.distanceTo(self.originPosition) < 1) {
 | 
						||
                        position = self.getAnotherSide(self.originPosition);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                self.camera.position.copy(position);
 | 
						||
                self.camera.updateProjectionMatrix();
 | 
						||
                for (var i = 0; i < self.options.buttons.length; i++) {
 | 
						||
                    self.options.buttons[i].classList.remove('mdc-3d-button-active');
 | 
						||
                }
 | 
						||
                self.options.buttons[index].classList.add('mdc-3d-button-active');
 | 
						||
                for (var i = 0; i < self.actions.length; i++) {
 | 
						||
                    self.actions[i].stop();
 | 
						||
                }
 | 
						||
                self.controls.autoRotate = index === 1;
 | 
						||
                if (index === 2) {
 | 
						||
                    for (var i = 0; i < self.actions.length; i++) {
 | 
						||
                        self.actions[i].play();
 | 
						||
                    }
 | 
						||
                }
 | 
						||
            }.bind(this, [i])
 | 
						||
        }
 | 
						||
    }
 | 
						||
    if (this.isWebGL2Available()) {
 | 
						||
        this.renderer = new THREE.WebGLRenderer({
 | 
						||
            antialias: true,
 | 
						||
            alpha: true
 | 
						||
        });
 | 
						||
    } else if (this.isWebGLAvailable()) {
 | 
						||
        this.renderer = new THREE.WebGL1Renderer({
 | 
						||
            antialias: true,
 | 
						||
            alpha: true
 | 
						||
        });
 | 
						||
    } else {
 | 
						||
        throw new Error('该浏览器不支持WEBGL3D渲染,请尝试使用最新版本的Chrome或Edge浏览器。');
 | 
						||
    }
 | 
						||
 | 
						||
    if (typeof this.renderer.domElement.onpointerdown != 'undefined') {
 | 
						||
        this.renderer.domElement.addEventListener('pointerdown', this.touchHandle, false);
 | 
						||
    } else {
 | 
						||
        this.renderer.domElement.addEventListener('mousedown', this.touchHandle, false);
 | 
						||
    }
 | 
						||
 | 
						||
 | 
						||
    if (typeof this.renderer.domElement.onpointerup != 'undefined') {
 | 
						||
        this.renderer.domElement.addEventListener('pointerup', this.touchendHandle, false);
 | 
						||
    } else {
 | 
						||
        this.renderer.domElement.addEventListener('mouseup', this.touchendHandle, false);
 | 
						||
    }
 | 
						||
 | 
						||
    if (typeof this.renderer.domElement.onpointermove != 'undefined') {
 | 
						||
        this.renderer.domElement.addEventListener('pointermove', this.touchMoveHandle, false);
 | 
						||
    } else {
 | 
						||
        this.renderer.domElement.addEventListener('mousemove', this.touchMoveHandle, false);
 | 
						||
    }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
    // 鼠标停留
 | 
						||
    this.renderer.domElement.addEventListener('mousemove', this.mousemoveHandle, false);
 | 
						||
    // 鼠标离开
 | 
						||
    this.renderer.domElement.addEventListener('mouseleave', this.mouseleaveHandle, false);
 | 
						||
 | 
						||
    // this.renderer.domElement.addEventListener('touchstart', this.touchHandle, false);
 | 
						||
    // this.renderer.domElement.addEventListener('touchmove', this.touchMoveHandle, false);
 | 
						||
    // this.renderer.domElement.addEventListener('touchend', this.touchendHandle, false);
 | 
						||
 | 
						||
 | 
						||
    this.container.appendChild(this.renderer.domElement);
 | 
						||
    this.renderer.domElement.style.width = '100%';
 | 
						||
    this.renderer.domElement.style.height = '100%';
 | 
						||
    this.initData();
 | 
						||
    this.loadCamera();
 | 
						||
    this.loadControls();
 | 
						||
    this.loadEnvironment();
 | 
						||
    this.loadTemplate();
 | 
						||
    requestAnimationFrame(this.render.bind(this));
 | 
						||
    return this;
 | 
						||
}
 | 
						||
/**
 | 
						||
 * 定义柜子对象的命名规则
 | 
						||
 */
 | 
						||
MDCThreeD.cabinetRegExp = /cabinet[1-9]+[0-9]*/;
 | 
						||
 | 
						||
/*:1
 | 
						||
 * 机柜对象表
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.cabinets = {};
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 3D配置选项
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.options = {
 | 
						||
    /**
 | 
						||
     * 容器DIV对象,初始化传入\
 | 
						||
     */
 | 
						||
    container: null,
 | 
						||
    /**
 | 
						||
     * 静态背景图路径,可选\
 | 
						||
     */
 | 
						||
    background: null,
 | 
						||
    /**
 | 
						||
     * 控制按钮列表\
 | 
						||
     * 传入button对象数组
 | 
						||
     * [0:静止,1:旋转,2:动画]
 | 
						||
     */
 | 
						||
    buttons: [],
 | 
						||
    /**
 | 
						||
     * 是否使用环境光贴图?\
 | 
						||
     * 模拟房间的环境光
 | 
						||
     */
 | 
						||
    environmentLight: true,
 | 
						||
 | 
						||
    /**
 | 
						||
     * 模型文件
 | 
						||
     */
 | 
						||
    modelFile: './img/3d/molds/mdc.fbx',
 | 
						||
 | 
						||
    /**
 | 
						||
     * 机柜点击变色 \
 | 
						||
     * #007ACC
 | 
						||
     */
 | 
						||
    touchDiscolor: null
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 初始化数据
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.initData = function () {
 | 
						||
    this.cabinets = {};
 | 
						||
    this.actions = [];
 | 
						||
    this.touchObject = null;
 | 
						||
    this.mixer = new THREE.AnimationMixer();
 | 
						||
    this.clock = new THREE.Clock();
 | 
						||
    this.scene = new THREE.Scene();
 | 
						||
    this.raycaster = new THREE.Raycaster();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 命中对象事件
 | 
						||
 * @param {*} object 命中对象
 | 
						||
 * @param {*} cabinetIndex 对象的柜子编号
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.objectTouch = function (object, cabinetIndex) {
 | 
						||
    this.scope.cabinetClk(cabinetIndex);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 获取一个坐标围绕中心点的另一面
 | 
						||
 * Y轴旋转180度
 | 
						||
 * @param {*} position 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.getAnotherSide = function (position) {
 | 
						||
    var ps = position.clone().sub(this.controls.target);
 | 
						||
    this.transformGroup.rotation.set(0, 0, 0);
 | 
						||
    this.transformObject.position.copy(ps);
 | 
						||
    this.transformGroup.rotation.y = Math.PI;
 | 
						||
    this.transformGroup.updateMatrixWorld(true);
 | 
						||
    const pos = new THREE.Vector3();
 | 
						||
    pos.setFromMatrixPosition(this.transformObject.matrixWorld)
 | 
						||
    return pos.add(this.controls.target);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 鼠标按下事件处理
 | 
						||
 * @param {*} event 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.onTouch = function (event) {
 | 
						||
    event.preventDefault();
 | 
						||
    const position = this.getPlatformMousePosition(event);
 | 
						||
    var rect = this.renderer.domElement.getBoundingClientRect();
 | 
						||
    position.sub(new THREE.Vector2(rect.x | rect.left, rect.y | rect.top));
 | 
						||
    var x = (position.x / rect.width) * 2 - 1;
 | 
						||
    var y = -(position.y / rect.height) * 2 + 1;
 | 
						||
    this.coord = new THREE.Vector2(x, y);
 | 
						||
    this.raycaster.setFromCamera(this.coord, this.camera);
 | 
						||
    var hitobjects = this.raycaster.intersectObjects(this.scene.children, true);
 | 
						||
    if (hitobjects.length > 0) {
 | 
						||
        const object = hitobjects[0].object;
 | 
						||
        if (this.isCabinet(object)) {
 | 
						||
            this.touchPosition = position;
 | 
						||
            this.touchObject = object;
 | 
						||
            this.discolor(this.touchObject, true);
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 鼠标停留
 | 
						||
 * @Author: Eddy
 | 
						||
 * @Date: 2021-06-05 16:59:25
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.onMouseMove = function (event) {
 | 
						||
    event.preventDefault();
 | 
						||
    const position = this.getPlatformMousePosition(event);
 | 
						||
    var rect = this.renderer.domElement.getBoundingClientRect();
 | 
						||
    position.sub(new THREE.Vector2(rect.x | rect.left, rect.y | rect.top));
 | 
						||
    var x = (position.x / rect.width) * 2 - 1;
 | 
						||
    var y = -(position.y / rect.height) * 2 + 1;
 | 
						||
    this.coord = new THREE.Vector2(x, y);
 | 
						||
    this.raycaster.setFromCamera(this.coord, this.camera);
 | 
						||
    var hitobjects = this.raycaster.intersectObjects(this.scene.children, true);
 | 
						||
    var currentObject = null;
 | 
						||
    if (hitobjects.length > 0) {
 | 
						||
        const object = hitobjects[0].object;
 | 
						||
        if (this.isCabinet(object)) {
 | 
						||
            currentObject = object;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    if (this.nouseObject != currentObject) {
 | 
						||
        if (this.nouseObject != null) {
 | 
						||
            this.discolor(this.nouseObject, false);
 | 
						||
            this.nouseObject = null;
 | 
						||
        }
 | 
						||
        this.nouseObject = currentObject;
 | 
						||
        if (this.nouseObject != null) {
 | 
						||
            this.discolor(this.nouseObject, true);
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 鼠标离开画布
 | 
						||
 * @Author: Eddy
 | 
						||
 * @Date: 2021-06-05 17:02:45
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.onMouseLeave = function (event) {
 | 
						||
    if (this.nouseObject) {
 | 
						||
        this.discolor(this.nouseObject, false);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 鼠标移动事件
 | 
						||
 * @param {*} event 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.onTouchMove = function (event) {
 | 
						||
    if (this.touchObject && this.touchPosition) {
 | 
						||
        const position = this.getPlatformMousePosition(event);
 | 
						||
        var rect = this.renderer.domElement.getBoundingClientRect();
 | 
						||
        position.sub(new THREE.Vector2(rect.x | rect.left, rect.y | rect.top));
 | 
						||
        /* 按下后拖动距离大于5像素,取消点击处理 */
 | 
						||
        const distance = this.touchPosition.clone().distanceTo(position.clone());
 | 
						||
        if (distance > 5) {
 | 
						||
            this.discolor(this.touchObject, false);
 | 
						||
            this.touchPosition = null;
 | 
						||
            this.touchObject = null;
 | 
						||
        }
 | 
						||
        event.preventDefault();
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 鼠标抬起事件
 | 
						||
 * @param {*} event 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.onTouchEnd = function (event) {
 | 
						||
    if (this.touchPosition == null || this.touchObject == null) return;
 | 
						||
    event.preventDefault();
 | 
						||
    this.discolor(this.touchObject, false);
 | 
						||
    this.objectTouch(this.touchObject, this.touchObject.userData.cabinetIndex);
 | 
						||
    this.touchPosition = null;
 | 
						||
    this.touchObject = null;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 变色
 | 
						||
 * @param {*} object 
 | 
						||
 * @param {*} enabled 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.discolor = function (object, enabled) {
 | 
						||
    if (this.options.touchDiscolor == null) return;
 | 
						||
    var emissive = new THREE.Color(this.options.touchDiscolor);
 | 
						||
    if (enabled) {
 | 
						||
        if (object._material == null) {
 | 
						||
            object._material = object.material;
 | 
						||
            if (object._material instanceof THREE.Material) {
 | 
						||
                object.material = object.material.clone();
 | 
						||
                object.material.emissive = emissive;
 | 
						||
            } else if (object.material instanceof Array) {
 | 
						||
                const materials = [];
 | 
						||
                for (var i = 0; i < object.material.length; i++) {
 | 
						||
                    const m = object.material[i].clone();
 | 
						||
                    m.emissive = emissive;
 | 
						||
                    materials.push(m);
 | 
						||
                }
 | 
						||
                object.material = materials;
 | 
						||
            }
 | 
						||
        }
 | 
						||
    } else {
 | 
						||
        if (object._material) {
 | 
						||
            if (object.material instanceof THREE.Material) {
 | 
						||
                object.material.dispose();
 | 
						||
            } else if (object.material instanceof Array) {
 | 
						||
                for (var i = 0; i < object.material.length; i++) {
 | 
						||
                    object.material[i].dispose();
 | 
						||
                }
 | 
						||
                object.material.length = 0;
 | 
						||
            }
 | 
						||
            object.material = object._material;
 | 
						||
            delete object._material;
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.loadObjectLabels = function () {
 | 
						||
    var scope = this.options.scope;
 | 
						||
    var devices = scope.NewMdcConfigures;
 | 
						||
    var configs = scope.cabinets;
 | 
						||
    for (var key in this.cabinets) {
 | 
						||
        var cabinet = this.cabinets[key];
 | 
						||
        var object3d = cabinet.object;
 | 
						||
        var index = cabinet.index;
 | 
						||
        var txtobject = object3d.getObjectByName('txt' + index);
 | 
						||
        if (txtobject) {
 | 
						||
            var info = this.createCanvasMaterial(this.options.labelOptions.width, this.options.labelOptions.height);
 | 
						||
            var cfg = _.findWhere(configs, {
 | 
						||
                no: index
 | 
						||
            });
 | 
						||
            if (cfg) {
 | 
						||
                this.drawCanvasLabel(info, cfg.cabinetName);
 | 
						||
                // var dev = _.findWhere(devices, {
 | 
						||
                //     configId: cfg.configId
 | 
						||
                // });
 | 
						||
                // if (dev) {
 | 
						||
                //     this.drawCanvasLabel(info, dev.configName);
 | 
						||
                // }
 | 
						||
            }
 | 
						||
            //this.drawCanvasLabel(info, "Txt"+index);
 | 
						||
            txtobject.material = info.material;
 | 
						||
        }else
 | 
						||
            console.log("3D模型不正确!");
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 渲染标签文本
 | 
						||
 * @param {*} info 材质纹理等信息
 | 
						||
 * @param {*} text 渲染文本
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.drawCanvasLabel = function (info, text) {
 | 
						||
    var options = this.options.labelOptions;
 | 
						||
    var ctx = info.context;
 | 
						||
    var fontsize = options.fontSize == null ? info.height * 0.8 : options.fontSize;
 | 
						||
    var fontstyle = fontsize + 'px ' + options.font;
 | 
						||
    if (options.bold) fontstyle += " bold";
 | 
						||
    ctx.font = fontstyle;
 | 
						||
    ctx.clearRect(0, 0, info.width, info.height);
 | 
						||
    ctx.fillStyle = options.color;
 | 
						||
    ctx.globalAlpha = 1;
 | 
						||
    ctx.textBaseline = "top";
 | 
						||
    var textwidth = ctx.measureText(text).width;
 | 
						||
    var left = (info.width - textwidth) / 2;
 | 
						||
    var top = (info.height - fontsize) / 2;
 | 
						||
    ctx.fillText(text, left, top);
 | 
						||
    info.texture.needsUpdate = true;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 创建材质和贴图
 | 
						||
 * @param {*} width 
 | 
						||
 * @param {*} height 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.createCanvasMaterial = function (width, height) {
 | 
						||
    var canvas = document.createElement('canvas');
 | 
						||
    var devicePixelRatio = window.devicePixelRatio;
 | 
						||
    canvas.style.width = width + "px";
 | 
						||
    canvas.style.height = height + "px";
 | 
						||
    canvas.height = height * devicePixelRatio;
 | 
						||
    canvas.width = width * devicePixelRatio;
 | 
						||
    var context = canvas.getContext('2d');
 | 
						||
    context.scale(devicePixelRatio, devicePixelRatio);
 | 
						||
    context.imageSmoothingEnabled = true;
 | 
						||
    context.translate(0, 0);
 | 
						||
    context.imageSmoothingEnabled = true;
 | 
						||
    context.imageSmoothingQuality = "high";
 | 
						||
    context.clearRect(0, 0, width, height);
 | 
						||
 | 
						||
    var texture = new THREE.CanvasTexture(canvas);
 | 
						||
    // texture.encoding = THREE.sRGBEncoding;
 | 
						||
    texture.magFilter = THREE.NearestFilter;
 | 
						||
    texture.minFilter = THREE.LinearMipmapLinearFilter;
 | 
						||
 | 
						||
    var material = new THREE.MeshBasicMaterial({
 | 
						||
        map: texture,
 | 
						||
        transparent: true,
 | 
						||
        depthTest : false
 | 
						||
    });
 | 
						||
    return {
 | 
						||
        width: width,
 | 
						||
        height: height,
 | 
						||
        canvas: canvas,
 | 
						||
        context: context,
 | 
						||
        texture: texture,
 | 
						||
        material: material
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 加载模型
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.loadTemplate = function () {
 | 
						||
    const loader = new THREE.FBXLoader();
 | 
						||
    var self = this;
 | 
						||
 | 
						||
    loader.load(this.options.modelFile, function (root) {
 | 
						||
        root.position.set(0, 0, 0);
 | 
						||
        root.traverse(function (e) {
 | 
						||
            if (e instanceof THREE.Light) {
 | 
						||
                e.intensity = 0.5;
 | 
						||
            }
 | 
						||
            self.initCabinet(e);
 | 
						||
        });
 | 
						||
        self.scene.add(root);
 | 
						||
        root.updateMatrixWorld();
 | 
						||
        // set the camera to frame the box
 | 
						||
        self.frameArea(root, 0.9);
 | 
						||
        // update the Trackball controls to handle the new size
 | 
						||
 | 
						||
        if (root.animations && root.animations.length > 0) {
 | 
						||
            for (var i = 0; i < root.animations.length; i++) {
 | 
						||
                const action = self.mixer.clipAction(root.animations[i], root);
 | 
						||
                action.loop = THREE.LoopRepeat;
 | 
						||
                self.actions.push(action);
 | 
						||
            }
 | 
						||
        }
 | 
						||
        self.loadObjectLabels();
 | 
						||
    });
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * [静态方法]\
 | 
						||
 * 从模型文件读取柜子的列表
 | 
						||
 * @param {string} modelFile 模型文件路径
 | 
						||
 */
 | 
						||
// MDCThreeD.readCabinetList = async function (modelFile) {
 | 
						||
//     const result = [];
 | 
						||
//     const loader = new THREE.FBXLoader();
 | 
						||
//     const root = await loader.loadAsync(modelFile);
 | 
						||
//     root.traverse(function (object) {
 | 
						||
//         if (object instanceof THREE.Mesh) {
 | 
						||
//             const indexs = object.name.match(/\d+(\.\d+)?/g);
 | 
						||
//             if (MDCThreeD.cabinetRegExp.test(object.name) && indexs.length === 1) {
 | 
						||
//                 const index = Number.parseInt(indexs[0]);
 | 
						||
//                 result.push(index);
 | 
						||
//             }
 | 
						||
//         }
 | 
						||
//     });
 | 
						||
//     return result.sort(function (a, b) {
 | 
						||
//         return a < b ? -1 : (a === b) ? 0 : 1
 | 
						||
//     });
 | 
						||
// }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
/**
 | 
						||
 * 初始化柜子
 | 
						||
 * @param {*} object 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.initCabinet = function (object) {
 | 
						||
    if (object instanceof THREE.Mesh) {
 | 
						||
        const indexs = object.name.match(/\d+(\.\d+)?/g);
 | 
						||
        if (MDCThreeD.cabinetRegExp.test(object.name) && indexs.length === 1) {
 | 
						||
            const index = parseInt(indexs[0]);
 | 
						||
            object.userData.selectable = true;
 | 
						||
            object.userData.cabinetIndex = index;
 | 
						||
            this.cabinets[index] = {
 | 
						||
                index: index,
 | 
						||
                object: object,
 | 
						||
            };
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * 判断命中对象是否是柜子
 | 
						||
 * @param {*} object 
 | 
						||
 * @returns 
 | 
						||
 */
 | 
						||
MDCThreeD.prototype.isCabinet = function (object) {
 | 
						||
    return object.userData.selectable && object.userData.cabinetIndex;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.dispose = function () {
 | 
						||
    this.exitFlag = true;
 | 
						||
    this.renderer.domElement.removeEventListener('pointerdown', this.touchHandle);
 | 
						||
    this.renderer.domElement.removeEventListener('pointermove', this.touchMoveHandle);
 | 
						||
    this.renderer.domElement.removeEventListener('pointerup', this.touchendHandle);
 | 
						||
 | 
						||
    this.renderer.domElement.removeEventListener('touchstart', this.touchHandle);
 | 
						||
    this.renderer.domElement.removeEventListener('touchmove', this.touchMoveHandle);
 | 
						||
    this.renderer.domElement.removeEventListener('touchend', this.touchendHandle);
 | 
						||
    if (this.renderer) {
 | 
						||
        this.scene.traverse(function (e) {
 | 
						||
            if (e instanceof THREE.Mesh) {
 | 
						||
                if (e.geometry) e.geometry.dispose();
 | 
						||
                if (e.material instanceof Array) {
 | 
						||
                    for (var i = 0; i < e.material.length; i++) {
 | 
						||
                        e.material[i].dispose();
 | 
						||
                    }
 | 
						||
                } else if (e.material) e.material.dispose();
 | 
						||
            }
 | 
						||
        });
 | 
						||
        this.renderer.dispose();
 | 
						||
        this.renderer = null;
 | 
						||
    }
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.render = function () {
 | 
						||
    if (this.exitFlag) return;
 | 
						||
    this.controls.update();
 | 
						||
    var delta = this.clock.getDelta();
 | 
						||
    this.mixer.update(delta);
 | 
						||
    if (this.resizeRendererToDisplaySize()) {
 | 
						||
        const canvas = this.renderer.domElement;
 | 
						||
        this.camera.aspect = canvas.clientWidth / canvas.clientHeight;
 | 
						||
        this.camera.updateProjectionMatrix();
 | 
						||
    }
 | 
						||
    this.renderer.render(this.scene, this.camera);
 | 
						||
    requestAnimationFrame(this.render.bind(this));
 | 
						||
};
 | 
						||
 | 
						||
MDCThreeD.prototype.isWebGLAvailable = function () {
 | 
						||
    try {
 | 
						||
        var canvas = document.createElement('canvas');
 | 
						||
        return !!(window.WebGLRenderingContext && (canvas.getContext('webgl') || canvas.getContext('experimental-webgl')));
 | 
						||
    } catch (e) {
 | 
						||
        return false;
 | 
						||
    }
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.getPlatformMousePosition = function (event) {
 | 
						||
    if (event.touches != null && event.touches.length > 0) {
 | 
						||
        return new THREE.Vector2(event.touches[0].clientX, event.touches[0].clientY);
 | 
						||
    } else {
 | 
						||
        var u = window.navigator.userAgent.toLocaleLowerCase();
 | 
						||
        var b = u.match(/(trident)\/([\d.]+)/);
 | 
						||
        if (b) {
 | 
						||
            var rect = event.target.getBoundingClientRect();
 | 
						||
            return new THREE.Vector2(event.pageX - rect.left, event.pageY - rect.top);
 | 
						||
        } else {
 | 
						||
            return new THREE.Vector2(event.clientX, event.clientY);
 | 
						||
        }
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.isWebGL2Available = function () {
 | 
						||
    try {
 | 
						||
        var canvas = document.createElement('canvas');
 | 
						||
        return !!(window.WebGL2RenderingContext && canvas.getContext('webgl2'));
 | 
						||
    } catch (e) {
 | 
						||
        return false;
 | 
						||
    }
 | 
						||
};
 | 
						||
MDCThreeD.prototype.resizeRendererToDisplaySize = function () {
 | 
						||
    const canvas = this.renderer.domElement;
 | 
						||
    const width = canvas.clientWidth;
 | 
						||
    const height = canvas.clientHeight;
 | 
						||
    const needResize = canvas.width !== width || canvas.height !== height;
 | 
						||
    if (needResize) {
 | 
						||
        this.camera.aspect = width / height;
 | 
						||
        this.camera.updateProjectionMatrix();
 | 
						||
        this.renderer.setSize(width, height, false);
 | 
						||
    }
 | 
						||
    return needResize;
 | 
						||
};
 | 
						||
 | 
						||
MDCThreeD.prototype.frameArea = function (object, sizeToFitOnScreen) {
 | 
						||
    const box = new THREE.Box3().setFromObject(object);
 | 
						||
    const size = box.getSize(new THREE.Vector3());
 | 
						||
    const boxSize = size.length();
 | 
						||
    const boxCenter = box.getCenter(new THREE.Vector3());
 | 
						||
    boxCenter.setY(-size.y / 2); //起始位置
 | 
						||
    const halfSizeToFitOnScreen = boxSize * sizeToFitOnScreen * 0.5;
 | 
						||
    const halfFovY = THREE.MathUtils.degToRad(this.camera.fov * .5);
 | 
						||
    const distance = halfSizeToFitOnScreen / Math.tan(halfFovY);
 | 
						||
    const direction = (new THREE.Vector3())
 | 
						||
        .subVectors(this.camera.position, boxCenter)
 | 
						||
        .multiply(new THREE.Vector3(1, 0, 1))
 | 
						||
        .normalize();
 | 
						||
    this.camera.position.copy(direction.multiplyScalar(distance).add(boxCenter));
 | 
						||
    this.camera.near = boxSize / 100;
 | 
						||
    this.camera.far = boxSize * 100;
 | 
						||
    this.camera.position.setX(1300);
 | 
						||
    this.camera.position.setY(700);
 | 
						||
    this.camera.position.setZ(300);
 | 
						||
    this.originPosition = this.camera.position.clone();
 | 
						||
    this.camera.updateProjectionMatrix();
 | 
						||
    this.camera.lookAt(boxCenter.x, boxCenter.y, boxCenter.z);
 | 
						||
    this.controls.maxDistance = boxSize * 10;
 | 
						||
    this.controls.target.copy(boxCenter);
 | 
						||
    this.controls.update();
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.RoomEnvironment = function () {
 | 
						||
 | 
						||
    const scene = new THREE.Scene();
 | 
						||
 | 
						||
    const geometry = new THREE.BoxBufferGeometry();
 | 
						||
    geometry.deleteAttribute('uv');
 | 
						||
 | 
						||
    const roomMaterial = new THREE.MeshStandardMaterial({
 | 
						||
        side: THREE.BackSide
 | 
						||
    });
 | 
						||
    const boxMaterial = new THREE.MeshStandardMaterial();
 | 
						||
 | 
						||
    const mainLight = new THREE.PointLight(0xffffff, 5.0, 28, 2);
 | 
						||
    mainLight.position.set(0.418, 16.199, 0.300);
 | 
						||
    scene.add(mainLight);
 | 
						||
 | 
						||
    const room = new THREE.Mesh(geometry, roomMaterial);
 | 
						||
    room.position.set(-0.757, 13.219, 0.717);
 | 
						||
    room.scale.set(31.713, 28.305, 28.591);
 | 
						||
    scene.add(room);
 | 
						||
 | 
						||
    const box1 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box1.position.set(-10.906, 2.009, 1.846);
 | 
						||
    box1.rotation.set(0, -0.195, 0);
 | 
						||
    box1.scale.set(2.328, 7.905, 4.651);
 | 
						||
    scene.add(box1);
 | 
						||
 | 
						||
    const box2 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box2.position.set(-5.607, -0.754, -0.758);
 | 
						||
    box2.rotation.set(0, 0.994, 0);
 | 
						||
    box2.scale.set(1.970, 1.534, 3.955);
 | 
						||
    scene.add(box2);
 | 
						||
 | 
						||
    const box3 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box3.position.set(6.167, 0.857, 7.803);
 | 
						||
    box3.rotation.set(0, 0.561, 0);
 | 
						||
    box3.scale.set(3.927, 6.285, 3.687);
 | 
						||
    scene.add(box3);
 | 
						||
 | 
						||
    const box4 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box4.position.set(-2.017, 0.018, 6.124);
 | 
						||
    box4.rotation.set(0, 0.333, 0);
 | 
						||
    box4.scale.set(2.002, 4.566, 2.064);
 | 
						||
    scene.add(box4);
 | 
						||
 | 
						||
    const box5 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box5.position.set(2.291, -0.756, -2.621);
 | 
						||
    box5.rotation.set(0, -0.286, 0);
 | 
						||
    box5.scale.set(1.546, 1.552, 1.496);
 | 
						||
    scene.add(box5);
 | 
						||
 | 
						||
    const box6 = new THREE.Mesh(geometry, boxMaterial);
 | 
						||
    box6.position.set(-2.193, -0.369, -5.547);
 | 
						||
    box6.rotation.set(0, 0.516, 0);
 | 
						||
    box6.scale.set(3.875, 3.487, 2.986);
 | 
						||
    scene.add(box6);
 | 
						||
 | 
						||
 | 
						||
    // -x right
 | 
						||
    const light1 = new THREE.Mesh(geometry, createAreaLightMaterial(50));
 | 
						||
    light1.position.set(-16.116, 14.37, 8.208);
 | 
						||
    light1.scale.set(0.1, 2.428, 2.739);
 | 
						||
    scene.add(light1);
 | 
						||
 | 
						||
    // -x left
 | 
						||
    const light2 = new THREE.Mesh(geometry, createAreaLightMaterial(50));
 | 
						||
    light2.position.set(-16.109, 18.021, -8.207);
 | 
						||
    light2.scale.set(0.1, 2.425, 2.751);
 | 
						||
    scene.add(light2);
 | 
						||
 | 
						||
    // +x
 | 
						||
    const light3 = new THREE.Mesh(geometry, createAreaLightMaterial(17));
 | 
						||
    light3.position.set(14.904, 12.198, -1.832);
 | 
						||
    light3.scale.set(0.15, 4.265, 6.331);
 | 
						||
    scene.add(light3);
 | 
						||
 | 
						||
    // +z
 | 
						||
    const light4 = new THREE.Mesh(geometry, createAreaLightMaterial(43));
 | 
						||
    light4.position.set(-0.462, 8.89, 14.520);
 | 
						||
    light4.scale.set(4.38, 5.441, 0.088);
 | 
						||
    scene.add(light4);
 | 
						||
 | 
						||
    // -z
 | 
						||
    const light5 = new THREE.Mesh(geometry, createAreaLightMaterial(20));
 | 
						||
    light5.position.set(3.235, 11.486, -12.541);
 | 
						||
    light5.scale.set(2.5, 2.0, 0.1);
 | 
						||
    scene.add(light5);
 | 
						||
 | 
						||
    // +y
 | 
						||
    const light6 = new THREE.Mesh(geometry, createAreaLightMaterial(100));
 | 
						||
    light6.position.set(0.0, 20.0, 0.0);
 | 
						||
    light6.scale.set(1.0, 0.1, 1.0);
 | 
						||
    scene.add(light6);
 | 
						||
 | 
						||
    function createAreaLightMaterial(intensity) {
 | 
						||
 | 
						||
        const material = new THREE.MeshBasicMaterial();
 | 
						||
        material.color.setScalar(intensity);
 | 
						||
        return material;
 | 
						||
 | 
						||
    }
 | 
						||
 | 
						||
    return scene;
 | 
						||
 | 
						||
}
 | 
						||
 | 
						||
MDCThreeD.prototype.loadCamera = function () {
 | 
						||
    const fov = 45;
 | 
						||
    const aspect = 2; // the canvas default
 | 
						||
    const near = 0.1;
 | 
						||
    const far = 100;
 | 
						||
    this.camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
 | 
						||
    this.camera.position.set(1500, 700, 500);
 | 
						||
}
 | 
						||
 | 
						||
MDCThreeD.prototype.loadControls = function () {
 | 
						||
    this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement);
 | 
						||
    this.controls.target.set(0, 5, 0);
 | 
						||
    this.controls.enablePan = false;
 | 
						||
    this.controls.enableDamping = false;
 | 
						||
    this.controls.minPolarAngle = 0;
 | 
						||
    this.controls.maxPolarAngle = Math.PI * 0.5;
 | 
						||
    this.controls.autoRotate = false;
 | 
						||
    this.controls.update();
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
MDCThreeD.prototype.loadEnvironment = function () {
 | 
						||
    // if (this.options.environmentLight) {
 | 
						||
    //     const pmremGenerator = new THREE.PMREMGenerator(this.renderer);
 | 
						||
    //     const texture = pmremGenerator.fromScene(this.RoomEnvironment()).texture;
 | 
						||
    //     this.scene.environment = texture;
 | 
						||
    //     pmremGenerator.dispose();
 | 
						||
    // }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
    if (this.options.background) {
 | 
						||
        this.scene.background = new THREE.TextureLoader().load(this.options.background);
 | 
						||
    }
 | 
						||
    // 
 | 
						||
    const light = new THREE.AmbientLight(0xFFFFFF, 0.2);
 | 
						||
    this.scene.add(light);
 | 
						||
    // 
 | 
						||
    const skyColor = 0xB1E1FF;
 | 
						||
    const groundColor = 0xB97A20;
 | 
						||
    const intensity = 0.5;
 | 
						||
    const hemisophereLight = new THREE.HemisphereLight(skyColor, groundColor, intensity);
 | 
						||
    this.scene.add(hemisophereLight);
 | 
						||
 | 
						||
 | 
						||
    /* 旋转变换 */
 | 
						||
    this.transformGroup = new THREE.Object3D();
 | 
						||
    this.transformObject = new THREE.Object3D();
 | 
						||
    this.transformGroup.add(this.transformObject);
 | 
						||
} |