threejs 智慧园区案例 (threejs碰撞测试)

threejs点击事件,threejs智慧园区案例

1、THREEJS 官方网址: <u>https://threejs.org/。</u> threejs 通过封装WEBGL API 实现了在网页端直接进行三维3d模型渲染。应用场景包括:小游戏,在线展厅,DIY 互动等现代互联网应用,极具发展前景。

2、官方使用案例https://threejs.org/examples/,可以直接套用。

threejs点击事件,threejs智慧园区案例

webglmaterial.png

以 <u>https://github.com/mrdoob/three.js/blob/master/examples/webgl_materials.html</u> 为例,讲解如何使用Threejs构建自己的应用:步骤一、新建html页面。

<!DOCTYPE html>
    <html lang="en">
    <head>
    <title>three.js webgl - materials</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
    <link type="text/css" rel="stylesheet" href="main.css">
    </head>
    <body>
    <div id="info">
    <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl materials
    </div>
    
    <script type="module">
    
    import * as THREE from '../build/three.module.js';  //引入threejs 主框架
    
    import Stats from './jsm/libs/stats.module.js'; //引入状态帧计数状态显示
    
    let stats;
    
    let camera, scene, renderer;
    let pointLight;
    
    const objects = [], materials = [];
    
    init();
    animate();
    
    function init() {
    
    const container = document.createElement( 'div' );//创建3d 场景所在的区域
    document.body.appendChild( container );
    
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );//设置3d场景的镜头参数,45度代表镜头的视角。
    camera.position.set( 0, 200, 800 );
    
    scene = new THREE.Scene();//创建场景对象,所有渲染都是根据该对象进行渲染。
    
    // Grid
    
    const helper = new THREE.GridHelper( 1000, 40, 0x303030, 0x303030 );//场景中的方格线,辅助视角
    helper.position.y = - 75;
    scene.add( helper );
    
    // Materials
    
    const texture = new THREE.Texture( generateTexture() );//创建纹理
    texture.needsUpdate = true;
    
    materials.push( new THREE.MeshLambertMaterial( { map: texture, transparent: true } ) );
    materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd } ) );
    materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, flatShading: true } ) );
    materials.push( new THREE.MeshNormalMaterial() );
    materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, transparent: true, blending: THREE.AdditiveBlending } ) );//设置材质参数,包括混合参数,直接影响颜色混合后的效果
    materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd } ) );
    materials.push( new THREE.MeshPhongMaterial( { color: 0xdddddd, specular: 0x009900, shininess: 30, map: texture, transparent: true } ) );//设置材质的反射、透明、高光参数,如金属材质,玻璃材质,木头材质,反射系数,高光系数,粗糙程度都是不一样的。
    materials.push( new THREE.MeshNormalMaterial( { flatShading: true } ) );
    materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } ) );
    materials.push( new THREE.MeshDepthMaterial() );
    materials.push( new THREE.MeshLambertMaterial( { color: 0x666666, emissive: 0xff0000 } ) );
    materials.push( new THREE.MeshPhongMaterial( { color: 0x000000, specular: 0x666666, emissive: 0xff0000, shininess: 10, opacity: 0.9, transparent: true } ) );
    materials.push( new THREE.MeshBasicMaterial( { map: texture, transparent: true } ) );
    
    // Spheres geometry
    
    const geometry = new THREE.SphereGeometry( 70, 32, 16 );
    
    for ( let i = 0, l = materials.length; i < l; i ++ ) {
    
    addMesh( geometry, materials[ i ] );
    
    }
    
    // Lights
    
    scene.add( new THREE.AmbientLight( 0x111111 ) );//设置漫反射光源,类似白天没有太阳直晒的房间,有暗光。产生的原有主要是环境物体多次发射后的光线。
    
    const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.125 );//方向光源,仿真太阳光,从很远的距离照射。
    
    directionalLight.position.x = Math.random() - 0.5;
    directionalLight.position.y = Math.random() - 0.5;
    directionalLight.position.z = Math.random() - 0.5;
    directionalLight.position.normalize();//位置参数,主要是控制光从哪个方向照射,类似太阳在东面,还是西面。
    
    scene.add( directionalLight );
    
    pointLight = new THREE.PointLight( 0xffffff, 1 );//点光影,仿真单个灯泡
    scene.add( pointLight );
    
    pointLight.add( new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) ) );
    
    //
    
    renderer = new THREE.WebGLRenderer( { antialias: true } );//webgl的渲染引擎
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    container.appendChild( renderer.domElement );//将3d渲染引擎绑定到html页面的div
    
    //
    
    stats = new Stats();
    container.appendChild( stats.dom );//状态显示,二维组件,与3d没有直接关系
    
    //
    
    window.addEventListener( 'resize', onWindowResize );
    
    }
    
    function addMesh( geometry, material ) {
    
    const mesh = new THREE.Mesh( geometry, material );
    
    mesh.position.x = ( objects.length % 4 ) * 200 - 400;
    mesh.position.z = Math.floor( objects.length / 4 ) * 200 - 200;
    
    mesh.rotation.x = Math.random() * 200 - 100;
    mesh.rotation.y = Math.random() * 200 - 100;
    mesh.rotation.z = Math.random() * 200 - 100;
    
    objects.push( mesh );
    
    scene.add( mesh );//所有渲染的模型,均需加入值场景对象scene内。3d引擎是通过遍历scene下的子对象,进行渲染的。
    
    }
    
    function onWindowResize() {
    
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    
    renderer.setSize( window.innerWidth, window.innerHeight );
    
    }
    
    function generateTexture() {//通过canvas 方式画出纹理,也可以直接从图像文件png加载纹理。
    
    const canvas = document.createElement( 'canvas' );
    canvas.width = 256;
    canvas.height = 256;
    
    const context = canvas.getContext( '2d' );
    const image = context.getImageData( 0, 0, 256, 256 );
    
    let x = 0, y = 0;
    
    for ( let i = 0, j = 0, l = image.data.length; i < l; i += 4, j ++ ) {
    
    x = j % 256;
    y = ( x === 0 ) ? y + 1 : y;
    
    image.data[ i ] = 255;
    image.data[ i + 1 ] = 255;
    image.data[ i + 2 ] = 255;
    image.data[ i + 3 ] = Math.floor( x ^ y );
    
    }
    
    context.putImageData( image, 0, 0 );
    
    return canvas;
    
    }
    
    //
    
    function animate() {
    
    requestAnimationFrame( animate );//这部分是关键,通过设置浏览器的动画循环调用animate函数。保障画面循环渲染。好比cpu的时钟,一直在运转。
    
    render();//场景渲染,webgl 渲染实际工作内容。
    stats.update();
    
    }
    
    function render() {
    
    const timer = 0.0001 * Date.now();
    
    camera.position.x = Math.cos( timer ) * 1000;
    camera.position.z = Math.sin( timer ) * 1000;
    
    camera.lookAt( scene.position );
    
    for ( let i = 0, l = objects.length; i < l; i ++ ) {
    
    const object = objects[ i ];
    
    object.rotation.x += 0.01;
    object.rotation.y += 0.005;
    
    }
    
    materials[ materials.length - 2 ].emissive.setHSL( 0.54, 1, 0.35 * ( 0.5 + 0.5 * Math.sin( 35 * timer ) ) );
    materials[ materials.length - 3 ].emissive.setHSL( 0.04, 1, 0.35 * ( 0.5 + 0.5 * Math.cos( 35 * timer ) ) );
    
    pointLight.position.x = Math.sin( timer * 7 ) * 300;
    pointLight.position.y = Math.cos( timer * 5 ) * 400;
    pointLight.position.z = Math.cos( timer * 3 ) * 300;
    
    renderer.render( scene, camera );//调用renderer引擎实际渲染场景scene,camera,后续另外再讲场景渲染的数学模型。
    
    }
    
    </script>
    
    </body>
    </html>


