我通过合并一个曲面和两个平面在Three.Js中创建了一个形状。我已经使用MeshLambertMaterial作为材料。垂直平面和曲面连接完美。然而,水平面与曲线连接处存在明显的硬线。照明似乎没有对齐。我希望3个平面显示为具有平滑着色的一个对象。我做错了吗?
addShape() {
var radius =58, height=100, startAngle=THREE.Math.degToRad(0), endAngle=THREE.Math.degToRad(90), horizontalSegments=25, verticalSegments=25;
var width = radius * 2 * Math.PI;
var plane = new THREE.PlaneGeometry(width, height, horizontalSegments, verticalSegments);
var index = 0;
for(var i=0; i<=verticalSegments; i++) {
for(var j=0; j<=horizontalSegments; j++) {
var angle = startAngle + (j/horizontalSegments)*(endAngle - startAngle);
plane.vertices[index].z = radius * Math.cos(angle);
plane.vertices[index].x = radius * Math.sin(angle);
index++;
}
}
var material = new THREE.MeshLambertMaterial({color: 0xa2cddd, side: THREE.DoubleSide});
var mesh = new THREE.Object3D();
var curve = new THREE.Mesh(plane, material);
curve.rotation.z = THREE.Math.degToRad(-90)
var plane1 = new THREE.PlaneGeometry(height, height, horizontalSegments, verticalSegments);
var side1 = new THREE.Mesh(plane1, material);
side1.rotation.z = THREE.Math.degToRad(270)
side1.position.z = radius;
side1.position.x = -radius * 0.85;
var plane2 = new THREE.PlaneGeometry(height, height, 1, 1);
var side2 = new THREE.Mesh(plane2);
side2.rotation.y = THREE.Math.degToRad(90)
side2.position.x = radius * 1.0
side2.position.z = -radius * 0.8;
plane.mergeMesh(side1);
plane.mergeMesh(side2);
mesh.rotation.y = THREE.Math.degToRad(180);
mesh.add(curve);
this.mesh = mesh;
this.scene.add(mesh);
}
addLight() {
let light1 = new THREE.PointLight(0xffffff, 1, 200);
light1.position.set(0, 20, 10);
this.scene.add(light1);
let light2 = new THREE.AmbientLight(0x404040); // soft white light
this.scene.add(light2);
}
答案 0 :(得分:2)
首先,你必须计算顶点法线。请使用THREE.Geometry.computeVertexNormals
。
见THREE.Geometry
plane.computeVertexNormals();
更进一步,你可以简化一些事情,如果你在一个乐队中绘制THREE.PlaneGeometry
使用这个解决方案,你可以根据自己的喜好选择起始角度和结束角度,并且开始和结束时的平面将始终能够无缝连接到弯曲部分:
var radius = 58, height = 100,
startAngle = THREE.Math.degToRad(-20),
endAngle = THREE.Math.degToRad(110),
horSegs = 25, vertSegs = 25,
startLen = 100, endLen = 100;
var width = startLen + endLen + radius * (endAngle-startAngle);
var plane = new THREE.PlaneGeometry( width, height, horSegs+2, vertSegs);
var index = 0;
for (var i = 0; i <= vertSegs; i++) {
plane.vertices[index].z = radius * Math.cos(startAngle) + startLen * Math.sin(startAngle);
plane.vertices[index].x = radius * Math.sin(startAngle) - startLen * Math.cos(startAngle);
index++;
for (var j = 0; j <= horSegs; j++) {
var angle = startAngle + j / horSegs * (endAngle - startAngle);
plane.vertices[index].z = radius * Math.cos(angle);
plane.vertices[index].x = radius * Math.sin(angle);
index++;
}
plane.vertices[index].z = radius * Math.cos(endAngle) - endLen * Math.sin(endAngle);
plane.vertices[index].x = radius * Math.sin(endAngle) + endLen * Math.cos(endAngle);
index++;
}
plane.computeVertexNormals();
请参阅代码段:
class World {
constructor() {
this.scene = new THREE.Scene();
this.renderer = new THREE.WebGLRenderer();
this.renderer.setClearColor(0x000000);
document.body.appendChild(this.renderer.domElement);
this.resize();
// this.addCube();
this.addShape();
this.addLight();
requestAnimationFrame(this.render.bind(this));
window.addEventListener("resize", this.resize.bind(this));
}
update() {
if (this.cube) this.cube.rotation.y += 0.01;
if (this.mesh) this.mesh.rotation.y += 0.01;
}
addLight() {
let light1 = new THREE.PointLight(0xffffff, 1, 200);
light1.position.set(0, 20, 10);
this.scene.add(light1);
let light2 = new THREE.AmbientLight(0x404040); // soft white light
this.scene.add(light2);
}
addShape() {
var radius = 58, height = 100,
startAngle = THREE.Math.degToRad(-20),
endAngle = THREE.Math.degToRad(110),
horSegs = 25, vertSegs = 25,
startLen = 100, endLen = 100;
var width = startLen + endLen + radius * (endAngle-startAngle);
var plane = new THREE.PlaneGeometry( width, height, horSegs+2, vertSegs);
var index = 0;
for (var i = 0; i <= vertSegs; i++) {
plane.vertices[index].z = radius * Math.cos(startAngle) + startLen * Math.sin(startAngle);
plane.vertices[index].x = radius * Math.sin(startAngle) - startLen * Math.cos(startAngle);
index++;
for (var j = 0; j <= horSegs; j++) {
var angle = startAngle + j / horSegs * (endAngle - startAngle);
plane.vertices[index].z = radius * Math.cos(angle);
plane.vertices[index].x = radius * Math.sin(angle);
index++;
}
plane.vertices[index].z = radius * Math.cos(endAngle) - endLen * Math.sin(endAngle);
plane.vertices[index].x = radius * Math.sin(endAngle) + endLen * Math.cos(endAngle);
index++;
}
plane.computeVertexNormals();
var material = new THREE.MeshLambertMaterial({
color: 0xa2cddd,
side: THREE.DoubleSide
});
var mesh = new THREE.Object3D();
var curve = new THREE.Mesh(plane, material);
curve.rotation.z = THREE.Math.degToRad(-90);
mesh.add(curve);
this.mesh = mesh;
this.scene.add(mesh);
}
render() {
this.update();
requestAnimationFrame(this.render.bind(this));
this.renderer.render(this.scene, this.camera);
}
resize() {
this.camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
this.camera.position.z = 200;
this.renderer.setSize(window.innerWidth, window.innerHeight);
}
}
var _w = new World();
&#13;
<script src="https://threejs.org/build/three.min.js"></script>
&#13;