我正在尝试创建一个带有方形底座的随机地形,它将导出为 .STL(和 3d 打印)。
我很难将每个单独的几何图形组合成一个网格。从表面上看,我的形状看起来不错,但是当我尝试 3d 打印 .STL 时,很明显在每个单独的几何图形合并后存在一些间隙。
目前,我首先创建顶部几何体,然后创建左、右、前、后和底部,最后将这些几何体合并为一个网格。
我现在的代码是:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>STL</title>
<style>
#container {
background: #000;
width: 800px;
height: 600px;
}
</style>
</head>
<body>
<input type="button" id="export" name="export" value="Export" />
<div id="container">
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script src="js/three.min.js"></script>
<script src="js/loaders/STLLoader.js"></script>
<script src="js/exporters/STLExporter.js"></script>
<script src="js/Detector.js"></script>
<script src="js/libs/stats.min.js"></script>
<script src="js/ImprovedNoise.js"></script>
<script src="js/blob/Blob.js"></script>
<script src="js/filesaver/FileSaver.js"></script>
<script src="js/controls/FirstPersonControls.js"></script>
<script>
$(document).ready(function() {
var mouseX, mouseY = 0;
var WIDTH = 800,
HEIGHT = 600;
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
var container = $('#container');
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 700;
var controls = new THREE.FirstPersonControls( camera );
controls.movementSpeed = 1000;
controls.lookSpeed = 0.1;
var exporter = new THREE.STLExporter();
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera( VIEW_ANGLE,
ASPECT,
NEAR,
FAR );
var scene = new THREE.Scene();
camera.position.z = 300;
renderer.setSize(WIDTH, HEIGHT);
var clock = new THREE.Clock();
animate();
container.append(renderer.domElement);
var sphereMaterial = new THREE.MeshLambertMaterial(
{
color: 0xCC0000
});
var worldWidth = 100, worldDepth = 100,
worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2;
var heightData = generateHeight( worldWidth, worldDepth );
camera.position.y = heightData[ 0] ;
var geometry = new THREE.PlaneGeometry( 300, 300, worldWidth - 1, worldDepth - 1 );
geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
geometry.vertices[ i ].y = heightData[ i ] * 2;
}
var leftGeometry = new THREE.PlaneGeometry(300, 1, worldWidth - 1, worldDepth - 1 );
for( var i = 0; i < worldWidth; i++ ) {
for( var j = 0; j < worldDepth; j++ ) {
var index = j * worldWidth + i;
if ( j == worldDepth-1 ) {
leftGeometry.vertices[index].y = geometry.vertices[index].y +1;
}
}
}
var rightGeometry = new THREE.PlaneGeometry(300, 1, worldWidth - 1, worldDepth - 1 );
for( var i = 0; i < worldWidth; i++ ) {
for( var j = 0; j < worldDepth; j++ ) {
var index = j * worldWidth + i;
if ( j == 0 ) {
rightGeometry.vertices[index].y = geometry.vertices[index].y + 1;
}
}
}
var topGeometry = new THREE.PlaneGeometry(1, 300, worldWidth - 1, worldDepth - 1 );
topGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
for( var i = 0; i < worldWidth; i++ ) {
for( var j = 0; j < worldDepth; j++ ) {
var index = j * worldWidth + i;
if ( i == 0 ) {
topGeometry.vertices[index].y = geometry.vertices[index].y+1;
}
}
}
var bottomGeometry = new THREE.PlaneGeometry(1, 300, worldWidth - 1, worldDepth - 1 );
bottomGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
for( var i = 0; i < worldWidth; i++ ) {
for( var j = 0; j < worldDepth; j++ ) {
var index = j * worldWidth + i;
if ( i == worldWidth-1 ) {
bottomGeometry.vertices[index].y = geometry.vertices[index].y+1;
}
}
}
var baseGeometry = new THREE.PlaneGeometry(300, 300, worldWidth - 1, worldDepth - 1 );
baseGeometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
// ------------------------------
var combined = new THREE.Geometry();
var meshA = new THREE.Mesh( geometry, new THREE.MeshNormalMaterial() );
var meshB = new THREE.Mesh( leftGeometry, new THREE.MeshNormalMaterial() );
var meshC = new THREE.Mesh( rightGeometry, new THREE.MeshNormalMaterial() );
var meshD = new THREE.Mesh( topGeometry, new THREE.MeshNormalMaterial() );
var meshE = new THREE.Mesh( bottomGeometry, new THREE.MeshNormalMaterial() );
var meshF = new THREE.Mesh( baseGeometry, new THREE.MeshNormalMaterial() );
meshB.position.z = worldHalfWidth+100;
meshB.position.y = 0;
meshC.position.y = 0;
meshC.position.z = -worldHalfWidth-100;
meshD.position.x = -worldHalfWidth-99;
meshE.position.x = worldHalfWidth+99;
THREE.GeometryUtils.merge(combined, meshA);
THREE.GeometryUtils.merge(combined, meshB);
THREE.GeometryUtils.merge(combined, meshC);
THREE.GeometryUtils.merge(combined, meshD);
THREE.GeometryUtils.merge(combined, meshE);
THREE.GeometryUtils.merge(combined, meshF);
var out = new THREE.Mesh( combined, new THREE.MeshBasicMaterial({
wireframe: true,
color: 'white'
}));
scene.add(out);
scene.add(camera);
var pointLight = new THREE.PointLight( 0xFFFFFF );
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.add(pointLight);
renderer.render(scene, camera);
function generateHeight( width, height ) {
var size = width * height, data = new Float32Array( size ),
perlin = new ImprovedNoise(), quality = 1, z = Math.random() * 100;
for ( var i = 0; i < size; i ++ ) {
data[ i ] = 0
}
for ( var j = 0; j < 4; j ++ ) {
for ( var i = 0; i < size; i ++ ) {
var x = i % width, y = ~~ ( i / width );
data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * quality * 1.75 );
}
quality *= 5;
}
return data;
}
function animate() {
requestAnimationFrame( animate );
render();
}
function render() {
controls.update( clock.getDelta() );
renderer.render( scene, camera );
camera.position.z = ( mouseX - camera.position.x ) * .6;
}
$("#export").click(function(){
var out = exporter.exportScene(scene);
var blob = new Blob([out], {type: 'text/plain'});
saveAs(blob, 'please work.stl');
});
$("#container").mousemove(function(event) {
mouseX = event.pageX;
mouseY = event.pageY;
});
});
</script>
</html>
我的问题是:除了使用 GeometryUtils.merge 函数之外,还有其他方法可以创建这种类型的形状吗?目前,输出形状无法 3d 打印,我想知道是不是因为形状合并后,最终的几何图形包含间隙。我不确定如何解决这个问题。