【问题标题】:Three.js Rotate object on sphere radiusThree.js 在球体半径上旋转对象
【发布时间】:2014-07-30 15:25:29
【问题描述】:

我想根据object.position.set(x,y,z)在球体半径的末端设置物体

在球面上点坐标的典型数学公式中,我们有:

var x = radius * Math.cos(phi) * Math.cos(theta);
var y = radius * Math.cos(phi) * Math.sin(theta);
var z = radius * Math.cos(phi);

我用

var x = radius * Math.cos(angleZ) * Math.cos(angleX);
var y = radius * Math.cos(angleZ) * Math.sin(angleX);
var z = radius * Math.cos(angleZ);

我知道这是错误的,因为 thete 和 phi 不是这个角度 我如何连接这 3 个角度 angleX、angleY、angleZ 以将其转换为 phi 和 theta

在三个 js 中我有:

cylinderX.rotation.x = degToRad(angleX); 
cylinderX.rotation.y = degToRad(angleY);                    
cylinderX.rotation.z = degToRad(angleZ);
  • degToRad - 将 deg 更改为弧度的函数

在哪里

angleX is angle between y plane and z plane
angleY is angle between z plane and x plane
angleZ is angle between x plane and y plane 

phi和theta是不同的角度,因为theta是半径和平面之间的角度

我运行动画和对象的位置 (x,y,z) 并且它在球面上的位置是错误的

我该如何解决这个问题?

更具体地说,下面是我的代码和示例:

http://newdesignlive.neomedia.info/index.html

当汽车在所有轴 x、y、z 上以所有角度旋转时,我想在这个红色长方体的末端设置这个绿色立方体

在数组中:x[...], y[...], z[...] 你有角度值汽车(物体)如何在所有轴(X,Y,Z)上旋转;

我不知道如何将 angleX、angleZ、angleY 连接到“phi”和“theta”以在正确的位置 x、y、z 上设置“绿色立方体”,例如取决于半径 = 100;

