com.a2client.corex.Camera.java Source code

Java tutorial

Introduction

Here is the source code for com.a2client.corex.Camera.java

Source

/*
 * This file is part of the Origin-World game client.
 * Copyright (C) 2013 Arkadiy Fattakhov <ark@ark.su>
 *
 * This program 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, version 3 of the License.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.a2client.corex;

import com.a2client.util.Vec2i;
import org.lwjgl.opengl.GL11;

public class Camera {
    public enum CAMERA_MODE {
        cmFree, cmTarget, cmLookAt
    }

    /**
     *  
     */
    public CAMERA_MODE mode = CAMERA_MODE.cmFree;

    /**
     * ? ?? ?  - ?
     */
    public boolean is_projection_persp = true;

    /**
     * ?
     */
    public Vec3f pos = new Vec3f();

    /**
     *   ? 
     */
    public Vec3f target = new Vec3f();

    /**
     * 
     */
    public Vec3f angle = new Vec3f();

    /**
     * ??
     */
    public float dist = 0;

    /**
     * ?       ?  ?
     * (    ?  ?)
     */
    public Vec2i offset_2d = new Vec2i(-1, -1);

    public float FOV = 0;

    public float ZNear = 0;

    public float ZFar = 0;

    /**
     *  
     */
    public Vec4f[] planes = new Vec4f[6];

    public Mat4f ViewMatrix = new Mat4f();

    public Mat4f ProjMatrix = new Mat4f();

    public Mat4f ViewProjMatrix = new Mat4f();

    public void Init() {
        Init(CAMERA_MODE.cmFree, true);
    }

    public void Init(CAMERA_MODE mode, boolean is_persp) {
        this.mode = mode;
        this.is_projection_persp = is_persp;
        FOV = 45;
        ZNear = 0.1f;
        ZFar = 100f;
        dist = 0;

        for (int i = 0; i < planes.length; i++) {
            planes[i] = new Vec4f();
        }
    }

    public void UpdateMatrix() {
        ViewMatrix.identity();
        switch (mode) {
        case cmFree:
            ViewMatrix = ViewMatrix.rotate(angle.z, new Vec3f(0, 0, 1));
            ViewMatrix = ViewMatrix.rotate(angle.x, new Vec3f(1, 0, 0));
            ViewMatrix = ViewMatrix.rotate(angle.y, new Vec3f(0, 1, 0));
            ViewMatrix = ViewMatrix.translate(pos.mul(-1));
            break;
        case cmTarget:
            ViewMatrix.setPos(new Vec3f(0, 0, -dist));
            ViewMatrix = ViewMatrix.rotate(angle.z, new Vec3f(0, 0, 1));
            ViewMatrix = ViewMatrix.rotate(angle.x, new Vec3f(1, 0, 0));
            ViewMatrix = ViewMatrix.rotate(angle.y, new Vec3f(0, 1, 0));
            ViewMatrix = ViewMatrix.translate(pos.mul(-1));
            break;
        case cmLookAt:
            ViewMatrix.lookat(pos, target, new Vec3f(0, 1, 0));
        }

        Rect vp = Render.getViewport();
        if (is_projection_persp) {
            ProjMatrix.perspective2(FOV, (float) vp.left, (float) vp.right, (float) vp.top, (float) vp.bottom,
                    ZNear, ZFar, offset_2d.x, offset_2d.y);
        } else {
            if (offset_2d.x < 0) {
                //                ProjMatrix.ortho(-1, 1, -1, 1, ZNear, ZFar); // original
                ProjMatrix.ortho(-1 * dist, 1 * dist, -1 * dist, 1 * dist, ZNear, ZFar);
            } else {
                float dx = -2 * ((float) (offset_2d.x) / (vp.right - vp.left));
                float dy = -2 * (1 - ((float) offset_2d.y) / (vp.bottom - vp.top));
                ProjMatrix.ortho(dx * dist, (2 + dx) * dist, dy * dist, (2 + dy) * dist, ZNear, ZFar);
            }
        }

        ViewProjMatrix = ProjMatrix.mul(ViewMatrix);
    }

    public void UpdatePlanes() {
        Mat4f m = ViewProjMatrix;
        Plane(planes[0], m.e30 - m.e00, m.e31 - m.e01, m.e32 - m.e02, m.e33 - m.e03); // right
        Plane(planes[1], m.e30 + m.e00, m.e31 + m.e01, m.e32 + m.e02, m.e33 + m.e03); // left
        Plane(planes[2], m.e30 - m.e10, m.e31 - m.e11, m.e32 - m.e12, m.e33 - m.e13); // top
        Plane(planes[3], m.e30 + m.e10, m.e31 + m.e11, m.e32 + m.e12, m.e33 + m.e13); // bottom
        Plane(planes[4], m.e30 - m.e20, m.e31 - m.e21, m.e32 - m.e22, m.e33 - m.e23); // near
        Plane(planes[5], m.e30 + m.e20, m.e31 + m.e21, m.e32 + m.e22, m.e33 + m.e23); // far
    }

    private void Plane(Vec4f p, float x, float y, float z, float w) {
        float len = (float) (1 / Math.sqrt(x * x + y * y + z * z));
        p.x = x * len;
        p.y = y * len;
        p.z = z * len;
        p.w = w * len;
    }

    public void Setup() {
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadMatrix(ProjMatrix.getBuf());

        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadMatrix(ViewMatrix.getBuf());

        Mat4f m = ViewMatrix.inverse();
        Render.view_pos = m.getPos();
    }

    /**
     *     ?
     *
     * @param b  
     * @return
     */
    public boolean Visible(Box b) {
        for (Vec4f p : planes) {
            if (p.dot(b.max) < 0 && p.dot(new Vec3f(b.min.x, b.max.y, b.max.z)) < 0
                    && p.dot(new Vec3f(b.max.x, b.min.y, b.max.z)) < 0
                    && p.dot(new Vec3f(b.min.x, b.min.y, b.max.z)) < 0
                    && p.dot(new Vec3f(b.max.x, b.max.y, b.min.z)) < 0
                    && p.dot(new Vec3f(b.min.x, b.max.y, b.min.z)) < 0
                    && p.dot(new Vec3f(b.max.x, b.min.y, b.min.z)) < 0 && p.dot(b.min) < 0)
                return false;
        }

        return true;
    }

    public boolean Visible(TSphere s) {
        for (Vec4f p : planes) {
            if (p.dot(s.center) < -s.radius)
                return false;
        }
        return true;
    }

}