ThreeJSは室内概念図の効果を徐々に実現する(レンダリング、インタラクティブ)

64192 ワード

最近プロジェクトの需要のため、ページの中で3 dの室内のレイアウトの概念図を挿入して、ゼロからthreeを学び始めます.jsの知识、以下はこの2周间の研究の结果を记录して、私も白い1枚で、足りないところ、また批判して指摘することを望みます!
最初に出会った問題は室内の地図ブロックのレンダリング効果の問題で、1つの光源を使う時、効果はいつも思うようにいかなくて、いつも光が照らせない一面は黒い影があって、それから2つの光源を使うことを考えて、両側は光を打って、レンダリングの効果はとても良いです.
var ambiColor = "#f2f2f2";
var spotLight = new THREE.SpotLight(ambiColor);
spotLight.position.set( -100, 100, -100);
scene.add(spotLight);
var spotLight2 = new THREE.SpotLight(ambiColor);
spotLight2.position.set( 100, 100, 150);
scene.add(spotLight2);

第2の問題はcubeの材質の問題で、threejsを研究する前に室内地図に関する博文を見て、実現効果が似ているため、博主のcubeの材質に対する構想を引用しました:頂面と側面は異なる材質を使って、私の第1の考えはcubeの上にplaneを加えて、cubeの元の頂面を覆うMeshLambertMaterialの材質で、しかし、この考えは後に回転を実現する際に否決された.planeの高さがcubeと重なると、上面とplaneの色が衝突し、1本の線が形成され、y軸方向が0.2より少し高くなれば、平面図では上記の問題は見えないが、カメラの視角が調整されると、すぐに問題が見え、公式文書の例を探した.MeshFaceMaterialでcubeの6つの面の色とマテリアルをカスタマイズできることがわかりました.
var yellow = [];
//    
yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
//    
yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
//    
yellow.push(new THREE.MeshBasicMaterial({color: "#F8D3A5",transparent:true,opacity:0.8}));
//    
yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
//    
yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
//    
yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
var face1Material = new THREE.MeshFaceMaterial(yellow);
var cube1Geom = new THREE.BoxGeometry(3,2,12);
var cube1 = new THREE.Mesh(cube1Geom, face1Material);

上部にはMeshBasicMaterialを使用すると、光の影響を受けずに透明度を設定でき、側面にシャドウが形成され、リアルに見えます.
第3歩はカメラの角度の回転を実現することで、これは直接持っている公式ドキュメントのケースの中の方法で、比較的に硬くて、まだ最適化しなければなりません.上下360度回転なので、地図の底面を少し回すと反ります.
<script src="libs/TrackballControls.js">script>
controls = new THREE.TrackballControls( camera );
controls.rotateSpeed = 1.0;
controls.zoomSpeed = 1.2;
controls.panSpeed = 0.8;
controls.noZoom = false;
controls.noPan = false;
controls.staticMoving = true;
controls.dynamicDampingFactor = 0.3;
function render() {
    controls.update();}

