Three.js 将渲染的 STL 文件放置在屏幕中央

问题描述 投票:0回答:1

我有一个来自 Thingiverse 的渲染 STL 文件,通过 Three.js 使用 THREE.STLLoader() 加载源文件。我的问题是我不知道如何将其放置在屏幕中心,只能通过调整我正在使用事件触摸坐标修改的旋转属性来实现。当我在屏幕上移动手指时,我试图让对象位于屏幕中心并从中心旋转。

这就是我目前所拥有的,任何帮助将不胜感激:

var container, stats;

var camera, scene, renderer;
var stlMesh;

var mesh, geometry;

var loader;

var directionalLight;

var mouseX = 0;
var mouseY = 0;
var zoom = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

// Ejecta; Added for touch controls:
document.addEventListener('touchmove', onDocumentTouchMove, false);

function init() {
    camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.2, 100);
    scene = new THREE.Scene();

    scene.add(camera);

    // light
    var dirLight = new THREE.DirectionalLight(0xffffff);
    dirLight.position.set(200, 200, 1000).normalize();

    scene.add(dirLight);

    // STL
    var loader = new THREE.STLLoader();
    loader.load(window.filePath, function(geometry) {
        var material = new THREE.MeshPhongMaterial({
            color: 0xffff00,
            specular: 0x111111,
            shininess: 200
        });
        stlMesh = new THREE.Mesh(geometry, material);

        stlMesh.position.set(0, -0.25, 0.6);

        stlMesh.rotation.set(0, -Math.PI / 2, 0);
        stlMesh.scale.set(0.5, 0.5, 0.5);
        stlMesh.castShadow = true;
        stlMesh.receiveShadow = true;

        scene.add(stlMesh);
    });

    // renderer
    renderer = new THREE.WebGLRenderer({
        canvas: document.getElementById('canvas'),
        alpha: true
    });
    renderer.setClearColor(0x000000, 0); // the default
    renderer.setSize(window.innerWidth, window.innerHeight);
    container = document.createElement('div');
    document.body.appendChild(container);
    container.appendChild(renderer.domElement);

    window.addEventListener('resize', onWindowResize, false);
}

function getCentroid(mesh) {
    mesh.geometry.computeBoundingBox();
    var boundingBox = mesh.geometry.boundingBox;

    var size = boundingBox.size();
    console.log(size.x, size.y, size.z);

    var x0 = boundingBox.min.x;
    var x1 = boundingBox.max.x;
    var y0 = boundingBox.min.y;
    var y1 = boundingBox.max.y;
    var z0 = boundingBox.min.z;
    var z1 = boundingBox.max.z;

    var bWidth = (x0 > x1) ? x0 - x1 : x1 - x0;
    var bHeight = (y0 > y1) ? y0 - y1 : y1 - y0;
    var bDepth = (z0 > z1) ? z0 - z1 : z1 - z0;

    var centroidX = x0 + (bWidth / 2) + mesh.position.x;
    var centroidY = y0 + (bHeight / 2) + mesh.position.y;
    var centroidZ = z0 + (bDepth / 2) + mesh.position.z;

    return mesh.geometry.centroid = {
        x: centroidX,
        y: centroidY,
        z: centroidZ
    };
}

function onWindowResize() {
    windowHalfX = window.innerWidth / 2;
    windowHalfY = window.innerHeight / 2;

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
}

// Ejecta; Added for touch controls
function onDocumentTouchMove(event) {
    //mouseX = ( event.touches[0].clientX - windowHalfX ) * 4;
    //mouseY = ( event.touches[0].clientY - windowHalfY ) * 4;
    //mouseX = event.touches[0].clientX-180
    //mouseY = event.touches[0].clientY-180

    if (event.touches.length == 1) {
        // Roation Action
        mouseX = degInRad(event.touches[0].clientX)
        mouseY = degInRad(event.touches[0].clientY)
    } else if (event.touches.length == 2) {
        positionY1 = event.touches[0].clientY
        positionY2 = event.touches[1].clientY
        if (positionY2 > positionY1) {
            t1 = positionY1
            positionY1 = positionY2
            positionY2 = t1
        }

        zoom = (positionY1 - positionY2) / window.innerHeight
        zoom = zoom > 0.9 ? 0.9 : zoom
    }
}

function animate() {
    requestAnimationFrame(animate);
    render();
}

function degInRad(deg) {
    return deg * Math.PI / 180;
}

function render() {
    var timer = -0.0002 * Date.now();
    // OLD
    //camera.position.x += ( mouseX - camera.position.x ) * .05;
    //camera.position.y += ( - mouseY - camera.position.y ) * .05;

    //camera.lookAt(stlMesh.position);
    //scene.rotation.copy( camera.rotation );

    // NEW
    stlMesh.rotation.y = mouseX;
    stlMesh.rotation.x = mouseY;
    //stlMesh.rotation.y = 4.790928796724434;
    //stlMesh.rotation.x = 3.3073989325292543;
    //stlMesh.position.z = camera.position.z*zoom
    //console.log(stlMesh.position.x, stlMesh.position.y)
    //console.log("Z: "+stlMesh.position.z)

    renderer.render(scene, camera);
}
javascript three.js
1个回答
6
投票

在阅读 Three.js 源代码后,我似乎找到了答案,关键是在创建网格之前将几何体“居中”。 这是我的新 THREE.STLoader();加载方式:

// STL
var loader = new THREE.STLLoader();
loader.load(window.filePath, function ( geometry ) {
    geometry.center()
    var material = new THREE.MeshLambertMaterial({color: 0x55B663});
    stlMesh = new THREE.Mesh(geometry, material);
    camera.position.z = geometry.boundingBox.size().z+300
    //stlMesh.translateY()
    scene.add(stlMesh);
});
© www.soinside.com 2019 - 2024. All rights reserved.