org.terasology.StaticCities.walls.TownWallRasterizer.java Source code

Java tutorial

Introduction

Here is the source code for org.terasology.StaticCities.walls.TownWallRasterizer.java

Source

/*
 * Copyright 2015 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.StaticCities.walls;

import com.google.common.math.DoubleMath;
import org.terasology.StaticCities.BlockTheme;
import org.terasology.StaticCities.DefaultBlockType;
import org.terasology.StaticCities.raster.*;
import org.terasology.StaticCities.surface.InfiniteSurfaceHeightFacet;
import org.terasology.commonworld.geom.Ramp;
import org.terasology.commonworld.heightmap.HeightMap;
import org.terasology.math.TeraMath;
import org.terasology.math.geom.LineSegment;
import org.terasology.world.chunks.CoreChunk;
import org.terasology.world.generation.Region;
import org.terasology.world.generation.WorldRasterizer;

import java.math.RoundingMode;

/**
 * Converts a {@link TownWall} into blocks
 */
public class TownWallRasterizer implements WorldRasterizer {

    private final BlockTheme blockTheme;

    public TownWallRasterizer(BlockTheme theme) {
        this.blockTheme = theme;
    }

    @Override
    public void generateChunk(CoreChunk chunk, Region chunkRegion) {
        TownWallFacet wallFacet = chunkRegion.getFacet(TownWallFacet.class);
        InfiniteSurfaceHeightFacet heightFacet = chunkRegion.getFacet(InfiniteSurfaceHeightFacet.class);
        RasterTarget target = new ChunkRasterTarget(chunk, blockTheme);
        HeightMap hm = new HeightMap() {

            @Override
            public int apply(int x, int z) {
                return TeraMath.floorToInt(heightFacet.getWorld(x, z));
            }
        };
        for (TownWall wall : wallFacet.getTownWalls()) {
            for (WallSegment seg : wall.getWalls()) {
                if (seg instanceof GateWallSegment) {
                    rasterGate(target, (GateWallSegment) seg, hm);
                }
                if (seg instanceof SolidWallSegment) {
                    rasterSolid(target, (SolidWallSegment) seg, hm);
                }
            }
        }
    }

    private void rasterSolid(RasterTarget target, SolidWallSegment element, HeightMap hm) {

        int x1 = element.getStart().getX();
        int z1 = element.getStart().getY();
        int y1 = hm.apply(x1, z1) + element.getWallHeight();
        int x2 = element.getEnd().getX();
        int z2 = element.getEnd().getY();
        int y2 = hm.apply(x2, z2) + element.getWallHeight();

        Ramp ramp = new Ramp(x1, y1, z1, x2, y2, z2);

        HeightMap topHm = new HeightMap() {

            @Override
            public int apply(int x, int z) {
                float y = ramp.getY(x, z);
                return DoubleMath.roundToInt(y, RoundingMode.HALF_UP);
            }
        };

        Pen pen = Pens.fill(target, hm, topHm, DefaultBlockType.TOWER_WALL);
        RasterUtil.drawLine(pen, new LineSegment(x1, z1, x2, z2));
    }

    private void rasterGate(RasterTarget target, GateWallSegment element, HeightMap terrain) {

        int x1 = element.getStart().getX();
        int z1 = element.getStart().getY();
        int y1 = terrain.apply(x1, z1) + element.getWallHeight();
        int x2 = element.getEnd().getX();
        int z2 = element.getEnd().getY();
        int y2 = terrain.apply(x2, z2) + element.getWallHeight();

        Ramp ramp = new Ramp(x1, y1, z1, x2, y2, z2);

        HeightMap hmTop = new HeightMap() {

            @Override
            public int apply(int x, int z) {
                float y = ramp.getY(x, z);
                return DoubleMath.roundToInt(y, RoundingMode.HALF_UP);
            }
        };

        HeightMap hmBottom = new HeightMap() {

            @Override
            public int apply(int x, int z) {
                int top = hmTop.apply(x, z);
                int minHeight = element.getWallHeight() / 3;

                float l = ramp.getLambda(x, z);

                // dist is max. at 0.5 * width
                float zig = Math.abs(0.5f - l);
                float arc = zig * zig * 4; // applying the sqr makes 0.25 the max. So we multiply with 4

                int base = TeraMath.floorToInt((top - minHeight) * (1 - arc));
                return base;
            }
        };

        Pen pen = Pens.fill(target, hmBottom, hmTop, DefaultBlockType.TOWER_WALL);
        RasterUtil.drawLine(pen, new LineSegment(x1, z1, x2, z2));
    }

    @Override
    public void initialize() {
        // nothing to do
    }

}