公式のjsパッケージを1つ導入するだけで実現できます.
第4歩は最も長い1つを考慮して、ユーザーのインタラクションを実現して、cubeをクリックした後に、cubeは変色することができて、ユーザーにヒントを与えることができて、このcubeはクリックされて、ネット上の多くのdemoを見て、すべて放射線の原理を使って、マウスをクリックしてスクリーンの中の点を垂直に1本の光線を発射して、もし複数のオブジェクトに触れるならば、第1のオブジェクトを取って現在クリックしたcubeです.この原理はとても簡単で、しかしcubeを変色することを実現するのは私を困らせて、それからまた多くのブログを探して、cubeを変色させることができる例を見つけて、しかしコードを私のここに移すたびに機能しなくて、いつも1つのgetHex()とset()の未定義の間違いを報告して、私はバージョンの問題だと思って、それから長い間考えて、長い間試して、やっと発見して、もとは私が材質を定義する問題で、私が定義した材質は1つの配列で、6つの面が色を変える必要がある場合、それぞれ色を変える必要がありますが、ケースではcubeの6つの面の材質の色は完全に同じなので、直接取得してから修正すればいいだけです.
function onDocumentMouseClick(event) {
    event.preventDefault();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
}
raycaster.setFromCamera(mouse, camera);
var intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
    if (INTERSECTED !== intersects[0].object) {
        if (INTERSECTED && INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6) {
            for(var i = 0; i < 6; i++){
                INTERSECTED.material[i].color.setHex(INTERSECTED.currentHex);
            }
        }
        INTERSECTED = intersects[0].object;
        if(INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6){
            for(var i = 0; i < 6; i++){
                INTERSECTED.currentHex = INTERSECTED.material[i].color.getHex();
                if(INTERSECTED.currentHex !== 16777215)
                    INTERSECTED.material[i].color.set( "#FFC965" );
            }
        }
    }
} else {
    if (INTERSECTED && INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6) {
        for(var i = 0; i < 6; i++){
            INTERSECTED.material[i].color.set(INTERSECTED.currentHex);
        }
    }
    INTERSECTED = null;
}

onmouseclickのメソッドはマウスクリックの位置を決定し、次の部分はrender()メソッドの一部です.全体的に効果の美観のために、すべてのcubeの上に直線を加えて、cubeがより明らかに見えるが、これはまた小さなトラブルを引き起こし、物体をクリックするときにmeshかどうかを判断し、クリックした直線が変色効果がないはずで、床をクリックしたときも変色効果があるはずがない.
一連の探索を経て、ついにゼロの基礎の上でいくつかのものがあって、完成品までまだ遠いですが(まだ最適化する必要があるところがたくさんあります)、しかしthreejsの学習の上の1歩を計算して、最後にコードを添付します.
span style="color:#bfa4a4;">html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Three.jstitle>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }
    style>
head>

