首页 > 解决方案 > 如何焊接物体并添加鳍状物体 THREE.js

问题描述

我正在制作一个围绕环绕某些行星等的火箭飞船旋转的场景。

我首先从创建自己的火箭飞船对象开始。我正在尝试重新创建一个看起来与此类似的模型https://kyleagnew.files.wordpress.com/2018/02/lowpolyrocket5.jpg

这是我创建的当前模型https://jsfiddle.net/pfya1sjm/4/

从我的模型可以看出,它由许多使用 y 轴创建并相互对齐的对象组成。这也意味着对象看起来并不完全平滑,因为您可以看到它们之间的所有线条。有没有办法可以避免这种情况或将所有物体焊接在一起,使它们成为一个光滑的物体?

另外,对于问题的第二部分,我怎样才能创建伸出火箭底部的鳍状物体?如我试图重制的示例所示。

<------------------------编辑------------- ->

// once everything is loaded, we run our Three.js stuff.
            $(function() {

                var stats = initStats();

                // create a scene, that will hold all our elements such as objects, cameras and lights.
                var scene = new THREE.Scene();

                // create a camera, which defines where we're looking at.
                var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

                // create a render and set the size
                var renderer = new THREE.WebGLRenderer();

                renderer.setClearColor(0xEEEEEE, 1.0);
                renderer.setSize(window.innerWidth, window.innerHeight);
                renderer.shadowMap.enabled = true;

                window.addEventListener('resize', function()
            {
                var width = window.innerWidth;
                var height = window.innerHeight;
                renderer.setSize(width, height);
                camera.aspect = width / height;
                camera.updateProjectionMatrix();

            } );

            controls = new THREE.OrbitControls(camera, renderer.domElement);

            // create the object group that contains all the sub-shapes
            var rocketGroup = new THREE.Object3D();
            scene.add(rocketGroup);

            var rocketMaterial = new THREE.MeshLambertMaterial({color: 0xEEEEEE});
            var hingeMaterial = new THREE.MeshLambertMaterial({color: 0xFD1414});
            /////////////////////////////////////////////////////////////////////////////////////////
            var rocketAntennaOne = new THREE.CylinderGeometry( 0, 2, 2, 11 );   
            var rocketAntennaOneMesh = new THREE.Mesh(rocketAntennaOne, hingeMaterial, new THREE.MeshPhongMaterial());            
            var rocketAntennaTwo = new THREE.CylinderGeometry( 2, 3, 1, 11 );            
            var rocketAntennaTwoMesh = new THREE.Mesh(rocketAntennaTwo, hingeMaterial, new THREE.MeshPhongMaterial());
            var rocketAntennaThree = new THREE.CylinderGeometry( 3, 4, 1, 11 );
            var rocketAntennaThreeMesh = new THREE.Mesh( rocketAntennaThree,hingeMaterial, new THREE.MeshPhongMaterial());
            /////////////////////////////////////////////////////////////////////////////////////////
            var rocketBodyOne = new THREE.CylinderGeometry( 4, 8, 6, 11 );   
            var rocketBodyOneMesh = new THREE.Mesh(rocketBodyOne,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyTwo = new THREE.CylinderGeometry( 8, 11, 6, 11 );   
            var rocketBodyTwoMesh = new THREE.Mesh(rocketBodyTwo,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyThree = new THREE.CylinderGeometry( 11, 14, 6, 11 );   
            var rocketBodyThreeMesh = new THREE.Mesh(rocketBodyThree,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyFour = new THREE.CylinderGeometry( 14, 15, 6, 11 );   
            var rocketBodyFourMesh = new THREE.Mesh(rocketBodyFour,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyFive = new THREE.CylinderGeometry( 15, 16, 6, 11 );   
            var rocketBodyFiveMesh = new THREE.Mesh(rocketBodyFive,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodySix = new THREE.CylinderGeometry( 16, 16, 7, 11 );   
            var rocketBodySixMesh = new THREE.Mesh(rocketBodySix,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodySeven = new THREE.CylinderGeometry( 16, 15, 6, 11 );   
            var rocketBodySevenMesh = new THREE.Mesh(rocketBodySeven,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyEight = new THREE.CylinderGeometry( 15, 14, 6, 11 ); 
            var rocketBodyEightMesh = new THREE.Mesh(rocketBodyEight,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyNine = new THREE.CylinderGeometry( 14, 13, 6, 11 ); 
            var rocketBodyNineMesh = new THREE.Mesh(rocketBodyNine,rocketMaterial, new THREE.MeshPhongMaterial());
            var rocketBodyTen = new THREE.CylinderGeometry( 13, 12, 6, 11 ); 
            var rocketBodyTenMesh = new THREE.Mesh(rocketBodyTen,rocketMaterial, new THREE.MeshPhongMaterial());
            /////////////////////////////////////////////////////////////////////////////////////////            
            var rocketBodyUpper = new THREE.CylinderGeometry( 7, 8, 7, 10 );
            var rocketBodyUpperMesh = new THREE.Mesh(rocketBodyUpper,rocketMaterial, new THREE.MeshPhongMaterial());            
            /////////////////////////////////////////////////////////////////////////////////////////            
            var rocketBodyLower = new THREE.CylinderGeometry( 5.5, 6, 5, 10 );
            var rocketBodyLowerMesh = new THREE.Mesh(rocketBodyLower,rocketMaterial, new THREE.MeshPhongMaterial());



            //////////////////////////////////////
            scene.add(rocketAntennaOneMesh);
            scene.add(rocketAntennaTwoMesh);
            scene.add(rocketAntennaThreeMesh);
            /////////////////////////////////////
            scene.add(rocketBodyOneMesh);
            scene.add(rocketBodyTwoMesh);  
            scene.add(rocketBodyThreeMesh);  
            scene.add(rocketBodyFourMesh);  
            scene.add(rocketBodyFiveMesh);  
            scene.add(rocketBodySixMesh);
            scene.add(rocketBodySevenMesh);  
            scene.add(rocketBodyEightMesh);
            scene.add(rocketBodyNineMesh);  
            scene.add(rocketBodyTenMesh);
            ///////////////////////////////////////
            scene.add(rocketBodyUpperMesh);
            scene.add(rocketBodyUpperMesh);

            //Specify the position of the rocket cone
            rocketAntennaOneMesh.position.y = 74;
            rocketAntennaTwoMesh.position.y = 72.5;
            rocketAntennaThreeMesh.position.y = 71.5;
            rocketBodyOneMesh.position.y = 68;
            rocketBodyTwoMesh.position.y = 62;
            rocketBodyThreeMesh.position.y = 56;
            rocketBodyFourMesh.position.y = 50;
            rocketBodyFiveMesh.position.y = 44;
            rocketBodySixMesh.position.y = 37.5;
            rocketBodySevenMesh.position.y = 31;
            rocketBodyEightMesh.position.y = 25;
            rocketBodyNineMesh.position.y = 19;
            rocketBodyTenMesh.position.y = 13;


            rocketBodyUpperMesh.position.y = 10;
            rocketBodyLowerMesh.position.y = 7;


            //Add the rocketCone to the lowpolyRocket group
            rocketGroup.add(rocketAntennaOneMesh);
            rocketGroup.add(rocketAntennaTwoMesh);
            rocketGroup.add(rocketAntennaTwoMesh);
            /////////////////////////////////////////
            rocketGroup.add(rocketBodyOneMesh);
            rocketGroup.add(rocketBodyTwoMesh);
            rocketGroup.add(rocketBodyThreeMesh);
            rocketGroup.add(rocketBodyFourMesh);
            rocketGroup.add(rocketBodyFiveMesh);
            rocketGroup.add(rocketBodySixMesh);
            rocketGroup.add(rocketBodySevenMesh);
            rocketGroup.add(rocketBodyEightMesh);
            rocketGroup.add(rocketBodyNineMesh);
            rocketGroup.add(rocketBodyTenMesh);
            //////////////////////////////////////////
            rocketGroup.add(rocketBodyUpperMesh);
            rocketGroup.add(rocketBodyLowerMesh);


                // create the ground plane
                var planeGeometry = new THREE.PlaneGeometry(60, 20);
                var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});
                var plane = new THREE.Mesh(planeGeometry, planeMaterial);
                plane.receiveShadow = true;

                // rotate and position the plane
                plane.rotation.x = -0.5 * Math.PI;
                plane.position.x = 15;

                // add the plane to the scene
                scene.add(plane);

                // position and point the camera to the center of the scene
                camera.position.x = -150;
                camera.position.y = 110;
                camera.position.z = 20;
                camera.lookAt(scene.position);

                // add subtle ambient lighting
                var ambientLight = new THREE.AmbientLight(0x0c0c0c);
                scene.add(ambientLight);

                // add spotlight for the shadows
                var spotLight = new THREE.SpotLight(0xffffff);
                spotLight.position.set(-70, 60, -10);
                spotLight.castShadow = true;
                scene.add(spotLight);

                // add the output of the renderer to the html element
                $("#WebGL-output").append(renderer.domElement);

                var controls = new function() {

                };


                // call the render function
                var angle = 0;
                render();

                function render() {

                }

                function initStats() {

                    var stats = new Stats();

                    stats.setMode(0); // 0: fps, 1: ms

                    // Align top-left
                    stats.domElement.style.position = 'absolute';
                    stats.domElement.style.left = '0px';
                    stats.domElement.style.top = '0px';

                    $("#Stats-output").append(stats.domElement);

                    return stats;
                }
            });

JSFiddle 代码:

// create a scene, that will hold all our elements such as objects, cameras and lights.
var scene = new THREE.Scene();

// create a camera, which defines where we're looking at.
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// create a render and set the size
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

window.addEventListener('resize', function() {
  var width = window.innerWidth;
  var height = window.innerHeight;
  renderer.setSize(width, height);
  camera.aspect = width / height;
  camera.updateProjectionMatrix();

});

controls = new THREE.OrbitControls(camera, renderer.domElement);

// create the object group that contains all the sub-shapes
var rocketGroup = new THREE.Object3D();
scene.add(rocketGroup);

var rocketMaterial = new THREE.MeshLambertMaterial({
  color: 0xEEEEEE
});
var hingeMaterial = new THREE.MeshLambertMaterial({
  color: 0xFD1414
});
/////////////////////////////////////////////////////////////////////////////////////////
var rocketAntennaOne = new THREE.CylinderGeometry(0, 2, 2, 11);
var rocketAntennaOneMesh = new THREE.Mesh(rocketAntennaOne, hingeMaterial, new THREE.MeshPhongMaterial());
var rocketAntennaTwo = new THREE.CylinderGeometry(2, 3, 1, 11);
var rocketAntennaTwoMesh = new THREE.Mesh(rocketAntennaTwo, hingeMaterial, new THREE.MeshPhongMaterial());
var rocketAntennaThree = new THREE.CylinderGeometry(3, 4, 1, 11);
var rocketAntennaThreeMesh = new THREE.Mesh(rocketAntennaThree, hingeMaterial, new THREE.MeshPhongMaterial());
/////////////////////////////////////////////////////////////////////////////////////////
var rocketBodyOne = new THREE.CylinderGeometry(4, 8, 6, 11);
var rocketBodyOneMesh = new THREE.Mesh(rocketBodyOne, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyTwo = new THREE.CylinderGeometry(8, 11, 6, 11);
var rocketBodyTwoMesh = new THREE.Mesh(rocketBodyTwo, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyThree = new THREE.CylinderGeometry(11, 14, 6, 11);
var rocketBodyThreeMesh = new THREE.Mesh(rocketBodyThree, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyFour = new THREE.CylinderGeometry(14, 15, 6, 11);
var rocketBodyFourMesh = new THREE.Mesh(rocketBodyFour, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyFive = new THREE.CylinderGeometry(15, 16, 6, 11);
var rocketBodyFiveMesh = new THREE.Mesh(rocketBodyFive, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodySix = new THREE.CylinderGeometry(16, 16, 7, 11);
var rocketBodySixMesh = new THREE.Mesh(rocketBodySix, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodySeven = new THREE.CylinderGeometry(16, 15, 6, 11);
var rocketBodySevenMesh = new THREE.Mesh(rocketBodySeven, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyEight = new THREE.CylinderGeometry(15, 14, 6, 11);
var rocketBodyEightMesh = new THREE.Mesh(rocketBodyEight, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyNine = new THREE.CylinderGeometry(14, 13, 6, 11);
var rocketBodyNineMesh = new THREE.Mesh(rocketBodyNine, rocketMaterial, new THREE.MeshPhongMaterial());
var rocketBodyTen = new THREE.CylinderGeometry(13, 12, 6, 11);
var rocketBodyTenMesh = new THREE.Mesh(rocketBodyTen, rocketMaterial, new THREE.MeshPhongMaterial());
/////////////////////////////////////////////////////////////////////////////////////////            
var rocketBodyUpper = new THREE.CylinderGeometry(7, 8, 7, 10);
var rocketBodyUpperMesh = new THREE.Mesh(rocketBodyUpper, rocketMaterial, new THREE.MeshPhongMaterial());
/////////////////////////////////////////////////////////////////////////////////////////            
var rocketBodyLower = new THREE.CylinderGeometry(5.5, 6, 5, 10);
var rocketBodyLowerMesh = new THREE.Mesh(rocketBodyLower, rocketMaterial, new THREE.MeshPhongMaterial());



//////////////////////////////////////
scene.add(rocketAntennaOneMesh);
scene.add(rocketAntennaTwoMesh);
scene.add(rocketAntennaThreeMesh);
/////////////////////////////////////
scene.add(rocketBodyOneMesh);
scene.add(rocketBodyTwoMesh);
scene.add(rocketBodyThreeMesh);
scene.add(rocketBodyFourMesh);
scene.add(rocketBodyFiveMesh);
scene.add(rocketBodySixMesh);
scene.add(rocketBodySevenMesh);
scene.add(rocketBodyEightMesh);
scene.add(rocketBodyNineMesh);
scene.add(rocketBodyTenMesh);
///////////////////////////////////////
scene.add(rocketBodyUpperMesh);
scene.add(rocketBodyUpperMesh);

//Specify the position of the rocket cone
rocketAntennaOneMesh.position.y = 74;
rocketAntennaTwoMesh.position.y = 72.5;
rocketAntennaThreeMesh.position.y = 71.5;
rocketBodyOneMesh.position.y = 68;
rocketBodyTwoMesh.position.y = 62;
rocketBodyThreeMesh.position.y = 56;
rocketBodyFourMesh.position.y = 50;
rocketBodyFiveMesh.position.y = 44;
rocketBodySixMesh.position.y = 37.5;
rocketBodySevenMesh.position.y = 31;
rocketBodyEightMesh.position.y = 25;
rocketBodyNineMesh.position.y = 19;
rocketBodyTenMesh.position.y = 13;


rocketBodyUpperMesh.position.y = 10;
rocketBodyLowerMesh.position.y = 7;


//Add the rocketCone to the lowpolyRocket group
rocketGroup.add(rocketAntennaOneMesh);
rocketGroup.add(rocketAntennaTwoMesh);
rocketGroup.add(rocketAntennaTwoMesh);
/////////////////////////////////////////
rocketGroup.add(rocketBodyOneMesh);
rocketGroup.add(rocketBodyTwoMesh);
rocketGroup.add(rocketBodyThreeMesh);
rocketGroup.add(rocketBodyFourMesh);
rocketGroup.add(rocketBodyFiveMesh);
rocketGroup.add(rocketBodySixMesh);
rocketGroup.add(rocketBodySevenMesh);
rocketGroup.add(rocketBodyEightMesh);
rocketGroup.add(rocketBodyNineMesh);
rocketGroup.add(rocketBodyTenMesh);
//////////////////////////////////////////
rocketGroup.add(rocketBodyUpperMesh);
rocketGroup.add(rocketBodyLowerMesh);


var ambientLight = new THREE.AmbientLight(0xcccccc, 0.4);
scene.add(ambientLight);

var pointLight = new THREE.PointLight(0xffffff, 0.8);
camera.add(pointLight);
scene.add(camera);



// position and point the camera to the center of the scene
camera.position.x = -140;
camera.position.y = 20;
camera.position.z = 30;
camera.lookAt(scene.position);

// game logic    
var update = function() {
  //cone.rotation.x += 0.01;
  //cone.rotation.y += 0.005;
};
// draw scene    
var render = function() {
  renderer.render(scene, camera);
};



// run game loop (update, render, repeat)
var GameLoop = function() {
  requestAnimationFrame(GameLoop);
  update();
  render();
};
GameLoop();
body {
  margin: 0;
}
<script type="text/javascript" src="https://threejs.org/build/three.js"></script>
<script type="text/javascript" src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script type="text/javascript" src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script type="text/javascript" src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>

<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>

标签: javascriptthree.js

解决方案


身体部分之间的边缘看起来很硬,因为匹配顶点的法线不同,并且以这种方式混合。

THREE.MeshPhongMaterial使用顶点法线进行边缘融合。如果一条边的两条法线相同,则两条边看起来会混合在一起。如果法线指向不同的方向,边缘会显得很硬。

你有几个选择:

  1. 编辑几何图形,使相交的边对它们的每个配对顶点共享相同的法向量值。

  2. 手动将几何图形合并到一个几何对象中,然后找出不同的法线,并将它们配置为使用相同的法线。

  3. THREE.Geometry使用或构建自定义几何定义THREE.BufferGeometry

我真的建议尝试选项 3,因为您可能需要使用它来定义您的“鳍”。您可能会变得棘手并弄清楚如何定位/缩放/倾斜原始网格以满足您的要求,但构建自定义几何体(在我看来)会容易得多。


推荐阅读