【问题标题】:Mapping image (Frontside-Backside) onto a sphere in three js将图像(Frontside-Backside)映射到三个js中的球体
【发布时间】:2018-07-09 17:35:28
【问题描述】:

我有一个关于三个 JS 的问题。

小提琴https://jsfiddle.net/syildiz/fk8thLsq/17/

我想创建一个跟随鼠标移动的眼睛。我上传的图像同时在背景中可见,并且图像连接处有一条白线。

在示例中,我在正面和背面添加了我要使用的图片。我想在前面使用图像,在后面,图像(或颜色)在后面,在前面。我也想去掉白线,怎么办?

Frontside Image https://image.ibb.co/mmsJ7J/logo_front.png

Backside Image https://image.ibb.co/bE8i7J/logo_back.png (or color)

我对 Three JS 还是很陌生,如果你能在这件事上帮助我,我将不胜感激。

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    您必须为对象指定两种材质,一种用于正面,一种用于背面。然后需要设置每个面的materialIndex,这样面就知道用什么材质了。

    // use material array to apply multiple materials
    var material = [
      new THREE.MeshBasicMaterial({
        map: new THREE.TextureLoader().load( "https://image.ibb.co/mmsJ7J/logo_front.png")
      }),
      new THREE.MeshBasicMaterial({
        map: new THREE.TextureLoader().load( "https://image.ibb.co/bE8i7J/logo_back.png")
      })
    ];
    
    // in your faces loop, set materialIndex according to front or back side of geometry
    if (v1.z < 0)
        faces[i].materialIndex = 1;
    
    // after loop, set groupsNeedUpdate -> "Set to true if a face3 materialIndex has been updated."
    geometry.groupsNeedUpdate = true;
    

    关于白线:这是因为您位于纹理的最边缘(分别是圆的不透明边缘)。我添加了一些偏移,所以纹理会稍微重叠。

    var max = geometry.boundingBox.max.clone().add(new THREE.Vector3(1,1,1)),
        min = geometry.boundingBox.min.clone().add(new THREE.Vector3(-1,-1,-1));
    
    // If the radius of the sphere is smaller, you should also set a smaller offset.
    // in this example it's 1:60, which is ok.
    

    这是一个 sn-p(或查看您更新的 jsFiddle:https://jsfiddle.net/fk8thLsq/36/

    //Setup:
    
    var container = document.querySelector('#container');
    
    
    var renderer = new THREE.WebGLRenderer({alpha: true});
    var WIDTH = window.innerWidth;
    var HEIGHT = window.innerHeight;
    renderer.setSize(WIDTH, HEIGHT);
    
    var VIEW_ANGLE = 40;
    var ASPECT = WIDTH / HEIGHT;
    var NEAR = 0.1;
    var FAR = 1000;
    
    var camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
    camera.position.set(0, 0, 50);
    
    var scene = new THREE.Scene();
    scene.background = null;
    scene.add(camera);
    
    container.appendChild(renderer.domElement);
    
    var RADIUS = 200;
    var SEGMENTS = 50;
    var RINGS = 50;
    
    
    var group = new THREE.Group();
    scene.add(group);
    
    var material = [
    	new THREE.MeshBasicMaterial({
        map: new THREE.TextureLoader().load( "https://image.ibb.co/mmsJ7J/logo_front.png" ),
        overdraw: 0
    	}),
    	new THREE.MeshBasicMaterial({
        map: new THREE.TextureLoader().load( "https://image.ibb.co/bE8i7J/logo_back.png" ),
        overdraw: 0
    	})
    ];
    
    scene.add(new THREE.AmbientLight(0xffffff, 0.2));
    
    var light = new THREE.PointLight(0xffffff, 0.2);
    camera.add(light);
    
    var geometry = new THREE.SphereGeometry(60, 64, 32);
    
    geometry.computeBoundingBox();
    
    var max = geometry.boundingBox.max.clone().add(new THREE.Vector3(1,1,1)),
        min = geometry.boundingBox.min.clone().add(new THREE.Vector3(-1,-1,-1));
        
    var offset = new THREE.Vector2(0 - min.x, 0 - min.y);
    var range = new THREE.Vector2(max.x - min.x, max.y - min.y);
    var faces = geometry.faces;
    
    geometry.faceVertexUvs[0] = [];
    
    for (var i = 0; i < faces.length; i++) {
    
        var v1 = geometry.vertices[faces[i].a],
            v2 = geometry.vertices[faces[i].b],
            v3 = geometry.vertices[faces[i].c];
            
        if (v1.z < 0)
        		faces[i].materialIndex = 1;
    
        geometry.faceVertexUvs[0].push([
            new THREE.Vector2((v1.x + offset.x) / range.x, (v1.y + offset.y) / range.y),
            new THREE.Vector2((v2.x + offset.x) / range.x, (v2.y + offset.y) / range.y),
            new THREE.Vector2((v3.x + offset.x) / range.x, (v3.y + offset.y) / range.y)
        ]);
    }
    
    geometry.groupsNeedUpdate = true;
    geometry.uvsNeedUpdate = true;
    
    var mesh = new THREE.Mesh(geometry, material);
    
    group.add(mesh);
    group.position.z = -270;
    
    var pointLight = new THREE.PointLight(0xFFFFFF);
    pointLight.position.x = -100;
    pointLight.position.y = 0;
    pointLight.position.z = 200;
    
    scene.add(pointLight);
    
    
    function update() {
        renderer.render(scene, camera);
        requestAnimationFrame(update);
    }
    
    requestAnimationFrame(update);
    
    function animationBuilder(direction) {
        return function animateRotate() {
            switch (direction) {
                case 'up':
                    group.rotation.x -= 0.2;
                    break;
                case 'down':
                    group.rotation.x += 0.2;
                    break;
                case 'left':
                    group.rotation.y -= 0.2;
                    break;
                case 'right':
                    group.rotation.y += 0.2;
                    break;
                default:
                    break;
            }
        };
    }
    
    var animateDirection = {
        up: animationBuilder('up'),
        down: animationBuilder('down'),
        left: animationBuilder('left'),
        right: animationBuilder('right')
    };
    
    function checkKey(e) {
        e = e || window.event;
        e.preventDefault();
        if (e.keyCode == '38') {
            animateDirection.up();
        } else if (e.keyCode == '40') {
            animateDirection.down();
        } else if (e.keyCode == '37') {
            animateDirection.left();
        } else if (e.keyCode == '39') {
            animateDirection.right();
        }
    }
    
    document.onkeydown = checkKey;
    
    var lastMove = [window.innerWidth / 2, window.innerHeight / 2];
    
    function rotateOnMouseMove(e) {
        e = e || window.event;
    
        var moveX = e.clientX - lastMove[0];
        var moveY = e.clientY - lastMove[1];
    
        group.rotation.y += moveX * .004;
        group.rotation.x += moveY * .004;
    
        lastMove[0] = e.clientX;
        lastMove[1] = e.clientY;
    }
    
    document.addEventListener('mousemove', rotateOnMouseMove);
    body{margin:0;background:#ddd;}
    .logo{position:absolute;top:10px;width:100px;height:100px;background-size:100% auto;background-repeat:no-repeat;}
    .front{left:10px;background-image:url("https://image.ibb.co/mmsJ7J/logo_front.png")}
    .back{left:120px;background-image:url("https://image.ibb.co/bE8i7J/logo_back.png")}
    <div class="logo front"></div>
    <div class="logo back"></div>
    <div id="container" width="100vw" height="100vh"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/94/three.min.js"></script>

    您会注意到两种材料之间仍然存在接缝。也许您应该为纹理使用纯色,并通过相应地设置材质属性来实现轻微的镜面反射行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      • 2019-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多