<body>
<script type="text/javascript" src="libs/three.js">script>
<script src="libs/TrackballControls.js">script>
<script>
    var renderer, scene, camera;
    var INTERSECTED;
    var raycaster;
    var mouse;
    var controls ;
    //       
    var lineHeight = 1.75;
    //     
    var cubeHeight = 1.5;
    function init() {
        renderer = new THREE.WebGLRenderer({
            antialias: true
        });
        renderer.setClearColor(0xF1F2F7);
        renderer.setSize(window.innerWidth, window.innerHeight);
        scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xF1F2F7 );
        camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        camera.lookAt(new THREE.Vector3(20, 0, 20));
        camera.position.set(0, 40, 50);
        //      
        var ambiColor = "#f2f2f2";
        var spotLight = new THREE.SpotLight(ambiColor);
        spotLight.position.set( -100, 100, -100);
        scene.add(spotLight);
        var spotLight2 = new THREE.SpotLight(ambiColor);
        spotLight2.position.set( 100, 100, 150);
        scene.add(spotLight2);

        controls = new THREE.TrackballControls( camera );
        controls.rotateSpeed = 1.0;
        controls.zoomSpeed = 1.2;
        controls.panSpeed = 0.8;
        controls.noZoom = false;
        controls.noPan = false;
        controls.staticMoving = true;
        controls.dynamicDampingFactor = 0.3;

        raycaster = new THREE.Raycaster();
        mouse = new THREE.Vector2();
        document.body.appendChild(renderer.domElement);
        document.addEventListener('click', onDocumentMouseClick, false);
        creatCube();
        render();
    }

    function onDocumentMouseClick(event) {
        event.preventDefault();
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    }

    function creatCube() {
        //     
        var yellow = [];
        //    
        yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
        //    
        yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
        //    
        yellow.push(new THREE.MeshBasicMaterial({color: "#F8D3A5",transparent:true,opacity:0.8}));
        //    
        yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
        //    
        yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));
        //    
        yellow.push(new THREE.MeshLambertMaterial({color: "#F8D3A5"}));

        var white = [];
        white.push(new THREE.MeshLambertMaterial({color: "#fff"}));
        white.push(new THREE.MeshLambertMaterial({color: "#fff"}));
        white.push(new THREE.MeshBasicMaterial({color: "#fff"}));
        white.push(new THREE.MeshLambertMaterial({color: "#fff"}));
        white.push(new THREE.MeshLambertMaterial({color: "#fff"}));
        white.push(new THREE.MeshLambertMaterial({color: "#fff"}));

        var purple = [];
        purple.push(new THREE.MeshLambertMaterial({color: "#E3B7F7"}));
        purple.push(new THREE.MeshLambertMaterial({color: "#E3B7F7"}));
        purple.push(new THREE.MeshBasicMaterial({color: "#E3B7F7",transparent:true,opacity:0.8}));
        purple.push(new THREE.MeshLambertMaterial({color: "#E3B7F7"}));
        purple.push(new THREE.MeshLambertMaterial({color: "#E3B7F7"}));
        purple.push(new THREE.MeshLambertMaterial({color: "#E3B7F7"}));

        var orange = [];
        orange.push(new THREE.MeshLambertMaterial({color: "#FFC965"}));
        orange.push(new THREE.MeshLambertMaterial({color: "#FFC965"}));
        orange.push(new THREE.MeshBasicMaterial({color: "#FFC965",transparent:true,opacity:0.5}));
        orange.push(new THREE.MeshLambertMaterial({color: "#FFC965"}));
        orange.push(new THREE.MeshLambertMaterial({color: "#FFC965"}));
        orange.push(new THREE.MeshLambertMaterial({color: "#FFC965"}));


        //        
        var cubeBottomLeftGeometry = new THREE.BoxGeometry(16,0.5,42);
        var cubeBottomLeftMaterial =  new THREE.MeshFaceMaterial(white);
        var cubeBottomLeft = new THREE.Mesh(cubeBottomLeftGeometry,cubeBottomLeftMaterial);
        cubeBottomLeft.position.x = -10;
        cubeBottomLeft.position.y = 0;
        cubeBottomLeft.position.z = 0;
        scene.add(cubeBottomLeft);

        //        
        var cubeBottomRightGeometry = new THREE.BoxGeometry(28,0.5,16);
        var cubeBottomRightMaterial =  new THREE.MeshFaceMaterial(white);
        var cubeBottomRight = new THREE.Mesh(cubeBottomRightGeometry,cubeBottomRightMaterial);
        cubeBottomRight.position.x = 12;
        cubeBottomRight.position.y = 0;
        cubeBottomRight.position.z = 13;
        scene.add(cubeBottomRight);


        //   1   1
        var line11Material = new THREE.LineBasicMaterial({color:"#F7A540"});
        var line11Geometry = new THREE.Geometry();
        line11Geometry.vertices.push(new THREE.Vector3(-17.5,lineHeight,20.5));
        line11Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,20.5));
        var line11 = new THREE.Line(line11Geometry, line11Material);
        scene.add(line11);
        //   1   2
        var line12Material = new THREE.LineBasicMaterial({color:"#F7A540"});
        var line12Geometry = new THREE.Geometry();
        line12Geometry.vertices.push(new THREE.Vector3(-17.5,lineHeight,20.5));
        line12Geometry.vertices.push(new THREE.Vector3(-17.5,lineHeight,8.5));
        var line12 = new THREE.Line(line12Geometry, line12Material);
        scene.add(line12);
        //   1   3
        var line13Material = new THREE.LineBasicMaterial({color:"#F7A540"});
        var line13Geometry = new THREE.Geometry();
        line13Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,8.5));
        line13Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,20.5));
        var line13 = new THREE.Line(line13Geometry, line13Material);
        scene.add(line13);
        //   1   4
        var line14Material = new THREE.LineBasicMaterial({color:"#F7A540"});
        var line14Geometry = new THREE.Geometry();
        line14Geometry.vertices.push(new THREE.Vector3(-17.5,lineHeight,8.5));
        line14Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,8.5));
        var line14 = new THREE.Line(line14Geometry, line14Material);
        scene.add(line14);


        //   2   1
        var line21Material = new THREE.LineBasicMaterial({color:"#B42EF7"});
        var line21Geometry = new THREE.Geometry();
        line21Geometry.vertices.push(new THREE.Vector3(-9.5,lineHeight,20.5));
        line21Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,20.5));
        var line21 = new THREE.Line(line21Geometry, line21Material);
        scene.add(line21);
        //   2   3
        var line22Material = new THREE.LineBasicMaterial({color:"#B42EF7"});
        var line22Geometry = new THREE.Geometry();
        line22Geometry.vertices.push(new THREE.Vector3(-9.5,lineHeight,20.5));
        line22Geometry.vertices.push(new THREE.Vector3(-9.5,lineHeight,13.5));
        var line22 = new THREE.Line(line22Geometry, line22Material);
        scene.add(line22);
        //   2   2    1       
        /*var line23Material = new THREE.LineBasicMaterial({color:"#B42EF7"});
        var line23Geometry = new THREE.Geometry();
        line23Geometry.vertices.push(new THREE.Vector3(-13.7,lineHeight,15.3));
        line23Geometry.vertices.push(new THREE.Vector3(-13.7,lineHeight,22));
        var line23 = new THREE.Line(line23Geometry, line23Material);
        scene.add(line23);*/
        //   2   4
        var line24Material = new THREE.LineBasicMaterial({color:"#B42EF7"});
        var line24Geometry = new THREE.Geometry();
        line24Geometry.vertices.push(new THREE.Vector3(-9.5,lineHeight,13.5));
        line24Geometry.vertices.push(new THREE.Vector3(-14.5,lineHeight,13.5));
        var line24 = new THREE.Line(line24Geometry, line24Material);
        scene.add(line24);


        //   1
        var face1Material = new THREE.MeshFaceMaterial(yellow);
        var cube1Geom = new THREE.BoxGeometry(3,cubeHeight,12);
        var cube1 = new THREE.Mesh(cube1Geom, face1Material);
        cube1.position.x = -16;
        cube1.position.y = 1;
        cube1.position.z = 14.5;
        scene.add(cube1);

        //   2
        var face2Material = new THREE.MeshFaceMaterial(purple);
        var cube2Geom = new THREE.BoxGeometry(5,cubeHeight,7);
        var cube2 = new THREE.Mesh(cube2Geom, face2Material);
        cube2.position.x = -12;
        cube2.position.y = 1.;
        cube2.position.z = 17;
        scene.add(cube2);

    }

    function render() {
        controls.update();
        requestAnimationFrame(render);
        renderer.render(scene, camera);
        raycaster.setFromCamera(mouse, camera);
        var intersects = raycaster.intersectObjects(scene.children);
        if (intersects.length > 0) {
            if (INTERSECTED !== intersects[0].object) {
                //        mesh           
                if (INTERSECTED && INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6) {
                    for(var i = 0; i < 6; i++){
                        INTERSECTED.material[i].color.setHex(INTERSECTED.currentHex);
                    }
                }
                INTERSECTED = intersects[0].object;
                if(INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6){
                    for(var i = 0; i < 6; i++){
                        INTERSECTED.currentHex = INTERSECTED.material[i].color.getHex();
                        //                      :16777215
                        if(INTERSECTED.currentHex !== 16777215)
                            INTERSECTED.material[i].color.set( "#FFC965" );
                    }
                }
            }
        } else {
            if (INTERSECTED && INTERSECTED instanceof THREE.Mesh && INTERSECTED.material.length === 6) {
                for(var i = 0; i < 6; i++){
                    INTERSECTED.material[i].color.set(INTERSECTED.currentHex);
                }
            }
            INTERSECTED = null;
        }
    }
    init();
script>
body>

html>
オリジナル作品、転載を歓迎して、出典を注釈します.