3、如何在vue中引入THREEJS步骤一、新建threejs 组件,ZeusStage.vue

threejs点击事件,threejs智慧园区案例

大画家效果图.jpg

<template>
    <div ref="container"  >

    </div>
</template>

<script>
 
import * as THREE from 'three' 

export default {
    name: 'ZeusStage',
    provide () {
        return {
        parentObj: null, // avoid "injection not found" warning
        _baseUrl: null,
        global: this.global
        }
    },
    props: {
        size: {
            type: Object, // { w, h }
            required: false,
            default: function(){
                return {
                    w:100,
                    h:100

                }
                
            }
        },
        scenejson:{
            type: Object
        },
        scene_url:{
            type:String
        }
    },
    data () {
        return {
            g_material_selected:'黄金',
            img_blend:'',
            popover_active: false,
        };
    },
    watch: {
        size(newval, oldval) { 
            if (newval != oldval) {
                this.$refs.container.style.width = this.size.w+'px';
                this.$refs.container.style.height = this.size.h+'px';

                this.$refs.container.width = this.size.w;
                this.$refs.container.height = this.size.h;

                this.$emit("resize");
                
            }

            
        } 
    },
    mounted () { 
        this.extent();
        this.container = this.$refs.container;
        this.init(); 
        this.parseScene();
    },
    methods: {
        init() { 
            var _this = this;
            var container = this.container;  
            var dom = container;
            this.dom = dom;

            this.DrawMode = false; //画布模式
  
            this.initScene();
            this.initControl();
            this.initRenderer();

            // POSTPROCESSING

            var clock = new THREE.Clock();

            var controls = this.controls;
            var scene = this.scene;
            var camera = this.camera;
            var renderer = this.renderer;

            setupEventHandlers();

            controls.addEventListener('change', render);

            animate();

            function setupEventHandlers() {
                    
                var onResize = function() {
                    if (camera instanceof THREE.OrthographicCamera) {
                        camera.left = dom.offsetWidth / -2;
                        camera.right = dom.offsetWidth / 2;
                        camera.top = dom.offsetHeight / 2;
                        camera.bottom = dom.offsetHeight / -2;
                    }

                    if (camera instanceof THREE.PerspectiveCamera) {
                        camera.aspect = dom.offsetWidth / dom.offsetHeight;
                    }

                    camera.updateProjectionMatrix(); 
                    renderer.setSize(dom.offsetWidth, dom.offsetHeight);

                    render();

                };
                //window.addEventListener('resize', onResize, false);
                _this.$on("resize", onResize );
                onResize();
            }

            // 
            

            function animate() {

                requestAnimationFrame(animate);

                controls.update();

                render();
            }

            function render() {

                if (renderer) {
                    renderer.clear();
                    _this.setLightPosition();

                    var delta = clock.getDelta(); 

                    updateDelta(delta, camera); 
                    renderer.render(scene, camera);
                }
            }

            function updateDelta(delta,camera) {
                if (scene) {
                    scene.traverse(function(_obj) {
                        if (_obj.updateDelta) {
                            _obj.updateDelta(delta,camera);
                        } 

                    });
                }

            } 
        },

        initControl() {
            var camera = this.camera;
            var dom = this.dom;  
            var controls = new ZEUS.THREE_EXT.OrbitControls(camera, dom);

            this.controls = controls;

            controls.enabled = true;

            controls.rotateSpeed = 1.0;
            controls.zoomSpeed = 2.0;
            controls.panSpeed = 0.0003;
            controls.minDistance = 15;
            controls.maxDistance = 100;

            controls.noZoom = false;
            controls.noPan = false;
            controls.maxPan = 10;
            controls.autoRotate = true;
            controls.autoRotateSpeed = -2.5; //TODO
    
            controls.enableDamping = true;
            controls.dampingFactor = 0.1;

            controls.keys = [65, 83, 68];

             

            hoverDelay({
                el:dom, 
                hoverDuring: 200,
                outDuring: 500,
                hoverEvent: function() {
                    controls.autoRotate = false;
                    //_this.setAutoRotate(false);
                },
                outEvent: function() {
                    //controls.autoRotate = true;
                    //_this.setAutoRotate(true);
                }
            })

            function hoverDelay(option){
                

                var el = option.el;
                var timer = null;

                var onMouseOver = function(){
                    if(timer){
                        clearTimeout(timer);
                    }
                    timer = setTimeout(() => {
                        if(option.hoverEvent){
                            option.hoverEvent();
                        }

                    },option.hoverDuring);

                }
                
                var onMouseOut = function (){
                    if(timer){
                        clearTimeout(timer);
                    }
                    timer = setTimeout(() => {
                        if(option.outEvent){
                            option.outEvent();
                        }
                    },option.outDuring);

                }

                el.addEventListener("mouseover",onMouseOver);
                el.addEventListener("mouseout",onMouseOut);

                el.addEventListener("touchstart",onMouseOver);
                el.addEventListener("touchend",onMouseOut)

            }

        },

        initScene() {   
            this.camera = new THREE.PerspectiveCamera(45, 1, 1, 100000);

            this.scene = new THREE.Scene();
            this.scene.name = 'Scene';  
            this.initLight(); 

            this.box = null; 
        },  
        initLight() { 
            // LIGHTS   
            var key_light = new THREE.DirectionalLight(0xffffff, 1);//new THREE.SpotLight(0xffffff, 1.4); //FFFFE6
            key_light.castShadow = true;
            key_light.position.x = 1;
            key_light.position.y = 1;
            key_light.position.z = 1;
            this.key_light = key_light;
            this.scene.add(this.key_light); 
 
        },
        initRenderer() {
            var clearColor = 0x00000000;

            var createRenderer = function(type, antialias) { 
                var renderer = new THREE[type]({
                    antialias: antialias,
                    alpha:true 
                });
                renderer.setClearColor(clearColor,0);
                renderer.setPixelRatio(window.devicePixelRatio);
                renderer.autoClear = false;
                renderer.autoUpdateScene = false; 

                renderer.gammaInput = true;
                renderer.gammaOutput = true;

                renderer.physicallyBasedShading = true;

                return renderer;

            };

            var renderer = createRenderer('WebGLRenderer', true);
            renderer.autoClear = false;
            this.renderer = renderer;
            this.dom.appendChild(renderer.domElement);

            renderer.setSize(this.size.w, this.size.h);
        },

        initAxesHelper(){
            var helper = new THREE.AxesHelper(200);
            this.scene.add( helper );

        },
          
        addObject(object) {  
            this.scene.add(object);   
        },
        moveObject(object, parent, before) { 
            if (parent === undefined) {
                parent = this.scene;
            }

            parent.add(object);

            // sort children array 
            if (before !== undefined) {

                var index = parent.children.indexOf(before);
                parent.children.splice(index, 0, object);
                parent.children.pop();

            }
        },

        nameObject(object, name) {
            object.name = name;
        },

        getObjectByName(name) {
            return this.scene.getObjectByName(name);
        },

        removeObject(object) {
            if (object.parent === undefined) return; // avoid deleting the camera or scene
            object.parent.remove(object);
        },

        setObjectMaterial(material, object_name) {
            var object = this.getObjectByName(object_name);

            var has_changed = false;

            if (object) {
                object.traverse(function(_obj) {
                    if (_obj.material != material) {
                        has_changed = true;

                        if (_obj.material instanceof THREE.MultiMaterial) {
                            var _material = new THREE.MultiMaterial(
                                [material.clone(), material]
                            );

                            for (var i = 0; i < _material.materials.length; i++) {
                                _material.materials[i].shading = _obj.material.materials[i].shading;
                            }

                            _obj.material = _material;
                        } else {
                            _obj.material = material;
                        }
                    }

                });
            }

            if (has_changed) { 
                this.$emit('materialChanged');
            }

        },

        setObjectPosition(position, object_name) {
            var object = this.getObjectByName(object_name);
            object.position.copy(position);
        },
        setLightPosition() {

            var _this = this;

            var camera = _this.camera;

            var position = new THREE.Vector3().copy(camera.position);

            var radius = position.length();

            var camera_py = new THREE.Vector3().copy(camera.up);
            var camera_pz = new THREE.Vector3(0, 0, 1);
            var camera_px = new THREE.Vector3().crossVectors(camera_py, camera_pz);

            camera_py.applyQuaternion(camera.quaternion);
            camera_pz.applyQuaternion(camera.quaternion);
            camera_px.applyQuaternion(camera.quaternion);

            var key_light = _this.key_light;

            var fill_light = _this.fill_light;

            var back_light = _this.back_light;

            var bottom_light = _this.bottom_light;

        
            key_light.position.copy(camera_pz);
            key_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_py, -Math.PI / 6));//-Math.PI / 4
            key_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_pz, -Math.PI / 6));//-Math.PI / 4
            key_light.position.multiplyScalar(radius);

            fill_light.position.copy(camera_pz);
            fill_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_py, Math.PI / 4)); //Math.PI / 4
            fill_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_pz, Math.PI / 4));//Math.PI / 4
            fill_light.position.multiplyScalar(radius);

            back_light.position.copy(camera_pz); 
            back_light.position.applyQuaternion(new THREE.Quaternion().setFromAxisAngle(camera_px, -Math.PI / 6));
            back_light.position.multiplyScalar(radius);

            bottom_light.position.copy(camera_py).multiplyScalar(-radius);

        },

        async initTextureCube() {
            var base_url = this.scene_url + "textures/";
            var r = base_url + "cube/2021/"; 
            await this.setTextureCube(r); 
        },

        async setTextureCube(url) {
            var urls = [url + "px.jpg", url + "nx.jpg",
                url + "py.jpg", url + "ny.jpg",
                url + "pz.jpg", url + "nz.jpg"
            ];
            this.textureCube = await this.loadTextureCube(urls);

            this.textureCube.format = THREE.RGBFormat;
            this.textureCube.mapping = THREE.CubeTexture;
        },

        async setTextureCube_diamond(url) {
            var urls = [url + "ny.jpg", url + "ny.jpg",
                url + "ny.jpg", url + "ny.jpg",
                url + "ny.jpg", url + "ny.jpg"
            ];

            this.textureCube_diamond = await this.loadTextureCube(urls);
            this.textureCube.mapping = THREE.CubeRefractionMapping;
        },
        getThreeMaterial(material_name) {
            var _this = this;
            if (THREE) {
                _this.Materials = _this.Materials || {};

                var material = _this.Materials[material_name];

                if (material instanceof THREE.Material) {
                    return material;

                } else{
                    var option = getMaterialConfig(material_name);
                    if (option) {
                        material = new THREE.MeshPhongMaterial(option);
                        _this.Materials[material_name] = material;
                    }
                }

                return material;

                
            }

            function getMaterialConfig(_material_name) {
                var textureCube = _this.textureCube || null;

                var textureCube_diamond = _this.textureCube_diamond || null;

                var config = global.ConfigMaterials;

                var metal_materials = config.metal_materials;

                for (let i = 0, l = metal_materials.length; i < l; i++) {

                    let material = metal_materials[i];

                    let material_name = material.name;

                    if (_material_name == material_name) {

                        return {
                            color: new THREE.Color().setStyle(material.color),
                            specular: new THREE.Color().setStyle(material.specular),
                            shininess: parseFloat(material.shininess),
                            envMap: textureCube,
                            combine: THREE.MultiplyOperation,
                            reflectivity: material.reflectivity
                        };

                    }

                }

                var diamond_materials = config.diamond_materials;

                for (let i = 0, l = diamond_materials.length; i < l; i++) {

                    let material = diamond_materials[i];

                    let material_name = material.name;

                    if (material_name == _material_name) {

                        var m = {};

                        m.envMap = textureCube_diamond;

                        if (material.envMap == false) {

                            m.envMap = null;

                        }

                        if (material.color != undefined) {
                            m.color = new THREE.Color().setStyle(material.color);
                        }

                        if (material.emissive != undefined) {
                            m.emissive = new THREE.Color().setStyle(material.emissive);
                        }
                        if (material.ambient != undefined) {
                            m.ambient = new THREE.Color().setStyle(material.ambient);
                        }
                        if (material.specular != undefined) {
                            m.specular = new THREE.Color().setStyle(material.specular);
                        }

                        if (material.shininess != undefined) {
                            m.shininess = parseFloat(material.shininess);

                        }

                        if (material.reflectivity != undefined) {
                            m.reflectivity = parseFloat(material.reflectivity);
                        }

                        if (material.opacity != undefined) {
                            m.opacity = parseFloat(material.opacity);

                        }

                        if (material.transparent != undefined) {
                            m.transparent = material.transparent;

                        }

                        if (material.refractionRatio != undefined)
                            m.refractionRatio = parseFloat(material.refractionRatio);
                        m.combine = THREE.MultiplyOperation;

                        return m;

                    }

                }

            }

        },
        //diy parts
        async parseScene( ){ 
            this.rundata = {};
            this.parseCamera();
 
        
            await this.initTextureCube();
            await this.parseMainMaterial();
            await this.parsePart();
             
            this.$root.$emit("sceneLoaded");

        },
        parseCamera() {
            var _this = this; 
            var camera = this.scenejson.camera;
            
            if (camera.distance != undefined) {
                var distance = parseFloat(camera.distance);

                var position0 = new THREE.Vector3(0, 0, distance);

                position0.applyAxisAngle(new THREE.Vector3(1, 0, 0), -15 * Math.PI / 180);

                this.camera.position.copy(position0);

                this.controls.position0 = position0.clone();

            }

            if (camera.lookAt != undefined) {

                var target0 = new THREE.Vector3().fromArray(camera.lookAt);
                this.camera.lookAt(target0);

                this.controls.target0.copy(target0);

                this.controls.target.copy(target0);
            }

            if (camera['min-distance'] != undefined) {
                var minDistance = parseFloat(camera['min-distance']);

                this.controls.minDistance = minDistance;

            }

            if (camera['max-distance'] != undefined) {
                var maxDistance = parseFloat(camera['max-distance']);

                this.controls.maxDistance = maxDistance;

            }

            if (camera.rotation != undefined) {
                var rotation = new THREE.Vector3().fromArray(camera.rotation);

                rotation.x = rotation.x * Math.PI / 180;
                rotation.y = rotation.y * Math.PI / 180;
                rotation.z = rotation.z * Math.PI / 180;

                this.controls.rotation0 = rotation;

                this.controls.rotateLeft(rotation.y);

                this.controls.rotateUp(rotation.x);
            } 
            _this.$emit('cameraChanged');

        },
        flyto:function(option){ 
            var _distance = option.distance;
            var _rotation = option.rotation;

            this.controls.reset();
            
            if (_distance != undefined) {
                var distance = parseFloat(_distance);
                var position0 = new THREE.Vector3(0, 0, distance);
                this.camera.position.copy(position0); 
            }

            if (_rotation != undefined) {
                var rotation = new THREE.Vector3().fromArray(_rotation); 
                rotation.x = rotation.x * Math.PI / 180;
                rotation.y = rotation.y * Math.PI / 180;
                rotation.z = rotation.z * Math.PI / 180;
                
                this.controls.rotateLeft(rotation.y); 
                this.controls.rotateUp(rotation.x);
            } 

            this.controls.update();

        },
        controlsPosSave(){ 
            //var target0 = this.controls.target.clone();
            var position0 = this.controls.object.position.clone();
            var zoom0 = this.controls.object.zoom;

            return {position0:position0, zoom0: zoom0};
        },
        controlsPosReset(option){
            this.controls.object.position.copy(option.position0);
            this.controls.object.zoom = option.zoom0;

            this.controls.update();

        },
        
        async parseMainMaterial( ) { 
            //var _this = this;
            var rundata = this.rundata || {};
            var materials = this.scenejson.materials;

            rundata.materials = rundata.materials || {};
            rundata.material_selected = "白金";

            for(var i=0; i<materials.length; i++){ 
                var _m = materials[i]; 
                rundata.materials[_m.name] = _m;
            }
    
            rundata.material_selected = materials[0]["name"];

        },
        parseMaterial(_diy) { 
            //var _this = this;
            var rundata = this.rundata || {};  
            rundata.materials = rundata.materials || {};

            rundata.materials_diy = rundata.materials_diy || {};

            rundata.materials_diy[_diy.name] = _diy; 

        },
        async parsePart() {
            var geometries = this.scenejson.geometries;

            await this.parseGeometry(geometries);
            
        },
        async parseGeometry(geometries, group){
            var _this = this;
            var rundata = this.rundata;
            var parts = rundata.parts || [];
            var scene_url = this.scene_url;
            
            group = group || this.scene;

            for (var i = 0, l = geometries.length; i < l; i++) {

                var geometry = geometries[i]; 
                var option = {
                    name: geometry.name,
                    url: scene_url+geometry.url,
                    position: geometry.position || [],
                    rotation: geometry.rotation || [],
                    scale: geometry.scale || [],
                    bumpMap: geometry.bumpMap || ''
                };
                var _geometry = await this.loadMesh(option);

                onLoad(_geometry, option);
            }

            rundata.parts = parts; 

            

            function onLoad(_geometry, option){
                if (_geometry.type=="BufferGeometry") {
                    var _geometry1 = new THREE.Geometry();
                    _geometry1 = _geometry1.fromBufferGeometry(_geometry);
                    _geometry = {};
                    _geometry = _geometry1;
                }
                
                var smooth_angle = 85;
                ZEUS.THREE_EXT.SoftenGeometryNormal(_geometry, smooth_angle, true);
                _geometry.computeBoundingBox();
                
                var material = _this.getMaterial(option.name);

                ZEUS.THREE_EXT.UVWrap(_geometry);
                let scale = 23;//46;//25;//50;
                let userdata = _geometry.userdata;
                let w =  userdata.map_size.x * scale;
                let h =  userdata.map_size.y * scale; 
                
                var max_w = 2048;
                if(w>max_w|| h>max_w){
                    var scaleX = w /max_w;
                    var scaleY = h /max_w;
                    var _scale = scaleX>scaleY?scaleX:scaleY;
                    w = Math.floor(w/_scale);
                    h = Math.floor(h/_scale); 
                    scale = scale / _scale;
                }
                userdata.map_size.scale = scale;
                
                let canvas_texture = new ZEUS.THREE_EXT.CanvasTexture({
                    width: w.toFixed(0),
                    height: h.toFixed(0),
                    bg_color: rundata.materials[rundata.material_selected].color
                });
                
                //_this.dom.appendChild(canvas_texture.canvas); 
                material.canvas_texture = canvas_texture;
                
                material.map = canvas_texture.canvas_texture; 
                material.map.minFilter = THREE.LinearFilter;
                material.map.generateMipmaps = false; 
                

                material.bumpMap = canvas_texture.canvas_texture;
                if(option.bumpMap!=''){
                    var mapHeight = new THREE.TextureLoader().load( option.bumpMap );
                    material.bumpMap = mapHeight;
                }
                if(option.bumpScale!=undefined){
                    material.bumpScale = option.bumpScale;
                }
                
                _geometry.uvsNeedsUpdate = true;

                var mesh = new THREE.Mesh(_geometry, material);

                mesh.castShadow = true;
                mesh.receiveShadow = true;

                if(option.name){
                    _this.nameObject(mesh, option.name); 
                }
                if (option['position'].length > 0) {
                    var position = option['position'];
                    position = new THREE.Vector3().fromArray(position);
                    mesh.position.copy(position);
                }

                if (option['rotation'].length > 0) {
                    var rotation = option['rotation'];
                    rotation = new THREE.Vector3().fromArray(rotation).multiplyScalar(Math.PI / 180);
                    mesh.rotateX(rotation.x);
                    mesh.rotateY(rotation.y);
                    mesh.rotateZ(rotation.z);
                }

                if (option['scale'].length > 0) {
                    let _scale = option['scale'];
                    _scale = new THREE.Vector3().fromArray(_scale);
                    mesh.scale.x = _scale.x;
                    mesh.scale.y = _scale.y;
                    mesh.scale.z = _scale.z;
                }

                mesh.userData.animate_enable = option['animate_enable'] || false;   
                parts.push(mesh); 
                group.add(mesh); 
            }

        },
         
        async loadMesh(option){
            
            return new Promise(function(resolve,reject){
                var loader = new ZEUS.THREE_EXT.MeshLoader();
                var url = option.url;
                var onLoad = function(_geometry){
                    resolve(_geometry);
                };
                var onProgress = null;
                var onError = reject;
                loader.load(url, onLoad, onProgress, onError);

            });

        },
        async loadImage(src){

            return new Promise(function(resolve,reject){
                var img = new Image();     
                img.onload = function(){ 
                    resolve(this);
                }; 
                img.onerror = reject; 
                img.src = src;  
                
            });

        },

        async imagedata_to_image(img_data, rect) {
            var canvas = document.createElement('canvas');
            var ctx = canvas.getContext('2d');
            canvas.width = img_data.width; 
            canvas.height = img_data.height; 
            ctx.putImageData(img_data, 0, 0);

            let _img_data = ctx.getImageData(rect.left, rect.top, rect.width, rect.height); 

            var  data = _img_data.data, iLen = data.length ;
            
            
            for (var i = 0; i < iLen; i += 4) {
                if(data[i+3]==0){
                    data[i] = 255;
                    data[i+1] = 255;
                    data[i+2] = 255;
                    data[i+3] = 255;
                } 
            }

            var _canvas = document.createElement('canvas');
            var _ctx = _canvas.getContext('2d');
            _canvas.width = rect.width;
            _canvas.height = rect.height; 
            _ctx.putImageData(_img_data, 0, 0);

            //var image = new Image();
            let url = _canvas.toDataURL('image/png'); 

            let image = await this.loadImage(url);
            return image;
        },

 
        async loadTextureCube(urls){
            return new Promise(function(resolve,reject){
                var loader = new THREE.CubeTextureLoader();  
                var onLoad = function(texture){ 
                    resolve(texture);
                }
                loader.load(urls,onLoad ,null, reject); 
                
            }); 
        },
           
        //设置材质名
        setMaterial(name){
            var rundata = this.rundata || {};
            rundata.material_selected = name;
            var parts = rundata.parts || [];
 
            for(var i=0; i<parts.length; i++){
                var mesh = parts[i]; 
                var m = mesh.material;
                if(m==undefined){
                    continue;
                }
                if(m.name!=name){
                    var _m = rundata.materials[rundata.material_selected];
                    m.color = new THREE.Color(_m.color);
                    m.name = _m.name;
                    m.canvas_texture.setBgcolor(_m.color);  
                }
            } 
        },
        getMaterialSelected(){
            var rundata = this.rundata || {};
            return rundata.material_selected || "白金";

        },

        onClickMaterial(name){
            this.$parent.$emit('onClickMaterial', name ); 

        }, 
        getMaterial(/*mesh_name*/){
            var rundata = this.rundata || {};  
            rundata.materials = rundata.materials || {};
    
            var _m = rundata.materials[rundata.material_selected]; 
            
             

            var material = new THREE.MeshPhysicalMaterial({
                name: _m.name,
                color: _m.color, 
                reflectivity: 0.99, 
                metalness: 1,
                roughness: 0.01,  
                envMap: this.textureCube,
                //envMapIntensity:1.5, 
                bumpScale: 0.1,
                  
            });
            return material;
        },
 
           
        clearObjects() {
            var objects = this.scene.children;
            while (objects.length > 0) {
                this.removeObject(objects[0]);
            }
        },

        clear() {
            this.clearObjects();
        },
        toDataURL() {
            if (this.renderer.domElement.toDataURL) {
                return this.renderer.domElement.toDataURL('image/png');

            } else {
                return "";
            }
        } 
  
    }
}
</script>