在 animate.js 中,这是我在下面添加的所有代码

    var container, stats, camera, scene, renderer, object;          
    var mouseX = 0, mouseY = 0;

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

    var angleX=0, angleY=0, angleZ=0, G=0;
    var x;  var y; var z; 
    var times = [];

    x = ["0", "10", "20","30", "40", "50" ];                                
    y = ["0", "20", "40","60", "70", "80" ];    
    z = ["0", "30", "60","90", "120", "150"  ];     
    gX = ["1", "1.4", "0.7", "0.4", "1", "1.2", "0.5", "1.2", "1.4", "1.3", "1", "0.7" ];
    gY = ["1", "2", "1", "2", "1", "2", "3", "1.2", "1.4", "1.3", "1", "2" ];
    gZ = ["1", "2", "1", "2", "1", "2", "3", "1.2", "1.4", "1.3", "1", "2" ];   


    generateTimesForAngles();
    generateTimesForG();

    var currentTransform = 0;
    var currentStep = 0;
    var intervalTime = 20;
    var intervalTimeG = 50

    setInterval(transformAngleX,intervalTime);
    setInterval(transformAngleY,intervalTime);
    setInterval(transformAngleZ,intervalTime);
    setInterval(transformGX,intervalTimeG);
    setInterval(transformGY,intervalTimeG); 
    setInterval(transformGZ,intervalTimeG);             

    init();
    animate();          

    function setVectorDirection (position, gValue)
    {
        var gValue = document.getElementById('g').value;
        gValue = gValue*10;

        var direction = document.getElementById("VectorDirection");
        var position = direction.options[direction.selectedIndex].value;

        var darkMaterial = new THREE.MeshBasicMaterial( { color: 0x222222 } );
        var wireframeMaterial = new THREE.MeshBasicMaterial( { color: 0x222222, wireframe: true, transparent: true } );                 var multiMaterial = [ darkMaterial, wireframeMaterial ];


        var x;
        var y;              
        x = 120 + gValue - gValue/2; 
        y = 110;
    }

    function init(objectfilename, materialfilename) {

        renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setClearColor( 0xDEDEDE, 1 );

        container = document.createElement('div');
        document.body.appendChild(container);   
        container.appendChild( renderer.domElement )                    

        camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000 );
        camera.position.y = 200;
        camera.position.z = 0;
        camera.position.x = 400;


        controls = new THREE.OrbitControls( camera );
        controls.addEventListener( 'change', render );

        scene = new THREE.Scene();

        var gridHelper = new THREE.GridHelper( 500, 100 );      
        gridHelper.setColors(0xFFFFFF, 0xFFFFFF);               
        scene.add(gridHelper);


        var material = new THREE.LineBasicMaterial({
            color: 0x0000ff
            });

        var initColor = new THREE.Color( 0xFFFFFF );
        var initTexture = THREE.ImageUtils.generateDataTexture( 1, 1, initColor );

        var groundMaterial = new THREE.MeshPhongMaterial
        ( 
            { 
            color: 0xEDEDED, 
            specular: 0xEDEDED, 
            map: initTexture }
            );

        var groundTexture = THREE.ImageUtils.loadTexture
            ( 
                "red.jpg", 
                undefined, 
                function()
                { 
                    groundMaterial.map = groundTexture 
                } 
            );

        groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
        groundTexture.repeat.set( 25, 25 );
        groundTexture.anisotropy = 16;

        var backgroundmesh = new THREE.Mesh( new THREE.PlaneGeometry( 20000, 20000 ), groundMaterial );
        backgroundmesh.position.y = -200;
        backgroundmesh.rotation.x = - Math.PI / 2;
        backgroundmesh.receiveShadow = true;
        scene.add( backgroundmesh );

        setVectorDirection();

        light = new THREE.DirectionalLight(0xffffff);

        light.position.set(0, 100, 60);
        light.castShadow = true;
        light.shadowCameraLeft = -60;
        light.shadowCameraTop = -60;
        light.shadowCameraRight = 60;
        light.shadowCameraBottom = 60;
        light.shadowCameraNear = 1;
        light.shadowCameraFar = 10000;
        light.shadowBias = -.0001
        light.shadowMapWidth = light.shadowMapHeight = 1024;
        light.shadowDarkness = .7;
            scene.add(light);


        mesh1 = new THREE.Mesh( geometry, material );
        mesh1.position.set(100,100,100);
        scene.add( mesh1 );


        var geometry;

        loader = new THREE.JSONLoader();

        var material = new THREE.MeshLambertMaterial({
        map: THREE.ImageUtils.loadTexture('gtare.jpg'),   
        colorAmbient: [0.480000026226044, 0.480000026226044, 0.480000026226044],
        colorDiffuse: [0.480000026226044, 0.480000026226044, 0.480000026226044],
        colorSpecular: [0.8999999761581421, 0.8999999761581421, 0.8999999761581421]
            });

        mesh = new THREE.Mesh( geometry, material );
        scene.add( mesh );


        grotX = new THREE.Mesh( new THREE.CylinderGeometry( 0.4, 8, 8, 40, 1 ),new THREE.MeshBasicMaterial( { color: 0x458B00 } ));

        cylinderX = new THREE.Mesh(new THREE.BoxGeometry(10,10,10)/*THREE.CylinderGeometry(4, 4, 300, 50, 50, false)*/,new THREE.MeshBasicMaterial( { color: 0x458B00 } )); 

        cylinderY = new THREE.Mesh(new THREE.BoxGeometry(10,10,10/*4, 4, 300, 50, 50, false*/),new THREE.MeshBasicMaterial( { color: 0x01C5BB } )); 
        cylinderZ = new THREE.Mesh(new THREE.BoxGeometry(10,200,10/*4, 4, 300, 50, 50, false*/),new THREE.MeshBasicMaterial( { color: 0xFF0000 } ));


        scene.add(cylinderX);
        scene.add(cylinderY);
        scene.add(cylinderZ);

        loader.load('car.js', function (geometry, materials) {
            var material = new THREE.MeshLambertMaterial({
        map: THREE.ImageUtils.loadTexture('gtare.jpg'),   
        colorAmbient: [0.480000026226044, 0.480000026226044, 0.480000026226044],
        colorDiffuse: [0.480000026226044, 0.480000026226044, 0.480000026226044],
        colorSpecular: [0.8999999761581421, 0.8999999761581421, 0.8999999761581421]
            });

          mesh = new THREE.Mesh( geometry, material );

          mesh.receiveShadow = true;
          scene.add(mesh);
          render(); 
        });



    }


    function degToRad(degrees) {
        return degrees * Math.PI / 180.0;
    }

        function radToDeg(radians) {
        return parseInt(radians * 180.0 / Math.PI);
    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
        render();
    }

    function generateTimesForAngles() {
        var baseTime360 = 10000;
        for(i=0;i<z.length-1;i++) {
            var timeMiddle = 10000;
            times.push(timeMiddle);
        }
    }

    function generateTimesForG() {
        var baseTimeallG = 5000;
        for(i=0;i<g.length-1;i++) {
            var timeMiddleG = 240;
            times.push(timeMiddleG);
        }

    }

    function transformGX() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepGX = (gX[currentTransform+1]-gX[currentTransform]) / steps;


        if(currentStep<steps) {
            currentStep++;
            GX = +gX[currentTransform] + (+currentStep * +singleStepGX); 

        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            GX = gX[currentTransform];
        } else {
        }
    }

    function transformGY() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepGY = (gY[currentTransform+1]-gY[currentTransform]) / steps;


        if(currentStep<steps) {
            currentStep++;
            GY = +gY[currentTransform] + (+currentStep * +singleStepGY);

        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            GY = gY[currentTransform];
        } else {

        }
    }

    function transformGZ() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepGZ = (gZ[currentTransform+1]-gZ[currentTransform]) / steps;

        if(currentStep<steps) {
            currentStep++;
            GZ = +gZ[currentTransform] + (+currentStep * +singleStepGZ); // Pamiętaj o plusach!!!
        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            GZ = gZ[currentTransform];
        } else {
        }
    }

    function transformAngleX() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepAngle = (x[currentTransform+1]-x[currentTransform]) / steps;

        if(currentStep<steps) {
            currentStep++;
            angleX = +x[currentTransform] + (+currentStep * +singleStepAngle); 

        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            angleX = x[currentTransform];
        } else {

        }
    }

    function transformAngleY() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepAngle = (y[currentTransform+1]-y[currentTransform]) / steps;

        if(currentStep<steps) {
            currentStep++;
            angleY = +y[currentTransform] + (+currentStep * +singleStepAngle); 
        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            angleY = y[currentTransform];
        } else {

        }
    }

    function transformAngleZ() {
        var steps = times[currentTransform] / intervalTime;
        var singleStepAngle = (z[currentTransform+1]-z[currentTransform]) / steps;

        if(currentStep<steps) {
            currentStep++;
            angleZ = +z[currentTransform] + (+currentStep * +singleStepAngle); // Pamiętaj o plusach!!!

        } else if(currentTransform<times.length){
            currentStep = 0;
            currentTransform++;
            angleZ = z[currentTransform];
        } else {

        }
    }

    var i = 0;

    function animate() {

        i++;
        requestAnimationFrame( animate );

        var x = 100 * Math.sin(degToRad(angleX))* Math.cos(degToRad(angleY)); 
        var y = 100 * Math.sin(degToRad(angleX))* Math.sin(degToRad(angleY));
        var z = 100 * Math.cos(degToRad(angleX));   

        z = -z;
        cylinderX.position.set(x,y,z);  
        cylinderY.position.set(0, 0, 0);
        cylinderX.rotation.x = degToRad(angleX);
        cylinderX.rotation.y = degToRad(angleY);                    
        cylinderX.rotation.z = degToRad(angleZ);
        cylinderZ.rotation.x = degToRad(angleX);
        cylinderZ.rotation.y = degToRad(angleY);                    
        cylinderZ.rotation.z = degToRad(angleZ-90);     

        mesh.rotation.x = degToRad(angleX);     
        mesh.rotation.y = degToRad(angleY);
        mesh.rotation.z = degToRad(angleZ);
        render();
    }

    //renderowanie obiektów
    function render() {

        renderer.render( scene, camera );
    }           

【问题讨论】:

    标签: javascript three.js geometry


    【解决方案1】:

    我认为最简单的方法是将对象添加到父Object3D,然后将对象移动到一个上的适当距离(要匹配其表面的球体的半径) xyz 轴。将父对象添加到场景中并将其放置在要匹配的球体的中心(子对象现在应该落在与您使用的轴相交的球体上)。通过这样的设置,您可以旋转父对象以将对象定位在球体上。

    【讨论】:

    • 有人可以在这里举个例子吗?
    • 三个 JS 改变了它们的一些依赖项,打破了原来的 JS 小提琴(顺便说一句,这太棒了)。我更新了小提琴以包含新的资源位置----只是将这里留给可能希望使用此解决方案的其他人:jsfiddle.net/8nxn6/2
    猜你喜欢
    • 2019-07-12
    • 2014-12-24
    • 2017-02-21
    • 1970-01-01
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多