如何使用三个js使用体素生成器生成地形

时间:2017-05-15 10:44:01

标签: javascript for-loop three.js voxel

我见过voxel js,但似乎已经过时了,它使用了我不想使用的节点js。我想使用for循环生成简单的地形,并使用我的函数创建一个块。

这是我的功能:

function createBlock(block, x, y, z, top, bottom, front, back, left, right) {
    var geometry;
    var meshFaceMaterial;
    var mesh;
    var material;
    var blockObj = {};
    if (top == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].top)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z;
        mesh.position.x = x;
        mesh.position.y = y+5;
        mesh.rotation.x = (-90 * Math.PI)/180;
        blockObj.top = mesh;
    }
    if (bottom == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].bottom)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z;
        mesh.position.x = x;
        mesh.position.y = y-5;
        mesh.rotation.x = (90 * Math.PI)/180;
        blockObj.bottom = mesh;
    }
    if (back == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z-5;
        mesh.position.x = x;
        mesh.position.y = y;
        mesh.rotation.y = (180 * Math.PI)/180;
        blockObj.back = mesh;
    }
    if (right == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z;
        mesh.position.x = x+5;
        mesh.position.y = y;
        mesh.rotation.y = (90 * Math.PI)/180;
        blockObj.right = mesh;
    }
    if (left == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z;
        mesh.position.x = x-5;
        mesh.position.y = y;
        mesh.rotation.y = (-90 * Math.PI)/180;
        blockObj.left = mesh;
    }
    if (front == true) {
        geometry = new THREE.PlaneGeometry(1, 1);
        material = new THREE.MeshPhongMaterial({map: THREE.ImageUtils.loadTexture(blocks[block].side)});
        meshFaceMaterial = new THREE.MeshFaceMaterial(material);
        mesh = new THREE.Mesh(geometry, meshFaceMaterial);
        mesh.position.z = z+5;
        mesh.position.x = x;
        mesh.position.y = y;
        blockObj.front = mesh;
    }

    blockObjects.push(blockObj);

    return blockObj;
}

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果我理解你的问题,你就会要求循环来调用你在3轴x,y,z上的功能。

你可以这样做:

for (var i = 0; i < SIZEX; i++) {
  for (var j = 0; j < SIZEY; j++) {
    for (var k = 0; k < SIZEZ; k++) {
      createBlock(block, i, j, k, (k == SIZEZ-1), (k == 0), (j == SIZEY-1), (j == 0), (i == SIZEX-1), (i == 0));
    }
  }
}

此代码将以3维方式导航。 如果(k == SIZEZ-1)为真,则top将在您的函数中为true。所有其他人都一样。

我不知道block是什么。

我希望你正在寻找的东西。

答案 1 :(得分:1)

这是一种创建立方体并使用它们构建随机地形的算法。在这种情况下,我已将地形高度变化固定为最多比相邻立方体高一个立方体高度。我为每个立方体随机生成了一种绿色,但你可以明显地应用你想到的任何纹理。

var camera, scene, renderer;
    var mesh;

    var cubesize = 30;
    var landscape_width = 30;
    var landscape_length = 30;
    var heights = [];
    var camera_offset = cubesize * landscape_width *0.7;
    var camera_height = cubesize * landscape_width / 2;

    function init() {
        camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
        camera.position.set(0,camera_offset,camera_height);
        camera.up = new THREE.Vector3(0,0,1);
        camera.lookAt(new THREE.Vector3(0,0,0));
        scene = new THREE.Scene();

        geom = new THREE.CubeGeometry( cubesize, cubesize, cubesize );
        cubes = new THREE.Object3D();
        scene.add( cubes );

        var xoff = landscape_width * cubesize / 2;
        var yoff = landscape_length * cubesize / 2;
        for(var i=0; i<landscape_width; i++) heights[i,0] = 0;
        for(var j=0; j<landscape_length; j++) heights[0,j] = 0;

        for(var i=1; i<landscape_width; i++) {
            var h = heights[i-1,0];
            for(var j=1; j< landscape_length; j++ ) {
                var rand = Math.random();
                if(heights[i-1,j] == heights[i,j-1]) { // level ground, go up dn or stay
                    if(rand < 0.33) 
                        heights[i,j] = heights[i-1,j] - cubesize;
                    else if (rand > 0.66)
                        heights[i,j] = heights[i-1,j] + cubesize;
                    else 
                        heights[i,j] = heights[i-1,j];                            
                }
                else if(Math.abs(heights[i-1,j] - heights[i,j-1]) > cubesize) { // two edges are wide apart, split the difference
                    heights[i,j] = (heights[i-1,j] +heights[i,j-1])/2;
                }
                else {
                    if(rand > 0.5)
                        heights[i,j] = heights[i-1,j];
                    else 
                        heights[i,j] = heights[i,j-1];                            
                }

                var grayness = Math.random() * 0.5 + 0.25,
                    mat = new THREE.MeshBasicMaterial(),
                    cube = new THREE.Mesh( geom, mat );
                mat.color.setRGB( 0, grayness, 0 );
                cube.position.set( i*cubesize - xoff, j*cubesize - yoff, heights[i,j] );
                cubes.add( cube );                        
            }
        }

        renderer = new THREE.WebGLRenderer();
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );
        //
        window.addEventListener( 'resize', onWindowResize, false );
    }
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
    }
    var angle = 0;
    function animate() {
        angle += 0.5;
        var rads = angle * Math.PI /180;
        camera.position.set(Math.cos(rads)*camera_offset,Math.sin(rads)*camera_offset,camera_height);
        camera.lookAt(scene.position);
        requestAnimationFrame( animate );
        renderer.render( scene, camera );
    }

    init();

    animate();
body {
        margin: 0px;
        background-color: #000000;
        overflow: hidden;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.js"></script>