步骤二、调用ZeusStage.vue组件

<template>
  <div id="app"> 
        
    <div class="container " style="background-image:url(images/background-3d.png)">
        <ZeusStage ref="zeus_stage"  :size="size" :scenejson="scenejson" :scene_url="scene_url"></ZeusStage>
    </div>
  </div>
</template>

<script>

import ZeusStage from './components/ZeusStage.vue' 

export default {
    name: 'App',
    components: {
       ZeusStage 
    },
    mounted(){
        var _this = this;

        
        function onresize(){
            _this.size = {
                w: window.innerWidth -1,
                h: window.innerHeight -1

            };

            _this.$set(_this.size, 'w',_this.size.w);
            _this.$set(_this.size, 'h',_this.size.h)

        }

        window.onresize = onresize;

        onresize(); 
    },
    data(){
        return {
            isActive: true,
            background:'images/bk.png',
            size: {
                w: 100,
                h: 100
            },
           scenejson:{
                camera:{
                    distance: 80,
                    rotation:[0,0,0],
                    "min-distance": 70,
                    "max-distance": 90
                },
                materials:[  
                    {
                        name:'玫瑰金',
                        color:'#fed9d1', //'#feded1'
                    },
                    {
                        name:'白金',
                        color:'#f3eeea'
                    },
                    {
                        name:'黄金',
                        color:'#ffefc3'
                    }, 
                    {
                        name:'925银镀金',
                        color:'#f3eeea'
                    },
                   
                ],
     
                geometries:[
                   
                    {
                        name:"circle_small",
                        url:"models/circle_small.zip",

                        position:[0,7.8,0],
                        rotation:[-90,0,0],

                    },
                    {
                        name:"circle_big",
                        url:"models/circle_big.zip",

                        position:[0,9.8,0],
                        rotation:[-90,0,0],

                    },
                    {
                        name:"chain",
                        url:"models/chain.zip",
                        position:[0,0,0],
                        rotation:[90,0,0],
                    }
                 
                ]

            },
            scene_url:"",//"./public/",
       }
    },
    methods:{
        

    }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50; 
  height: 100%;
  width:100%;
  margin:0px;
  padding:0px;
}

.container{ 
    float: left;
    width: 100%;
    margin: 0px;
    position: absolute;
    background-repeat: repeat; 
    background-size: 320px;
}
 

</style>


0人点赞

THREEJS web3d