Three.js:值正确时,屏幕上的对象定位不准确

时间:2013-09-18 19:39:00

标签: javascript three.js

我正在构建不同形状的矩形行。它们都有不同的宽度和高度,但我已经从json对象(整数)中获取它们。

现在我需要将它们全部放在相同的高度,同时保持比例,然后将它们分批对齐。 E.g:

var data = [{width:724,height:234},{width:345,height:726},{width:853,height:320}];
var xpos = 0;

for (var i=0, s=data.length; i<s; i+=1) {
    var materialBlack = new THREE.MeshPhongMaterial({
        ambient: 0x1b1b1b,
        color: 0x1b1b1b,
        overdraw: false,
        side: THREE.DoubleSide
    });
    var geometry = new THREE.PlaneGeometry( 1, 1, 1, 1 );
    var object = new THREE.Mesh( geometry, materialBlack );
    var scaleFactor = 300/data[i].height; // 300 units height for all
    var scaledWidth = data[i].width*scaleFactor;
    var scaledHeight = data[i].height*scaleFactor;
    xpos += i==0 ? 0 : scaledWidth;
    object.scale.set( scaledWidth, scaledHeight, 1);
    object.position.set( xpos, 0, 0 );
    scene.add( object );
}

现在问题在于,大多数矩形整齐地坐在一起,而少数矩形向左或向右偏移一点。它不仅仅是一个单位,更像是整个矩形的八分之一。

当视觉结果关闭时,记录对象中的设定值会返回正确的值,并且它们都会相加。

我尝试过舍入比例值,但这并没有什么区别。它总是发生在相同的对象上。我在这里找不到一个模式。

这是代码中的一个例子,也许有人可以发现我身边明显的错误行为。我完全不知道如何发生这种情况。

的jsfiddle

这是一个小提琴。你需要webgl,我只加载jsfiddle徽标。但你会注意到闪烁线条的重叠。

http://jsfiddle.net/7t2AM/2/

更新

当我将“scaleFactor”更改为始终为1并将矩形对齐为未缩放的大小时,它们会正确对齐。我在我的智慧结束时,我没有得到,而大多数都正确显示,只有一些是抵消。

更新2

这是代码的更完整副本。在这里,我没有使用1x1进行矩形的初始缩放,而是使用最终需要的值创建它。但结果仍然相同。

$(document).ready( function () {
    Content.loadContent("en",function () {
        doStuff();
    });
});

var Config = {
    lang : "de",
    datahost : "http://localhost:3000/proxy?url=DATA_SOURCE_URL",
    imgproxy : "http://localhost:3000/imgproxy?url="
};

var objects = [];
var data;
var camera;
var scene;
var renderer;

function doStuff() {

    renderer = new THREE.WebGLRenderer({ antialias: true });
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 20000 )

    data = Content.data;

    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.domElement.style.position = 'absolute';
    camera.position.z = -1000;

    controls = new THREE.TrackballControls( camera );
    controls.addEventListener( 'change', render );
    controls.rotateSpeed = 0.5;
    controls.maxDistance = 8000;
    controls.target.set(0,0,-2000);

    var ambientLight = new THREE.AmbientLight(0xeeeeee);
    ambientLight.castShadow = true;
    ambientLight.shadowCameraNear = 200;
    ambientLight.shadowCameraFar = camera.far;
    ambientLight.shadowCameraFov = 50;
    ambientLight.shadowBias = -0.00022;
    ambientLight.shadowDarkness = 0.5;
    ambientLight.shadowMapWidth = 1024;
    ambientLight.shadowMapHeight = 1024;
    scene.add(ambientLight);

    document.getElementById( 'container' ).appendChild( renderer.domElement );

    for ( var i= 0; i<data.length; i++ ) {
        var texture = THREE.ImageUtils.loadTexture(( Config.imgproxy ? Config.imgproxy : "" ) + data[i]["node"]["img"]);
        texture.minFilter = THREE.LinearFilter;
        texture.magFilter = THREE.LinearFilter;

        var material = new THREE.MeshPhongMaterial({
            map: texture,
            overdraw: false,
            side: THREE.FrontSide
        });

        var width = parseInt(data[i]["node"]["img_width"]); // this is coming in as strings... sigh.
        var height = parseInt(data[i]["node"]["img_height"]);
        var scaleFactor = 300 / height;
        var geometry = new THREE.PlaneGeometry( width*scaleFactor, height*scaleFactor, 1, 1 );

        var object = new THREE.Mesh( geometry, material );
        object["nodeObject"] = data[i]["node"];

        scene.add( object );
        objects.push( object );
    }

    var xpos = 0;

    for ( var i = 0, l = objects.length; i < l; i ++ ) {
        var object = objects[i];
        var height = parseInt(objects[i]["nodeObject"]["img_height"]);
        var scaleFactor = 300 / height;
        objects[i].position.set(xpos,0,-4000);
        xpos += (parseInt(objects[i]["nodeObject"]["img_width"])*scaleFactor);
    }

    animate();
}

function animate() {
    requestAnimationFrame( animate );
    controls.update();
    render();
}

function render() {
    renderer.render( scene, camera );
}

var Content = {
    data : [],
    loadContent : function (lang,callback) {
        console.log("loading remote data");
        $.ajax(Config.datahost+"/"+lang+"/export/explore", {
            type : "GET",
            dataType : "json",
            success : function (data) {
                if (data["nodes"]) {
                    if (typeof data["nodes"]!=="array") {
                        if (typeof data["nodes"]==="object") {
                            Content.data = new Array();
                            for (var key in data["nodes"]) {
                                Content.data.push(data["nodes"][key]);
                            }
                        } else {
                            console.log("unable to read data. neither array nor object");
                        }
                    } else {
                        Content.data = data["nodes"];
                    }
                };
                if (typeof callback==="function") callback();
            },
            error : function (xhr,stat,err) {
                console.log("error loading data - status: "+stat+" msg: "+err);
            }
        })
    }
};

2 个答案:

答案 0 :(得分:2)

var width = parseInt( objects[ i ][ "nodeObject" ][ "img_width" ] ) * scaleFactor;

objects[ i ].position.set( xpos + ( width / 2 ), 0, 0 );

xpos += width;

http://jsfiddle.net/7t2AM/4/

此外,将来,请尝试提出对他人有帮助的问题。

答案 1 :(得分:1)

我认为问题是PlaneGeometry的大小是2,你期望它是1。

试试这个:

var geometry = new THREE.PlaneGeometry( 0.5, 0.5, 1, 1 );

此外,您只需创建一个几何体和材质,并在每个网格中重复使用它们。