com.opengrave.og.base.Picking.java Source code

Java tutorial

Introduction

Here is the source code for com.opengrave.og.base.Picking.java

Source

/*
 * Copyright 2016 Nathan Howard
 * 
 * This file is part of OpenGrave
 * 
 * OpenGrave is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * OpenGrave is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with OpenGrave. If not, see <http://www.gnu.org/licenses/>.
 */
package com.opengrave.og.base;

import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.util.HashMap;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.opengl.GL20;

import com.opengrave.og.MainThread;
import com.opengrave.og.Util;
import com.opengrave.og.engine.Location;
import com.opengrave.og.engine.RenderView;
import com.opengrave.og.states.BaseState;
import com.opengrave.og.terrain.TerrainLayerNode;
import com.opengrave.og.util.Vector4f;

public class Picking {

    static HashMap<Long, Pickable> allPickables;
    static long lastInt = 0;

    public static void pickRender(BaseState s) {
        GL11.glClearColor(0, 0, 0, 0);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        allPickables = new HashMap<Long, Pickable>();
        lastInt = 1;
        MainThread.set2D();
        s.renderGuiForPicking();
    }

    public static void pickCleanup() {
        lastInt = 0;
        allPickables = null;
        GL11.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    }

    public static PickingResult pick(int x, int y) {
        PickingResult res = new PickingResult();
        Util.checkErr();
        ByteBuffer pixel = BufferUtils.createByteBuffer(32);
        Util.checkErr();
        GL11.glReadPixels(x, y, 1, 1, GL12.GL_BGRA, GL11.GL_UNSIGNED_BYTE, pixel);
        Util.checkErr();
        int b = byteToInt(pixel.get()), g = byteToInt(pixel.get()), r = byteToInt(pixel.get());
        Util.checkErr();
        long chosenL = r + (g << 8) + (b << 16) + (0 << 24);
        res.worldLoc = null;
        res.picked = allPickables.get(chosenL);
        if (chosenL != 0) {
            // Get collision point, either null for GUI or world co-ords
            FloatBuffer buf = BufferUtils.createFloatBuffer(1);
            Util.checkErr();
            GL11.glReadPixels(x, y, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, buf);
            Util.checkErr();
            float dist = buf.get();
            // Infinite distance (1f) means nothing was rendered there.
            if (dist != 1f) {
                if (res.picked.getContext() != null) {
                    RenderView context = res.picked.getContext();
                    FloatBuffer a = BufferUtils.createFloatBuffer(4);
                    Vector4f vec = Util.unproject(x, y, dist, context.getViewMatrix(),
                            context.getProjectionMatrix(), context.totalx, context.totaly, context.width,
                            context.height);
                    // GLU.gluUnProject(x, y, dist, viewM, projM, viewport, a);
                    res.worldLoc = new Location(vec);
                    res.worldLoc = res.worldLoc.add(context.getCam().getLocation());
                    if (res.picked instanceof TerrainLayerNode) {
                        res.worldLoc.setLayer(((TerrainLayerNode) res.picked).layerNum);
                    }
                }
            }
        }
        return res;

    }

    public static int byteToInt(byte f) {
        return f & 0xff;
    }

    public static void registerObject(int pid, RenderView context, Pickable t) {
        int r = (int) (lastInt % 256);
        int g = (int) ((lastInt >> 8) % 256);
        int b = (int) ((lastInt >> 16) % 256);
        int i = GL20.glGetUniformLocation(pid, "pickCol");
        if (i == -1) {
            return;
        }
        GL20.glUniform4f(i, r / 255f, g / 255f, b / 255f, 1f);
        allPickables.put(lastInt, t);
        lastInt++;
    }

}