123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- let texLoader = new THREE.TextureLoader;
- let camera, scene, renderer, stats, gui;
- const mouse = new THREE.Vector2();
- const raycaster = new THREE.Raycaster(); raycaster.linePrecision = 0;//不检测boxHelper
- const Transitions = {
- doubleClick: 0,
- helperOpa: 1,
- }
- let labelIndex = 0
- var Viewer = function (index, dom) {
- THREE.EventDispatcher.call(this)
- this.index = index;
- this.dom = dom
- this.camera = new THREE.PerspectiveCamera();
- this.camera.position.set(0, 0, 0.78);
- this.control = new THREE.OrbitControls(this.camera, this.dom)
- this.control.enableDamping = true;
- this.control.dampingFactor = 0.4;
- this.control.minDistance = 0.3;
- this.control.maxDistance = 2;
- this.control.enablePan = true;
- this.control.enableZoom = true;
- this.setRenderer()
- this.scene = new THREE.Scene;
- this.pointerDownPos
- this.textures = [];
- this.labels = []
- this.active = false;
- this.antialias = true;
- this.clickTime = new Date().getTime();
- this.updateClock = new THREE.Clock;
- this.init()
- }
- Viewer.prototype = Object.create(THREE.EventDispatcher.prototype)
- Viewer.constructor = Viewer
- Viewer.prototype.bindEvents = function () {
- this.renderer.domElement.addEventListener('pointerdown', this.onPointerDown.bind(this), false);
- this.renderer.domElement.addEventListener('pointerup', this.onPointerUp.bind(this), false);
- }
- Viewer.prototype.setRenderer = function () {
- try {
- this.renderer = new THREE.WebGLRenderer(
- {
- canvas: $(this.dom).find("canvas")[0],
- antialias: true,
- alpha: true
- }
- ),//许钟文 添加个抗锯齿,否则添加的线条锯齿严重,
- this.renderer.setClearAlpha(0);
- //this.renderer.autoClear = !0,
- this.renderer.setPixelRatio(window.devicePixelRatio ? window.devicePixelRatio : 1)
- // this.renderer.autoClear = false
- //this.emit(Events.ContextCreated)
- } catch (e) {
- console.error("Unable to create a WebGL rendering context")
- }
- }
- Viewer.prototype.update = function (deltaTime) {//绘制的时候同时更新
- //if(!this.active)return;
- this.setSize()
- this.control.update(deltaTime)
- transitions.update(deltaTime)
- var needsUpdate = 1;
- if (needsUpdate) {
- //this.renderer.autoClear = true
- this.renderer.render(this.scene, this.camera)
- }
- }
- Viewer.prototype.hasChanged = function () {//判断画面是否改变了,改变后需要更新一些东西
- var copy = function () {
- this.previousState = {
- projectionMatrix: this.camera.projectionMatrix.clone(),//worldMatrix在control时归零了所以不用了吧,用position和qua也一样
- position: this.camera.position.clone(),
- quaternion: this.camera.quaternion.clone(),
- //mouse: this.mouse.clone(),
- fov: this.camera.fov
- };
- }.bind(this)
- if (!this.previousState) {
- copy()
- return { cameraChanged: !0, changeSlightly: !1 };
- }
- var cameraChanged =
- !this.camera.projectionMatrix.equals(this.previousState.projectionMatrix) ||
- !this.camera.position.equals(this.previousState.position) ||
- !this.camera.quaternion.equals(this.previousState.quaternion)
- //var changed = cameraChanged //|| !this.mouse.equals(this.previousState.mouse)
- let changeSlightly
- if(cameraChanged){
- changeSlightly = math.closeTo(this.camera.position,this.previousState.position, 1e-2) &&
- math.closeTo(this.camera.quaternion,this.previousState.quaternion, 1e-3)
- }
- copy()
- return { cameraChanged, changeSlightly };
- }
- Viewer.prototype.setSize = function () {
- var w, h, pixelRatio;
- return function () {
- if (w != this.dom.clientWidth || h != this.dom.clientHeight || pixelRatio != window.devicePixelRatio) {
- w = this.dom.clientWidth;
- h = this.dom.clientHeight;
- pixelRatio = window.devicePixelRatio;
- this.camera.aspect = w / h;
- this.camera.updateProjectionMatrix();
- this.renderer.setSize(w, h, false, pixelRatio);
- }
- }
- }()
- Viewer.prototype.init = function () {
- this.meshGroup = new THREE.Object3D();
- this.scene.add(this.meshGroup);
- this.meshGroup.name = "viewerMeshGroup";
- var buildScene = () => {
- this.animate()
- }
- this.loadOBJ(() => {
- this.bindEvents()
- //this.loadLabels()
- })
- buildScene()
- }
- Viewer.prototype.animate = function () {
- var deltaTime = Math.min(1, this.updateClock.getDelta());
- this.update(deltaTime)
- //bus.emit('player/position/change', {x:this.position.x, y:this.position.z, lon: this.cameraControls.controls.panorama.lon})
- let changed = this.hasChanged()
- if (changed.cameraChanged) {
- this.dispatchEvent({ type: 'view.changed', changeSlightly:changed.changeSlightly })
- let label_ = this.labels.filter(e => e.elem[0].style.display == 'block')
- label_.sort((a, b) => b.pos2d.z - a.pos2d.z)
- label_.forEach((e, index) => e.elem.css('z-index', index + 1000));
- }
- window.requestAnimationFrame(this.animate.bind(this));
- },
- Viewer.prototype.loadOBJ = function (done) {
- var startTime = new Date().getTime();
- window.objs = [];
- var group = new THREE.Object3D;
- this.meshGroup.add(group);
- function onProgress(xhr) {
- if (xhr.lengthComputable) {
- var percentComplete = xhr.loaded / xhr.total * 100;
- console.log('model ' + Math.round(percentComplete, 2) + '% downloaded');
- }
- }
- function onError() { }
- var MTLLoader = new THREE.MTLLoader();
- var OBJLoader = new THREE.OBJLoader()
- var loadModel = () => {
- var info = {//凳子
- path: 'model/',
- mtl: 'wl48-he.mtl',
- obj: 'wl48-he.obj',
- position: [0, 0],
- rotation: 0,
- height: 1
- };
- if (!info) {
- console.log("加载持续时间:" + (new Date().getTime() - startTime))
- return;
- }
- MTLLoader.setPath(info.path).load(info.mtl, (materials) => {
- materials.preload();
- OBJLoader.setMaterials(materials)
- .setPath(info.path)
- .load(info.obj, (object) => {
- group.add(object);
- object.traverse(function (child) {
- if (child.isMesh) {
- console.log(child);
- // if (child.name == "WL48_ping") {
- // let textrueLoader = new THREE.TextureLoader();
- // var emissiveTexture = textrueLoader.load("model/shadow.jpg");
- // // emissiveTexture.encoding = THREE.LinearEncoding;
- // child.material.emissiveMap = emissiveTexture;
- // child.material.emissiveIntensity = 0;
- // // let step = 1
- // // setInterval(() => {
- // // if (child.material.emissiveIntensity > 0.3) {
- // // step = -1
- // // }
- // // if (child.material.emissiveIntensity < 0) {
- // // step = 1
- // // }
- // // child.material.emissiveIntensity += 0.01 * step;
- // // }, 50);
- // child.material.emissive = new THREE.Color(0xffffff);
- // }
- /* if(child.geometry){
- child.geometry.computeBoundingBox();
- bound.union(child.geometry.boundingBox)
- } */
- }
- });
- this.model = object
- let s = 0.010
- object.scale.set(s, s, s)
- done && done()
- console.log("加载持续时间:" + (new Date().getTime() - startTime))
- setTimeout(() => {
- this.dispatchEvent({ type: 'hadLoaded' })
- });
- }, onProgress, onError);
- });
- }
- loadModel()
- var light1 = new THREE.AmbientLight(16777215);
- light1.intensity = 2.8;
- this.scene.add(light1)
- var light2 = new THREE.SpotLight(0xffffff, 1);
- light2.position.set(0, 0, 3)
- light2.intensity = 0.2;
- var light3 = new THREE.SpotLight(0xffffff, 1);
- light3.position.set(0, 0, -3)
- light3.intensity = 0.4;
- // let spotLightHelper = new THREE.SpotLightHelper(light2);
- // let spotLightHelper3 = new THREE.SpotLightHelper(light3);
- this.scene.add(light2)
- this.scene.add(light3)
- // this.scene.add( spotLightHelper );
- // this.scene.add( spotLightHelper3 );
- }
- Viewer.prototype.onPointerMove = function (event) {
- if (event.isPrimary === false) return;
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
- if (!this.pointerDownPos) this.checkIntersection();
- }
- Viewer.prototype.onPointerDown = function (event) {
- if (event.isPrimary === false) return;
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
- this.pointerDownPos = mouse.clone()
- }
- Viewer.prototype.onPointerUp = function (event) {
- if (event.isPrimary === false) return;
- mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
- mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
- if (mouse.distanceTo(this.pointerDownPos) < 0.006) {//click
- this.checkIntersection()
- // if (this.intersects.length) {
- // console.log(this.intersects[0].point);
- // this.addLabel({ position: this.intersects[0].point })
- // }
- var time = new Date().getTime();
- if (time - this.clickTime < 300) {
- if (this.intersects.length) {
- console.log('doubleClick');
- transitions.cancelById(0)
- transitions.start(lerp.vector(this.control.target, this.intersects[0].point), 600, null, 0/* Delay */, easing.easeInOutQuad, null, Transitions.doubleClick);
- }
- }
- this.clickTime = time;
- }
- this.pointerDownPos = null
- }
- Viewer.prototype.checkIntersection = function () {
- raycaster.setFromCamera(mouse, this.camera);
- const intersects = raycaster.intersectObject(this.model/* this.meshGroup */, true);
- this.intersects = intersects;
- }
- /* Viewer.prototype.adjustModelPos = function(){ //固定地板高度的情况下,调整模型的position.y
-
- this.meshGroup.updateMatrixWorld();
- this.model.updateMatrixWorld();
- var bound = this.model.bound.clone().applyMatrix4(this.model.matrixWorld)
- var center = bound.getCenter()
-
-
- //为了让最低点在地面上:
- this.meshGroup.position.y += floorY - bound.min.y
- //居中:
- this.meshGroup.position.x += 0 - center.x
- this.meshGroup.position.z += 0 - center.z
-
-
- } */
- Viewer.prototype.removeAllLabels = function (data) {
- this.labels.forEach(label=>{
- label.dispose()
- label = null
- })
- this.labels = []
- }
- Viewer.prototype.loadLabelsFromData = function (data) {
-
- data.forEach(info => {
- info.position = new THREE.Vector3().fromArray(info.posInModel).applyMatrix4(this.model.matrixWorld)
- this.addLabel(info)
- })
- }
- Viewer.prototype.addLabel = function (o) {
- labelIndex++
- o.title = o.title || ('default' + labelIndex)
- o.shelterByModel = true
- let label = new Label2D(o)
- this.labels.push(label)
- }
- Viewer.prototype.removeLabel = function (label) {
- label.dispose()
- let index = this.labels.indexOf(label)
- index > -1 && this.labels.splice(index)
- label.li && label.li.remove()
- }
- Viewer.prototype.setAddLabelState = function (state) {
- this.addingLabel = !!state
- $('#addLabel').text(state ? '停止加标签' : '添加标签')
- }
- Viewer.prototype.exportLabelData = function () {
- let data = this.labels.map(label => {
- let inv = new THREE.Matrix4().getInverse(this.model.matrixWorld)
- let posInModel = label.position.clone().applyMatrix4(inv)
- let info = {
- title: label.title,
- posInModel: convertTool.toPrecision(posInModel.toArray(), 4),
- }
- return info
- })
- $('textarea').css('display', 'block').text(JSON.stringify(data))
- console.log(data)
- return data
- }
- Viewer.prototype.getCLabel = function () { //获取最接近中心的label
- let disSquairs = this.labels.filter(e => e.elem[0].style.display == 'block').map((label) => {
- return {
- label,
- disSquair: label.pos2d.x * label.pos2d.x + label.pos2d.y * label.pos2d.y
- }
- })
- disSquairs.sort((e1, e2) => { return e1.disSquair - e2.disSquair })
- return disSquairs[0] && disSquairs[0].label
- }
- //============
- var startTime = new Date().getTime();
- function dataURLtoBlob(dataurl) {//将base64转换blob
- var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
- bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
- while (n--) {
- u8arr[n] = bstr.charCodeAt(n);
- }
- return new Blob([u8arr], { type: mime });
- }
- /*
- MeshStandardMaterial(pbr)代替Phong
- 优点 : 能量守恒、更容易调节出真实感。 metalnessMap只用到一个通道,颜色信息整合到albedo贴图里,省数据。
- 缺点:可能,mtl里的值只能用到一部分, specular用不到。 (会降低对specular的控制)
- 另外不知道大部分模型用的是哪种模式,是否使用metalnessMap。
-
- aoMap r
- roughnessMap alphaMap g
- metalnessMap b
-
- normalMap ?
- bumpMap : 黑白?
- 主要是光滑度or粗糙度(可贴图) 还有 金属性(可贴图) 还有颜色(可贴图),透明度(in颜色贴图),法线贴图or凹凸贴图
-
-
-
- 贴图的属性 rotation offset repeat (当wrapS = THREE.RepeatWrapping,wrapT = THREE.RepeatWrapping)
-
-
- */
|