Package org.terasology.engine.subsystem.headless.renderer

Source Code of org.terasology.engine.subsystem.headless.renderer.HeadlessWorldRenderer$ChunkFrontToBackComparator

/*
* 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.engine.subsystem.headless.renderer;

import com.google.common.collect.Lists;
import org.terasology.config.Config;
import org.terasology.engine.ComponentSystemManager;
import org.terasology.logic.players.LocalPlayer;
import org.terasology.logic.players.LocalPlayerSystem;
import org.terasology.math.AABB;
import org.terasology.math.Region3i;
import org.terasology.math.Vector3i;
import org.terasology.monitoring.PerformanceMonitor;
import org.terasology.physics.bullet.BulletPhysics;
import org.terasology.physics.engine.PhysicsEngine;
import org.terasology.registry.CoreRegistry;
import org.terasology.rendering.cameras.Camera;
import org.terasology.rendering.opengl.DefaultRenderingProcess.StereoRenderState;
import org.terasology.rendering.world.Skysphere;
import org.terasology.rendering.world.ViewDistance;
import org.terasology.rendering.world.WorldRenderer;
import org.terasology.world.WorldProvider;
import org.terasology.world.chunks.ChunkConstants;
import org.terasology.world.chunks.ChunkProvider;
import org.terasology.world.chunks.RenderableChunk;

import javax.vecmath.Vector3f;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

public class HeadlessWorldRenderer implements WorldRenderer {

    private static final int MAX_CHUNKS = ViewDistance.MEGA.getChunkDistance().x * ViewDistance.MEGA.getChunkDistance().y * ViewDistance.MEGA.getChunkDistance().z;

    private WorldProvider worldProvider;
    private ChunkProvider chunkProvider;

    private Camera noCamera = new NullCamera();

    /* CHUNKS */
    private boolean pendingChunks;
    private final List<RenderableChunk> chunksInProximity = Lists.newArrayListWithCapacity(MAX_CHUNKS);
    private Vector3i chunkPos = new Vector3i();

    /* PHYSICS */
    // TODO: Remove physics handling from world renderer
    private final BulletPhysics bulletPhysics;

    private Config config;

    public HeadlessWorldRenderer(WorldProvider worldProvider, ChunkProvider chunkProvider, LocalPlayerSystem localPlayerSystem) {
        this.worldProvider = worldProvider;
        this.chunkProvider = chunkProvider;
        bulletPhysics = new BulletPhysics(worldProvider);

        localPlayerSystem.setPlayerCamera(noCamera);
        config = CoreRegistry.get(Config.class);
    }

    @Override
    public void onChunkLoaded(Vector3i pos) {

    }

    @Override
    public void onChunkUnloaded(Vector3i pos) {

    }

    @Override
    public Camera getActiveCamera() {
        return noCamera;
    }

    @Override
    public Camera getLightCamera() {
        return noCamera;
    }

    @Override
    public ChunkProvider getChunkProvider() {
        return chunkProvider;
    }

    @Override
    public WorldProvider getWorldProvider() {
        return worldProvider;
    }

    @Override
    public PhysicsEngine getBulletRenderer() {
        return bulletPhysics;
    }

    @Override
    public void setPlayer(LocalPlayer localPlayer) {
        // TODO Auto-generated method stub

    }

    @Override
    public void update(float delta) {

        worldProvider.processPropagation();

        // Free unused space
        PerformanceMonitor.startActivity("Update Chunk Cache");
        chunkProvider.completeUpdate();
        chunkProvider.beginUpdate();
        PerformanceMonitor.endActivity();

        PerformanceMonitor.startActivity("Update Close Chunks");
        updateChunksInProximity(false);
        PerformanceMonitor.endActivity();
    }

    @Override
    public void render(StereoRenderState mono) {
        // TODO Auto-generated method stub

    }

    @Override
    public void dispose() {
        worldProvider.dispose();

    }

    @Override
    public boolean pregenerateChunks() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void changeViewDistance(ViewDistance viewDistance) {
        // TODO Auto-generated method stub

    }

    @Override
    public float getDaylight() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getSunlightValue() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getBlockLightValue() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getRenderingLightValueAt(Vector3f vector3f) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getSunlightValueAt(Vector3f worldPos) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getBlockLightValueAt(Vector3f worldPos) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public float getSmoothedPlayerSunlightValue() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public boolean isHeadUnderWater() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public Vector3f getTint() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public float getTick() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public Skysphere getSkysphere() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isAABBVisible(AABB aabb) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public WorldRenderingStage getCurrentRenderStage() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public String getMetrics() {
        return "";
    }

    /**
     * Updates the list of chunks around the player.
     *
     * @param force Forces the update
     * @return True if the list was changed
     */
    public boolean updateChunksInProximity(boolean force) {
        Vector3i newChunkPos = calcCamChunkOffset();

        // TODO: This should actually be done based on events from the ChunkProvider on new chunk availability/old chunk removal
        boolean chunksCurrentlyPending = false;
        if (!newChunkPos.equals(chunkPos) || force || pendingChunks) {
            Vector3i viewingDistance = config.getRendering().getViewDistance().getChunkDistance();
            Region3i viewRegion = Region3i.createFromCenterExtents(newChunkPos, new Vector3i(viewingDistance.x / 2, viewingDistance.y / 2, viewingDistance.z / 2));
            if (chunksInProximity.size() == 0 || force || pendingChunks) {
                // just add all visible chunks
                chunksInProximity.clear();
                for (Vector3i chunkPosition : viewRegion) {
                    RenderableChunk c = chunkProvider.getChunk(chunkPosition);
                    if (c != null && worldProvider.getLocalView(c.getPosition()) != null) {
                        chunksInProximity.add(c);
                    } else {
                        chunksCurrentlyPending = true;
                    }
                }
            } else {
                Region3i oldRegion = Region3i.createFromCenterExtents(chunkPos, new Vector3i(viewingDistance.x / 2, viewingDistance.y / 2, viewingDistance.z / 2));

                Iterator<Vector3i> chunksForRemove = oldRegion.subtract(viewRegion);
                // remove
                while (chunksForRemove.hasNext()) {
                    Vector3i r = chunksForRemove.next();
                    RenderableChunk c = chunkProvider.getChunk(r);
                    if (c != null) {
                        chunksInProximity.remove(c);
                        c.disposeMesh();
                    }
                }

                // add
                for (Vector3i chunkPosition : viewRegion) {
                    RenderableChunk c = chunkProvider.getChunk(chunkPosition);
                    if (c != null && worldProvider.getLocalView(c.getPosition()) != null) {
                        chunksInProximity.add(c);
                    } else {
                        chunksCurrentlyPending = true;
                    }
                }
            }

            chunkPos.set(newChunkPos);
            pendingChunks = chunksCurrentlyPending;

            Collections.sort(chunksInProximity, new ChunkFrontToBackComparator());

            return true;
        }

        return false;
    }

    /**
     * Chunk position of the player.
     *
     * @return The player offset on the x-axis
     */
    private Vector3i calcCamChunkOffset() {
        return new Vector3i((int) (getActiveCamera().getPosition().x / ChunkConstants.SIZE_X),
                (int) (getActiveCamera().getPosition().y / ChunkConstants.SIZE_Y),
                (int) (getActiveCamera().getPosition().z / ChunkConstants.SIZE_Z));
    }

    private static float distanceToCamera(RenderableChunk chunk) {
        Vector3f result = new Vector3f((chunk.getPosition().x + 0.5f) * ChunkConstants.SIZE_X, 0, (chunk.getPosition().z + 0.5f) * ChunkConstants.SIZE_Z);

        Vector3f cameraPos = CoreRegistry.get(WorldRenderer.class).getActiveCamera().getPosition();
        result.x -= cameraPos.x;
        result.z -= cameraPos.z;

        return result.length();
    }

    private static class ChunkFrontToBackComparator implements Comparator<RenderableChunk> {

        @Override
        public int compare(RenderableChunk o1, RenderableChunk o2) {
            double distance = distanceToCamera(o1);
            double distance2 = distanceToCamera(o2);

            if (o1 == null) {
                return -1;
            } else if (o2 == null) {
                return 1;
            }

            if (distance == distance2) {
                return 0;
            }

            return distance2 > distance ? -1 : 1;
        }
    }

}
TOP

Related Classes of org.terasology.engine.subsystem.headless.renderer.HeadlessWorldRenderer$ChunkFrontToBackComparator

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.