Package org.terasology.core.world.generator.facetProviders

Source Code of org.terasology.core.world.generator.facetProviders.HeightMapSurfaceHeightProvider

/*
* Copyright 2014 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.core.world.generator.facetProviders;

import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.terasology.asset.Assets;
import org.terasology.math.Rect2i;
import org.terasology.math.Region3i;
import org.terasology.math.TeraMath;
import org.terasology.math.Vector2i;
import org.terasology.math.Vector3i;
import org.terasology.rendering.assets.texture.Texture;
import org.terasology.world.chunks.ChunkConstants;
import org.terasology.world.generation.Border3D;
import org.terasology.world.generation.Facet;
import org.terasology.world.generation.FacetProvider;
import org.terasology.world.generation.GeneratingRegion;
import org.terasology.world.generation.Produces;
import org.terasology.world.generation.Requires;
import org.terasology.world.generation.facets.SeaLevelFacet;
import org.terasology.world.generation.facets.SurfaceHeightFacet;

import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.Set;

@Produces(SurfaceHeightFacet.class)
@Requires(@Facet(SeaLevelFacet.class))
public class HeightMapSurfaceHeightProvider implements FacetProvider {
    private static final Logger logger = LoggerFactory.getLogger(HeightMapSurfaceHeightProvider.class);
    private static final int MAX_HEIGHT = 256;

    private static float[][] heightmap;

    @Override
    public void setSeed(long seed) {
        logger.info("Reading height map..");

        Texture texture = Assets.getTexture("core:platec_heightmap");
        ByteBuffer[] bb = texture.getData().getBuffers();
        IntBuffer intBuf = bb[0].asIntBuffer();

        int width = texture.getWidth();
        int height = texture.getHeight();

        heightmap = new float[width][height];
        while (intBuf.position() < intBuf.limit()) {
            int pos = intBuf.position();
            int val = intBuf.get();
            heightmap[pos % width][pos / width] = val / (256 * 256 * 256 * 12.8f);
        }

        heightmap = shiftArray(rotateArray(heightmap), -50, -100);

    }

    @Override
    public void process(GeneratingRegion region) {
        Border3D border = region.getBorderForFacet(SurfaceHeightFacet.class);
        SurfaceHeightFacet facet = new SurfaceHeightFacet(region.getRegion(), border);

        Set<Vector3i> chunkCoordinates = Sets.newHashSet();
        for (Vector3i pos : border.expandTo3D(region.getRegion())) {
            chunkCoordinates.add(TeraMath.calcChunkPos(pos));
        }

        for (Vector3i chunkCoordinate : chunkCoordinates) {
            Vector3i minWorldPosForChunk = new Vector3i(ChunkConstants.SIZE_X * chunkCoordinate.x,
                    ChunkConstants.SIZE_Y * chunkCoordinate.y,
                    ChunkConstants.SIZE_Z * chunkCoordinate.z);
            Region3i chunkWorldRegion = Region3i.createFromMinAndSize(minWorldPosForChunk, ChunkConstants.CHUNK_SIZE);

            int hmX = (((chunkWorldRegion.minX() / chunkWorldRegion.sizeX()) % 512) + 512) % 512;
            int hmZ = (((chunkWorldRegion.minZ() / chunkWorldRegion.sizeZ()) % 512) + 512) % 512;

            double scaleFactor = 0.05 * MAX_HEIGHT;

            double p00 = heightmap[hmX][hmZ] * scaleFactor;
            double p10 = heightmap[(hmX - 1 + 512) % 512][(hmZ) % 512] * scaleFactor;
            double p11 = heightmap[(hmX - 1 + 512) % 512][(hmZ + 1 + 512) % 512] * scaleFactor;
            double p01 = heightmap[(hmX) % 512][(hmZ + 1 + 512) % 512] * scaleFactor;

            Rect2i worldRegion = Rect2i.createFromMinAndSize(chunkWorldRegion.minX(),
                    chunkWorldRegion.minZ(),
                    chunkWorldRegion.sizeX(),
                    chunkWorldRegion.sizeZ());

            for (Vector2i pos : worldRegion) {
                Vector3i localPos = TeraMath.calcBlockPos(new Vector3i(pos.x, 0, pos.y));
                int x = localPos.x;
                int z = localPos.z;
                //calculate avg height
                float interpolatedHeight = (float) lerp(x / (double) ChunkConstants.CHUNK_REGION.sizeX(), lerp(z / (double) ChunkConstants.CHUNK_REGION.sizeZ(), p10, p11),
                        lerp(z / (double) ChunkConstants.CHUNK_REGION.sizeZ(), p00, p01));

                if (facet.getWorldRegion().contains(pos)) {
                    facet.setWorld(pos, interpolatedHeight);
                }
            }
        }

        region.setRegionFacet(SurfaceHeightFacet.class, facet);

    }

    //helper functions for the Mapdesign until real mapGen is in
    public static float[][] rotateArray(float[][] array) {
        float[][] newArray = new float[array[0].length][array.length];
        for (int i = 0; i < newArray.length; i++) {
            for (int j = 0; j < newArray[0].length; j++) {
                newArray[i][j] = array[j][array[j].length - i - 1];
            }
        }
        return newArray;
    }

    public static float[][] shiftArray(float[][] array, int x, int y) {
        int size = array.length;
        float[][] newArray = new float[size][size];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                newArray[i][j] = array[(i + x + size) % size][(j + y + size) % size];
            }
        }
        return newArray;
    }

    private static double lerp(double t, double a, double b) {
        return a + fade(t) * (b - a)//not sure if i should fade t, needs a bit longer to generate chunks but is definately nicer
    }

    private static double fade(double t) {
        return t * t * t * (t * (t * 6 - 15) + 10);
    }
}
TOP

Related Classes of org.terasology.core.world.generator.facetProviders.HeightMapSurfaceHeightProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.